4. What’s in a Name?
The term originally stood for “Asynchronous JavaScript
and XML”
5. What’s in a Name?
The term originally stood for “Asynchronous JavaScript
and XML”
But it doesn’t have to be asynchronous
6. What’s in a Name?
The term originally stood for “Asynchronous JavaScript
and XML”
But it doesn’t have to be asynchronous
Or involve XML
7. What’s in a Name?
The term originally stood for “Asynchronous JavaScript
and XML”
But it doesn’t have to be asynchronous
Or involve XML
Nowadays the term pretty much stands on its own
11. The Accidental Feature
It’s hard to change the Web
You need to get through standards committees
And it doesn’t really count until most browsers agree
12. The Accidental Feature
It’s hard to change the Web
You need to get through standards committees
And it doesn’t really count until most browsers agree
In 1999 Microsoft added an XMLHTTP ActiveX control
13. The Accidental Feature
It’s hard to change the Web
You need to get through standards committees
And it doesn’t really count until most browsers agree
In 1999 Microsoft added an XMLHTTP ActiveX control
Not to be outdone, Mozilla, Safari, and Opera copied
it, adding native XMLHttpRequest objects
14. The Accidental Feature
It’s hard to change the Web
You need to get through standards committees
And it doesn’t really count until most browsers agree
In 1999 Microsoft added an XMLHTTP ActiveX control
Not to be outdone, Mozilla, Safari, and Opera copied
it, adding native XMLHttpRequest objects
No one really knew what to do with it
23. Why the History Lesson?
Ajax was never really planned
Even today, the way it is used are is very
experimental
24. Why the History Lesson?
Ajax was never really planned
Even today, the way it is used are is very
experimental
Some uses, like Gmail and Google Maps, have been
amazing
25. Why the History Lesson?
Ajax was never really planned
Even today, the way it is used are is very
experimental
Some uses, like Gmail and Google Maps, have been
amazing
A lot more have been disastrous
26. Why the History Lesson?
Ajax was never really planned
Even today, the way it is used are is very
experimental
Some uses, like Gmail and Google Maps, have been
amazing
A lot more have been disastrous
Proceed with caution: a little Ajax goes a long way!
27. So What the Heck is it?
You can scroll from Edmond to Tulsa
and beyond without loading a Web page!
28. So What the Heck is it?
You can scroll from Edmond to Tulsa
and beyond without loading a Web page!
31. A Definition
Ajax is the process of
Using JavaScript to make a request to the server
32. A Definition
Ajax is the process of
Using JavaScript to make a request to the server
Using the results of that request to dynamically
modify the page the user is currently viewing
33. A Definition
Ajax is the process of
Using JavaScript to make a request to the server
Using the results of that request to dynamically
modify the page the user is currently viewing
This request is not a full page load that moves the user
to a new URL
36. The Upside
Ajax can improve the user experience
When used right, it sometimes makes Web applications
feel a bit more like desktop applications (think Gmail)
37. The Upside
Ajax can improve the user experience
When used right, it sometimes makes Web applications
feel a bit more like desktop applications (think Gmail)
It is generally faster
38. The Upside
Ajax can improve the user experience
When used right, it sometimes makes Web applications
feel a bit more like desktop applications (think Gmail)
It is generally faster
A full page load is expensive: full HTML, CSS,
JavaScript files, and typically several images
39. The Upside
Ajax can improve the user experience
When used right, it sometimes makes Web applications
feel a bit more like desktop applications (think Gmail)
It is generally faster
A full page load is expensive: full HTML, CSS,
JavaScript files, and typically several images
Ajax requests usually load a lot less
42. Many Downsides
Ajax interactions are usually much harder to debug
Everything happens in the background, so it’s hard to
see things go wrong
43. Many Downsides
Ajax interactions are usually much harder to debug
Everything happens in the background, so it’s hard to
see things go wrong
Badly planned Ajax actions can easily degrade the
interface experience instead of enhancing it
44. Many Downsides
Ajax interactions are usually much harder to debug
Everything happens in the background, so it’s hard to
see things go wrong
Badly planned Ajax actions can easily degrade the
interface experience instead of enhancing it
You lose addressability (a big advantage of the Web)
52. Rails has Ajax
Support Built-in
Rails added a slew of Ajax helpers many versions ago
At the time, they were very impressive
53. Rails has Ajax
Support Built-in
Rails added a slew of Ajax helpers many versions ago
At the time, they were very impressive
We’ve learned better ways (experimental remember?)
54. Rails has Ajax
Support Built-in
Rails added a slew of Ajax helpers many versions ago
At the time, they were very impressive
We’ve learned better ways (experimental remember?)
The helpers have fallen out of fashion
55. Rails has Ajax
Support Built-in
Rails added a slew of Ajax helpers many versions ago
At the time, they were very impressive
We’ve learned better ways (experimental remember?)
The helpers have fallen out of fashion
Rails is abandoning the old strategy in the next release
56. Rails has Ajax
Support Built-in
Rails added a slew of Ajax helpers many versions ago
At the time, they were very impressive
We’ve learned better ways (experimental remember?)
The helpers have fallen out of fashion
Rails is abandoning the old strategy in the next release
The helpers will be reworked, similar to what I am
going to show you
60. Unobtrusive JavaScript
Behavior (JavaScript) should be separated from
presentation (HTML and CSS)
We should progressively enhance pages with
functionality
Agents not supporting the advanced functionality are
just not enhanced
64. jQuery
Rails uses the Prototype and script.aculo.us libraries
I prefer jQuery
It makes it very easy to select pieces of a Web page
65. jQuery
Rails uses the Prototype and script.aculo.us libraries
I prefer jQuery
It makes it very easy to select pieces of a Web page
It helps you manipulate what you have selected
66. jQuery
Rails uses the Prototype and script.aculo.us libraries
I prefer jQuery
It makes it very easy to select pieces of a Web page
It helps you manipulate what you have selected
It handles events for you
67. jQuery
Rails uses the Prototype and script.aculo.us libraries
I prefer jQuery
It makes it very easy to select pieces of a Web page
It helps you manipulate what you have selected
It handles events for you
And it supports Ajax
70. jQuery Crash Course
Run when the DOM is ready: jQuery(function() { });
Select with CSS: $(‘form#data input.autofill’)
71. jQuery Crash Course
Run when the DOM is ready: jQuery(function() { });
Select with CSS: $(‘form#data input.autofill’)
Run on click: $(‘…’).click(function() { });
72. jQuery Crash Course
Run when the DOM is ready: jQuery(function() { });
Select with CSS: $(‘form#data input.autofill’)
Run on click: $(‘…’).click(function() { });
Run on submit: $(‘form’).submit(function() { });
73. jQuery Crash Course
Run when the DOM is ready: jQuery(function() { });
Select with CSS: $(‘form#data input.autofill’)
Run on click: $(‘…’).click(function() { });
Run on submit: $(‘form’).submit(function() { });
Change content: $(‘…’).html(content);
74. jQuery Crash Course
Run when the DOM is ready: jQuery(function() { });
Select with CSS: $(‘form#data input.autofill’)
Run on click: $(‘…’).click(function() { });
Run on submit: $(‘form’).submit(function() { });
Change content: $(‘…’).html(content);
Append content: $(‘…’).append(content);
76. $.ajax({
url: "http://ajaxapp.com/ajax_action",
type: "POST",
dataType: "html",
data: $('form').serialize(),
complete: function() {
// called when complete
},
success: function() {
// called when successful
},
error: function() {
// called when there is an error
}
});
Ajax With jQuery
jQuery gives you full control over how
the Ajax request is executed
77. $.ajax({
url: "http://ajaxapp.com/ajax_action",
type: "POST",
dataType: "html",
data: $('form').serialize(),
complete: function() {
// called when complete
},
success: function() {
// called when successful
},
error: function() {
// called when there is an error
}
});
Ajax With jQuery
jQuery gives you full control over how
the Ajax request is executed
78. $.ajax({
url: "http://ajaxapp.com/ajax_action",
type: "POST",
dataType: "html",
data: $('form').serialize(),
complete: function() {
// called when complete
},
success: function() {
// called when successful
},
error: function() {
// called when there is an error
}
});
Ajax With jQuery
jQuery gives you full control over how
the Ajax request is executed
79. $.ajax({
url: "http://ajaxapp.com/ajax_action",
type: "POST",
dataType: "html",
data: $('form').serialize(),
complete: function() {
// called when complete
},
success: function() {
// called when successful
},
error: function() {
// called when there is an error
}
});
Ajax With jQuery
jQuery gives you full control over how
the Ajax request is executed
80. $.ajax({
url: "http://ajaxapp.com/ajax_action",
type: "POST",
dataType: "html",
data: $('form').serialize(),
complete: function() {
// called when complete
},
success: function() {
// called when successful
},
error: function() {
// called when there is an error
}
});
Ajax With jQuery
jQuery gives you full control over how
the Ajax request is executed
83. Commenting via Ajax
Let’s take a working blog comment system and convert
it to use Ajax (when JavaScript is available)
84. Commenting via Ajax
Let’s take a working blog comment system and convert
it to use Ajax (when JavaScript is available)
There’s no advantage to having the user visit a create
action
85. Commenting via Ajax
Let’s take a working blog comment system and convert
it to use Ajax (when JavaScript is available)
There’s no advantage to having the user visit a create
action
We won’t lose addressability in this case
86. Commenting via Ajax
Let’s take a working blog comment system and convert
it to use Ajax (when JavaScript is available)
There’s no advantage to having the user visit a create
action
We won’t lose addressability in this case
The Ajax request will require less resources from our
controller and be more responsive for the user
87. An Article With Comments
This is a trivial blog like interface,
allowing users to comment on articles
88. An Article With Comments
This is a trivial blog like interface,
allowing users to comment on articles
89. A Full Page Refresh
We loaded a lot of content that didn’t change
just to add that little comment
90. A Full Page Refresh
We loaded a lot of content that didn’t change
just to add that little comment
91. A Full Page Refresh
We loaded a lot of content that didn’t change
just to add that little comment
92. A Full Page Refresh
We loaded a lot of content that didn’t change
just to add that little comment
94. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title><%= build_page_title yield(:page_title) %></title>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script>
<%= javascript_include_tag "application" %>
</head>
<body>
<%= flash_messages %>
<%= yield %>
</body>
</html>
Add JavaScript
I have loaded jQuery from Google and
my own JavaScript file
95. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title><%= build_page_title yield(:page_title) %></title>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script>
<%= javascript_include_tag "application" %>
</head>
<body>
<%= flash_messages %>
<%= yield %>
</body>
</html>
Add JavaScript
I have loaded jQuery from Google and
my own JavaScript file
96. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title><%= build_page_title yield(:page_title) %></title>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script>
<%= javascript_include_tag "application" %>
</head>
<body>
<%= flash_messages %>
<%= yield %>
</body>
</html>
Add JavaScript
I have loaded jQuery from Google and
my own JavaScript file
97. Prepare Form
I have added a little structure to the document
to assist me with the JavaScript manipulation
98. <h1><%= h @article.title %></h1>
<%= simple_format @article.body %>
<h2>Comments</h2>
<div id="comments">
<%= render @article.comments %>
</div>
<h3>Add a Comment</h3>
<% form_for @comment || @article.comments.build,
:html => {:id => "comment_form"} do |f| %>
<%= f.error_messages %>
<%= f.hidden_field :article_id %>
<%= f.label :author %><br>
<%= f.text_field :author, :size => 42 %><br>
<%= f.label :body, "Comment" %><br>
<%= f.text_area :body, :cols => 40, :rows => 5 %><br>
<%= f.submit "Comment" %>
<span class="ajax_message"> </span>
<% end %>
Prepare Form
I have added a little structure to the document
to assist me with the JavaScript manipulation
99. <h1><%= h @article.title %></h1>
<%= simple_format @article.body %>
<h2>Comments</h2>
<div id="comments">
<%= render @article.comments %>
</div>
<h3>Add a Comment</h3>
<% form_for @comment || @article.comments.build,
:html => {:id => "comment_form"} do |f| %>
<%= f.error_messages %>
<%= f.hidden_field :article_id %>
<%= f.label :author %><br>
<%= f.text_field :author, :size => 42 %><br>
<%= f.label :body, "Comment" %><br>
<%= f.text_area :body, :cols => 40, :rows => 5 %><br>
<%= f.submit "Comment" %>
<span class="ajax_message"> </span>
<% end %>
Prepare Form
I have added a little structure to the document
to assist me with the JavaScript manipulation
100. <h1><%= h @article.title %></h1>
<%= simple_format @article.body %>
<h2>Comments</h2>
<div id="comments">
<%= render @article.comments %>
</div>
<h3>Add a Comment</h3>
<% form_for @comment || @article.comments.build,
:html => {:id => "comment_form"} do |f| %>
<%= f.error_messages %>
<%= f.hidden_field :article_id %>
<%= f.label :author %><br>
<%= f.text_field :author, :size => 42 %><br>
<%= f.label :body, "Comment" %><br>
<%= f.text_area :body, :cols => 40, :rows => 5 %><br>
<%= f.submit "Comment" %>
<span class="ajax_message"> </span>
<% end %>
Prepare Form
I have added a little structure to the document
to assist me with the JavaScript manipulation
101. <h1><%= h @article.title %></h1>
<%= simple_format @article.body %>
<h2>Comments</h2>
<div id="comments">
<%= render @article.comments %>
</div>
<h3>Add a Comment</h3>
<% form_for @comment || @article.comments.build,
:html => {:id => "comment_form"} do |f| %>
<%= f.error_messages %>
<%= f.hidden_field :article_id %>
<%= f.label :author %><br>
<%= f.text_field :author, :size => 42 %><br>
<%= f.label :body, "Comment" %><br>
<%= f.text_area :body, :cols => 40, :rows => 5 %><br>
<%= f.submit "Comment" %>
<span class="ajax_message"> </span>
<% end %>
Prepare Form
I have added a little structure to the document
to assist me with the JavaScript manipulation
102. Build Ajax Request
We can pull the request details from the form,
but we have to do some manual interface work
103. jQuery(function() {
$('#comment_form').submit(function(event) {
event.preventDefault();
var f = $(this);
f.find('.ajax_message').html('Saving...');
f.find('input[type="submit"]').attr('disabled', true);
$.ajax({
url: f.attr('action'),
type: f.attr('method'),
dataType: "html",
data: f.serialize(),
complete: function() {
f.find('.ajax_message').html(' ');
f.find('input[type="submit"]').attr('disabled', false);
},
success: function(data, textStatus, xhr) {
$('#comments').append(data);
f.find('input[type="text"], textarea').val('');
},
error: function() {
alert('Please enter an author and comment.');
},
});
});
});
Build Ajax Request
We can pull the request details from the form,
but we have to do some manual interface work
104. jQuery(function() {
$('#comment_form').submit(function(event) {
event.preventDefault();
var f = $(this);
f.find('.ajax_message').html('Saving...');
f.find('input[type="submit"]').attr('disabled', true);
$.ajax({
url: f.attr('action'),
type: f.attr('method'),
dataType: "html",
data: f.serialize(),
complete: function() {
f.find('.ajax_message').html(' ');
f.find('input[type="submit"]').attr('disabled', false);
},
success: function(data, textStatus, xhr) {
$('#comments').append(data);
f.find('input[type="text"], textarea').val('');
},
error: function() {
alert('Please enter an author and comment.');
},
});
});
});
Build Ajax Request
We can pull the request details from the form,
but we have to do some manual interface work
105. jQuery(function() {
$('#comment_form').submit(function(event) {
event.preventDefault();
var f = $(this);
f.find('.ajax_message').html('Saving...');
f.find('input[type="submit"]').attr('disabled', true);
$.ajax({
url: f.attr('action'),
type: f.attr('method'),
dataType: "html",
data: f.serialize(),
complete: function() {
f.find('.ajax_message').html(' ');
f.find('input[type="submit"]').attr('disabled', false);
},
success: function(data, textStatus, xhr) {
$('#comments').append(data);
f.find('input[type="text"], textarea').val('');
},
error: function() {
alert('Please enter an author and comment.');
},
});
});
});
Build Ajax Request
We can pull the request details from the form,
but we have to do some manual interface work
106. jQuery(function() {
$('#comment_form').submit(function(event) {
event.preventDefault();
var f = $(this);
f.find('.ajax_message').html('Saving...');
f.find('input[type="submit"]').attr('disabled', true);
$.ajax({
url: f.attr('action'),
type: f.attr('method'),
dataType: "html",
data: f.serialize(),
complete: function() {
f.find('.ajax_message').html(' ');
f.find('input[type="submit"]').attr('disabled', false);
},
success: function(data, textStatus, xhr) {
$('#comments').append(data);
f.find('input[type="text"], textarea').val('');
},
error: function() {
alert('Please enter an author and comment.');
},
});
});
});
Build Ajax Request
We can pull the request details from the form,
but we have to do some manual interface work
107. jQuery(function() {
$('#comment_form').submit(function(event) {
event.preventDefault();
var f = $(this);
f.find('.ajax_message').html('Saving...');
f.find('input[type="submit"]').attr('disabled', true);
$.ajax({
url: f.attr('action'),
type: f.attr('method'),
dataType: "html",
data: f.serialize(),
complete: function() {
f.find('.ajax_message').html(' ');
f.find('input[type="submit"]').attr('disabled', false);
},
success: function(data, textStatus, xhr) {
$('#comments').append(data);
f.find('input[type="text"], textarea').val('');
},
error: function() {
alert('Please enter an author and comment.');
},
});
});
});
Build Ajax Request
We can pull the request details from the form,
but we have to do some manual interface work
109. class CommentsController < ApplicationController
def create
@comment = Comment.new(params[:comment])
if @comment.save
if request.xhr?
render @comment
else
flash[:notice] = "Comment added."
redirect_to article_path(@comment.article)
end
else
if request.xhr?
render :status => 403
else
flash[:error] = "Comment could not be added."
redirect_to article_path(@comment.article)
end
end
end
end
Respond to Ajax
Remember XMLHttpRequest (“xhr”)?
We respond with just the comment.
110. class CommentsController < ApplicationController
def create
@comment = Comment.new(params[:comment])
if @comment.save
if request.xhr?
render @comment
else
flash[:notice] = "Comment added."
redirect_to article_path(@comment.article)
end
else
if request.xhr?
render :status => 403
else
flash[:error] = "Comment could not be added."
redirect_to article_path(@comment.article)
end
end
end
end
Respond to Ajax
Remember XMLHttpRequest (“xhr”)?
We respond with just the comment.
111. class CommentsController < ApplicationController
def create
@comment = Comment.new(params[:comment])
if @comment.save
if request.xhr?
render @comment
else
flash[:notice] = "Comment added."
redirect_to article_path(@comment.article)
end
else
if request.xhr?
render :status => 403
else
flash[:error] = "Comment could not be added."
redirect_to article_path(@comment.article)
end
end
end
end
Respond to Ajax
Remember XMLHttpRequest (“xhr”)?
We respond with just the comment.
112. class CommentsController < ApplicationController
def create
@comment = Comment.new(params[:comment])
if @comment.save
if request.xhr?
render @comment
else
flash[:notice] = "Comment added."
redirect_to article_path(@comment.article)
end
else
if request.xhr?
render :status => 403
else
flash[:error] = "Comment could not be added."
redirect_to article_path(@comment.article)
end
end
end
end
Respond to Ajax
Remember XMLHttpRequest (“xhr”)?
We respond with just the comment.
113. Sending Ajax
I have provided some interface clues
so the user knows work is in progress
114. Sending Ajax
I have provided some interface clues
so the user knows work is in progress
115. Sending Ajax
I have provided some interface clues
so the user knows work is in progress
121. Mind the Details
With Ajax, you need to manage the interface details
122. Mind the Details
With Ajax, you need to manage the interface details
I added a “Saving…” indicator
123. Mind the Details
With Ajax, you need to manage the interface details
I added a “Saving…” indicator
I disabled the “Comment” button
124. Mind the Details
With Ajax, you need to manage the interface details
I added a “Saving…” indicator
I disabled the “Comment” button
I undid both of the above when the request finished
125. Mind the Details
With Ajax, you need to manage the interface details
I added a “Saving…” indicator
I disabled the “Comment” button
I undid both of the above when the request finished
I cleared the form for new entries
126. Mind the Details
With Ajax, you need to manage the interface details
I added a “Saving…” indicator
I disabled the “Comment” button
I undid both of the above when the request finished
I cleared the form for new entries
I showed a reasonable error message for failure