From 69e9715f792fae5134ae0a8666f54df6cdf118b3 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Tue, 23 Oct 2012 22:09:10 +0200 Subject: renames the JS guide file name to match the new title [ci skip] --- guides/source/working_with_javascript.md | 390 ---------------------- guides/source/working_with_javascript_in_rails.md | 390 ++++++++++++++++++++++ 2 files changed, 390 insertions(+), 390 deletions(-) delete mode 100644 guides/source/working_with_javascript.md create mode 100644 guides/source/working_with_javascript_in_rails.md (limited to 'guides') diff --git a/guides/source/working_with_javascript.md b/guides/source/working_with_javascript.md deleted file mode 100644 index ccd7e8a77d..0000000000 --- a/guides/source/working_with_javascript.md +++ /dev/null @@ -1,390 +0,0 @@ -Working With JavaScript in Rails -================================ - -This guide covers the built-in Ajax/JavaScript functionality of Rails (and -more); it will enable you to create rich and dynamic AJAX applications with -ease! We will cover the following topics: - -* Quick introduction to AJAX -* Unobtrusive JavaScript -* How Rails' built-in helpers assist you -* Handling AJAX on the server side -* The Turbolinks gem - -------------------------------------------------------------------------------- - -An introduction to AJAX ------------------------- - -In order to understand AJAX, you must first understand what a web browser does -normally. - -When you type `http://localhost:3000` into your browser's address bar and hit -'Go,' the browser (your 'client') makes a request to the server. It parses the -response, then fetches all associated assets, like JavaScript files, -stylesheets and images. It then assembles the page. If you click a link, it -does the same process: fetch the page, fetch the assets, put it all together, -show you the results. This is called the 'request response cycle.' - -JavaScript can also make requests to the server, and parse the response. It -also has the ability to update information on the page. Combining these two -powers, a JavaScript writer can make a web page that can update just parts of -itself, without needing to get the full page data from the server. This is a -powerful technique that we call AJAX. - -Rails ships with CoffeeScript by default, and so the rest of the examples -in this guide will be in CoffeeScript. All of these lessons, of course, apply -to vanilla JavaScript as well. - -As an example, here's some CoffeeScript code that makes an AJAX request using -the jQuery library: - -``` -$.ajax(url: "/test").done (html) -> - $("#results").append html -``` - -This code fetches data from "/test", and then appends the result to the `div` -with an id of `results`. - -Rails provides quite a bit of built-in support for building web pages with this -technique. You rarely have to write this code yourself. The rest of this guide -will show you how Rails can help you write web sites in this manner, but it's -all built on top of this fairly simple technique. - -Unobtrusive JavaScript -------------------------------------- - -Rails uses a technique called "Unobtrusive JavaScript" to handle attaching -JavaScript to the DOM. This is generally considered to be a best-practice -within the frontend community, but you may occasionally read tutorials that -demonstrate other ways. - -Here's the simplest way to write JavaScript. You may see it referred to as -'inline JavaScript': - -``` -Here -``` - -When clicked, the alert will trigger. Here's the problem: what happens when -we have lots of JavaScript we want to execute on a click? - -``` -Calculate -``` - -Awkward, right? We could pull the function definition out of the click handler, -and turn it into CoffeeScript: - -``` -fib = (n) -> - (if n < 2 then n else fib(n - 1) + fib(n - 2)) -``` - -And then on our page: - -``` -Calculate -``` - -That's a little bit better, but what about multiple links that have the same -effect? - -``` -Calculate -Calculate -Calculate -``` - -Not very DRY, eh? We can fix this by using events instead. We'll add a `data-*` -attribute to our link, and then bind a handler to the click event of every link -that has that attribute: - -``` -fib = (n) -> - (if n < 2 then n else fib(n - 1) + fib(n - 2)) - -$(document).ready -> - $("a[data-fib]").click (e) -> - count = $(this).data("fib") - alert "fib of #{count} is: #{fib(count)}." - -... later ... - -Calculate -Calculate -Calculate -``` - -We call this 'unobtrusive' JavaScript because we're no longer mixing our -JavaScript into our HTML. We've properly separated our concerns, making future -change easy. We can easily add behavior to any link by adding the data -attribute. We can run all of our JavaScript through a minimizer and -concatenator. We can serve our entire JavaScript bundle on every page, which -means that it'll get downloaded on the first page load and then be cached on -every page after that. Lots of little benefits really add up. - -The Rails team strongly encourages you to write your CoffeeScript (and -JavaScript) in this style, and you can expect that many libraries will also -follow this pattern. - -Built-in Helpers ----------------------- - -Rails provides a bunch of view helper methods written in Ruby to assist you -in generating HTML. Sometimes, you want to add a little AJAX to those elements, -and Rails has got your back in those cases. - -Because of Unobtrusive JavaScript, the Rails "AJAX helpers" are actually in two -parts: the JavaScript half and the Ruby half. -[rails.js](https://github.com/rails/jquery-ujs/blob/master/src/rails.js) -provides the JavaScript half, and the regular Ruby view helpers add appropriate -tags to your DOM. The CoffeeScript in rails.js then listens for these -attributes, and attaches appropriate handlers. - -### form_for - -[`form_for`](http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_for) -is a helper that assists with writing forms. `form_for` takes a `:remote` -option. It works like this: - -``` -<%= form_for(@post, remote: true) do |f| %> - ... -<% end %> -``` - -This will generate the following HTML: - -``` -
- ... -
-``` - -Note the `data-remote='true'`. Now, the form will be submitted by AJAX rather -than by the browser's normal submit mechanism. - -You probably don't want to just sit there with a filled out `
`, though. -You probably want to do something upon a successful submission. To do that, -bind to the `ajax:success` event. On failure, use `ajax:error`. Check it out: - -``` - -``` - -Obviously, you'll want to be a bit more sophisticated than that, but it's a -start. - -### form_tag - -[`form_tag`](http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html#method-i-form_tag) -is very similar to `form_for`. It has a `:remote` option that you can use like -this: - -``` -<%= form_tag('/posts', remote: true) %> -``` - -Everything else is the same as `form_for`. See its documentation for full -details. - -### link_to - -[`link_to`](http://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html#method-i-link_to) -is a helper that assists with generating links. It has a `:remote` option you -can use like this: - -``` -<%= link_to "first post", @post, remote: true %> -``` - -which generates - -``` -a post -``` - -You can bind to the same AJAX events as `form_for`. Here's an example. Let's -assume that we have a resource `/fib/:n` that calculates the `n`th Fibonacci -number. We would generate some HTML like this: - -<%= link_to "Calculate", "/fib/15", remote: true, data: { fib: 15 } %> - -and write some CoffeeScript like this: - -``` -$(document).ready -> - $("a[data-fib]").on "ajax:success", (e, data, status, xhr) -> - count = $(this).data("fib") - alert "fib of #{count} is: #{data}." -``` - -### button_to - -[`button_to`](http://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html#method-i-button_to) is a helper that helps you create buttons. It has a `:remote` option that you can call like this: - -``` -<%= button_to "A post", @post, remote: true %> -``` - -this generates - -``` - -
-``` - -Since it's just a `
`, all of the information on `form_for` also applies. - -Server side concerns --------------------- - -AJAX isn't just client-side, you also need to do some work on the server -side to support it. Often, people like their AJAX requests to return JSON -rather than HTML. Let's discuss what it takes to make that happen. - -### A Simple Example - -Imagine you have a series of users that you would like to display and provide a -form on that same page to create a new user. The index action of your -controller looks like this: - -``` -class UsersController < ApplicationController - def index - @users = User.all - @user = User.new - end - # ... -``` - -The index view (`app/views/users/index.html.erb`) contains: - -``` -Users - - - -
- -<%= form_for(@user, remote: true) do |f| %> - <%= f.label :name %>
- <%= f.text_field :name %> - <%= f.submit %> -<% end %> -``` - -The `app/views/users/_user.html.erb` partial contains the following: - -``` -
  • <%= user.name %>
  • -``` - -The top portion of the index page displays the users. The bottom portion -provides a form to create a new user. - -The bottom form will call the create action on the Users controller. Because -the form's remote option is set to true, the request will be posted to the -users controller as an AJAX request, looking for JavaScript. In order to -service that request, the create action of your controller would look like -this: - -``` - # app/controllers/users_controller.rb - # ...... - def create - @user = User.new(params[:user]) - - respond_to do |format| - if @user.save - format.html { redirect_to @user, notice: 'User was successfully created.' } - format.js {} - format.json { render json: @user, status: :created, location: @user } - else - format.html { render action: "new" } - format.json { render json: @user.errors, status: :unprocessable_entity } - end - end - end -``` - -Notice the format.js in the respond_to block; that allows the controller to -respond to your AJAX request. You then have a corresponding -`app/views/users/create.js.erb` view file that generates the actual JavaScript -code that will be sent and executed on the client side. - -``` -$("<%= escape_javascript(render @user) %>").appendTo("#users"); -``` - -Turbolinks ----------- - -Rails 4 ships with the [Turbolinks gem](https://github.com/rails/turbolinks). -This gem uses AJAX to speed up page rendering in most applications. - -### How Turbolinks works - -Turbolinks attaches a click handler to all `` on the page. If your browser -supports -[PushState](https://developer.mozilla.org/en-US/docs/DOM/Manipulating_the_browser_history#The_pushState(\).C2.A0method), -Turbolinks will make an AJAX request for the page, parse the response, and -replace the entire `` of the page with the `` of the response. It -will then use PushState to change the URL to the correct one, preserving -refresh semantics and giving you pretty URLs. - -The only thing you have to do to enable Turbolinks is have it in your Gemfile, -and put `//= require turbolinks` in your CoffeeScript manifest, which is usually -`app/assets/javascripts/application.js`. - -If you want to disable Turbolinks for certain links, add a `data-no-turbolink` -attribute to the tag: - -``` -No turbolinks here. -``` - -### Page Change events - -When writing CoffeeScript, you'll often want to do some sort of processing upon -page load. With jQuery, you'd write something like this: - -``` -$(document).ready -> - alert "page has loaded!" -``` - -However, because Turbolinks overrides the normal page loading process, the -event that this relies on will not be fired. If you have code that looks like -this, you must change your code to do this instead: - -``` -$(document).on "page:change", -> - alert "page has loaded!" -``` - -For more details, including other events you can bind to, check out [the -Turbolinks -README](https://github.com/rails/turbolinks/blob/ec9ca4d6cf9626e03a672f3b9e7968c816aff94e/README.md). - -Other resources ---------------- - -Here are some helpful links to help you learn even more: - -* [jquery-ujs wiki](https://github.com/rails/jquery-ujs/wiki) -* [jquery-ujs list of external articles](https://github.com/rails/jquery-ujs/wiki/External-articles) -* [Rails 3 Remote Links and Forms: A Definitive Guide](http://www.alfajango.com/blog/rails-3-remote-links-and-forms/) -* [Railscasts: Unobtrusive JavaScript](http://railscasts.com/episodes/205-unobtrusive-javascript) diff --git a/guides/source/working_with_javascript_in_rails.md b/guides/source/working_with_javascript_in_rails.md new file mode 100644 index 0000000000..ccd7e8a77d --- /dev/null +++ b/guides/source/working_with_javascript_in_rails.md @@ -0,0 +1,390 @@ +Working With JavaScript in Rails +================================ + +This guide covers the built-in Ajax/JavaScript functionality of Rails (and +more); it will enable you to create rich and dynamic AJAX applications with +ease! We will cover the following topics: + +* Quick introduction to AJAX +* Unobtrusive JavaScript +* How Rails' built-in helpers assist you +* Handling AJAX on the server side +* The Turbolinks gem + +------------------------------------------------------------------------------- + +An introduction to AJAX +------------------------ + +In order to understand AJAX, you must first understand what a web browser does +normally. + +When you type `http://localhost:3000` into your browser's address bar and hit +'Go,' the browser (your 'client') makes a request to the server. It parses the +response, then fetches all associated assets, like JavaScript files, +stylesheets and images. It then assembles the page. If you click a link, it +does the same process: fetch the page, fetch the assets, put it all together, +show you the results. This is called the 'request response cycle.' + +JavaScript can also make requests to the server, and parse the response. It +also has the ability to update information on the page. Combining these two +powers, a JavaScript writer can make a web page that can update just parts of +itself, without needing to get the full page data from the server. This is a +powerful technique that we call AJAX. + +Rails ships with CoffeeScript by default, and so the rest of the examples +in this guide will be in CoffeeScript. All of these lessons, of course, apply +to vanilla JavaScript as well. + +As an example, here's some CoffeeScript code that makes an AJAX request using +the jQuery library: + +``` +$.ajax(url: "/test").done (html) -> + $("#results").append html +``` + +This code fetches data from "/test", and then appends the result to the `div` +with an id of `results`. + +Rails provides quite a bit of built-in support for building web pages with this +technique. You rarely have to write this code yourself. The rest of this guide +will show you how Rails can help you write web sites in this manner, but it's +all built on top of this fairly simple technique. + +Unobtrusive JavaScript +------------------------------------- + +Rails uses a technique called "Unobtrusive JavaScript" to handle attaching +JavaScript to the DOM. This is generally considered to be a best-practice +within the frontend community, but you may occasionally read tutorials that +demonstrate other ways. + +Here's the simplest way to write JavaScript. You may see it referred to as +'inline JavaScript': + +``` +Here +``` + +When clicked, the alert will trigger. Here's the problem: what happens when +we have lots of JavaScript we want to execute on a click? + +``` +Calculate +``` + +Awkward, right? We could pull the function definition out of the click handler, +and turn it into CoffeeScript: + +``` +fib = (n) -> + (if n < 2 then n else fib(n - 1) + fib(n - 2)) +``` + +And then on our page: + +``` +Calculate +``` + +That's a little bit better, but what about multiple links that have the same +effect? + +``` +Calculate +Calculate +Calculate +``` + +Not very DRY, eh? We can fix this by using events instead. We'll add a `data-*` +attribute to our link, and then bind a handler to the click event of every link +that has that attribute: + +``` +fib = (n) -> + (if n < 2 then n else fib(n - 1) + fib(n - 2)) + +$(document).ready -> + $("a[data-fib]").click (e) -> + count = $(this).data("fib") + alert "fib of #{count} is: #{fib(count)}." + +... later ... + +Calculate +Calculate +Calculate +``` + +We call this 'unobtrusive' JavaScript because we're no longer mixing our +JavaScript into our HTML. We've properly separated our concerns, making future +change easy. We can easily add behavior to any link by adding the data +attribute. We can run all of our JavaScript through a minimizer and +concatenator. We can serve our entire JavaScript bundle on every page, which +means that it'll get downloaded on the first page load and then be cached on +every page after that. Lots of little benefits really add up. + +The Rails team strongly encourages you to write your CoffeeScript (and +JavaScript) in this style, and you can expect that many libraries will also +follow this pattern. + +Built-in Helpers +---------------------- + +Rails provides a bunch of view helper methods written in Ruby to assist you +in generating HTML. Sometimes, you want to add a little AJAX to those elements, +and Rails has got your back in those cases. + +Because of Unobtrusive JavaScript, the Rails "AJAX helpers" are actually in two +parts: the JavaScript half and the Ruby half. +[rails.js](https://github.com/rails/jquery-ujs/blob/master/src/rails.js) +provides the JavaScript half, and the regular Ruby view helpers add appropriate +tags to your DOM. The CoffeeScript in rails.js then listens for these +attributes, and attaches appropriate handlers. + +### form_for + +[`form_for`](http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_for) +is a helper that assists with writing forms. `form_for` takes a `:remote` +option. It works like this: + +``` +<%= form_for(@post, remote: true) do |f| %> + ... +<% end %> +``` + +This will generate the following HTML: + +``` + + ... +
    +``` + +Note the `data-remote='true'`. Now, the form will be submitted by AJAX rather +than by the browser's normal submit mechanism. + +You probably don't want to just sit there with a filled out `
    `, though. +You probably want to do something upon a successful submission. To do that, +bind to the `ajax:success` event. On failure, use `ajax:error`. Check it out: + +``` + +``` + +Obviously, you'll want to be a bit more sophisticated than that, but it's a +start. + +### form_tag + +[`form_tag`](http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html#method-i-form_tag) +is very similar to `form_for`. It has a `:remote` option that you can use like +this: + +``` +<%= form_tag('/posts', remote: true) %> +``` + +Everything else is the same as `form_for`. See its documentation for full +details. + +### link_to + +[`link_to`](http://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html#method-i-link_to) +is a helper that assists with generating links. It has a `:remote` option you +can use like this: + +``` +<%= link_to "first post", @post, remote: true %> +``` + +which generates + +``` +a post +``` + +You can bind to the same AJAX events as `form_for`. Here's an example. Let's +assume that we have a resource `/fib/:n` that calculates the `n`th Fibonacci +number. We would generate some HTML like this: + +<%= link_to "Calculate", "/fib/15", remote: true, data: { fib: 15 } %> + +and write some CoffeeScript like this: + +``` +$(document).ready -> + $("a[data-fib]").on "ajax:success", (e, data, status, xhr) -> + count = $(this).data("fib") + alert "fib of #{count} is: #{data}." +``` + +### button_to + +[`button_to`](http://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html#method-i-button_to) is a helper that helps you create buttons. It has a `:remote` option that you can call like this: + +``` +<%= button_to "A post", @post, remote: true %> +``` + +this generates + +``` + +
    +``` + +Since it's just a `
    `, all of the information on `form_for` also applies. + +Server side concerns +-------------------- + +AJAX isn't just client-side, you also need to do some work on the server +side to support it. Often, people like their AJAX requests to return JSON +rather than HTML. Let's discuss what it takes to make that happen. + +### A Simple Example + +Imagine you have a series of users that you would like to display and provide a +form on that same page to create a new user. The index action of your +controller looks like this: + +``` +class UsersController < ApplicationController + def index + @users = User.all + @user = User.new + end + # ... +``` + +The index view (`app/views/users/index.html.erb`) contains: + +``` +Users + + + +
    + +<%= form_for(@user, remote: true) do |f| %> + <%= f.label :name %>
    + <%= f.text_field :name %> + <%= f.submit %> +<% end %> +``` + +The `app/views/users/_user.html.erb` partial contains the following: + +``` +
  • <%= user.name %>
  • +``` + +The top portion of the index page displays the users. The bottom portion +provides a form to create a new user. + +The bottom form will call the create action on the Users controller. Because +the form's remote option is set to true, the request will be posted to the +users controller as an AJAX request, looking for JavaScript. In order to +service that request, the create action of your controller would look like +this: + +``` + # app/controllers/users_controller.rb + # ...... + def create + @user = User.new(params[:user]) + + respond_to do |format| + if @user.save + format.html { redirect_to @user, notice: 'User was successfully created.' } + format.js {} + format.json { render json: @user, status: :created, location: @user } + else + format.html { render action: "new" } + format.json { render json: @user.errors, status: :unprocessable_entity } + end + end + end +``` + +Notice the format.js in the respond_to block; that allows the controller to +respond to your AJAX request. You then have a corresponding +`app/views/users/create.js.erb` view file that generates the actual JavaScript +code that will be sent and executed on the client side. + +``` +$("<%= escape_javascript(render @user) %>").appendTo("#users"); +``` + +Turbolinks +---------- + +Rails 4 ships with the [Turbolinks gem](https://github.com/rails/turbolinks). +This gem uses AJAX to speed up page rendering in most applications. + +### How Turbolinks works + +Turbolinks attaches a click handler to all `` on the page. If your browser +supports +[PushState](https://developer.mozilla.org/en-US/docs/DOM/Manipulating_the_browser_history#The_pushState(\).C2.A0method), +Turbolinks will make an AJAX request for the page, parse the response, and +replace the entire `` of the page with the `` of the response. It +will then use PushState to change the URL to the correct one, preserving +refresh semantics and giving you pretty URLs. + +The only thing you have to do to enable Turbolinks is have it in your Gemfile, +and put `//= require turbolinks` in your CoffeeScript manifest, which is usually +`app/assets/javascripts/application.js`. + +If you want to disable Turbolinks for certain links, add a `data-no-turbolink` +attribute to the tag: + +``` +No turbolinks here. +``` + +### Page Change events + +When writing CoffeeScript, you'll often want to do some sort of processing upon +page load. With jQuery, you'd write something like this: + +``` +$(document).ready -> + alert "page has loaded!" +``` + +However, because Turbolinks overrides the normal page loading process, the +event that this relies on will not be fired. If you have code that looks like +this, you must change your code to do this instead: + +``` +$(document).on "page:change", -> + alert "page has loaded!" +``` + +For more details, including other events you can bind to, check out [the +Turbolinks +README](https://github.com/rails/turbolinks/blob/ec9ca4d6cf9626e03a672f3b9e7968c816aff94e/README.md). + +Other resources +--------------- + +Here are some helpful links to help you learn even more: + +* [jquery-ujs wiki](https://github.com/rails/jquery-ujs/wiki) +* [jquery-ujs list of external articles](https://github.com/rails/jquery-ujs/wiki/External-articles) +* [Rails 3 Remote Links and Forms: A Definitive Guide](http://www.alfajango.com/blog/rails-3-remote-links-and-forms/) +* [Railscasts: Unobtrusive JavaScript](http://railscasts.com/episodes/205-unobtrusive-javascript) -- cgit v1.2.3