在 Rails3 中,處理 JavaScript 改採用 UJS 的方式,也就是以往 inline JS 的情況將不復見,link_to_remote 跟 remote_form_for 都沒有了:
例如:
link_to 'Logout', session_path, :method => :delete
產生出來的是:
<a href="/session" data-method="delete" rel="nofollow">Logoout</a>
例如
link_to 'Ajax delete', person_path(person),
:remote => true, :confirm => "Are you sure?"
產生出來的是
<a href="/people/1" data-confirm="Are you sure?" data-method="delete"
data-remote="true" rel="nofollow">Ajax delete</a>
# 點下去會向 Server 要求 JavaScript 內容執行
Rails3 預設還是使用 Prototype.js,要換成 jQuery 非常簡單。首先在產生 rails 專案時,可以輸入 rails your_project -J 就不會產生 Prototype.js 的檔案。
修改 /public/javascripts/rails.js 這個檔案,內容換成 http://github.com/rails/jquery-ujs/blob/master/src/rails.js 這個官方提供的 jQuery js driver。
在 Rails layout 的 HTML head 中加入:
<%= csrf_meta_tag %>
<%= javascript_include_tag "http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js" %>
<%= javascript_include_tag 'rails' %>
其中 csrf_mate_tag 產生的是做 CSRF 防禦的 authenticity_token,以往這也是 inline 在 HTML 中,現在則是先宣告在 HTML head 中。
另外要提醒你,如果你有使用 RJS 的話,Rails3 的 RJS 還是只會產生 prototype.js 的版本。所以如果非得用 RJS 的話,目前恐怕還是得裝以往 Rails2 用的 jRails,這好像有點蠢。也許是時候把 RJS 徹底揚棄,直接寫 jQuery 好了(?)
例如上面的 Ajax delete 例子,它的 controller 跟 js 可以這樣:
# people_controller.rb
def destroy
@person = Person.find(params[:id])
@person.destroy
respond_to do |format|
format.html { redirect_to(people_url) }
format.js # destroy.js.erb
end
end
# destroy.js.erb
jQuery("#<%= dom_id(@person)%>").remove();
FaceboxRender 是我最近寫的第二個 Ajax UI plugin,它讓你在 Rails 中可以無縫使用 lightbox 效果,搭配使用的 Javascript library 正如其名是 Facebox。首先你得先裝好 jQuery 和 Facebox:
- 下載 jQuery (建議你可以考慮用 jRails 完全換掉 Prototype library)
- 下載 facebox
- 把 facebox js file 放到 /public/javascripts/
- 把 facebox css file 放到 /public/styleshees/
- 把 facebox all image files 放到 /public/facebox/
- 設定好 layout 的 stylesheet_link_tag 和 javascript_include_tag 加入這些 js,css 檔案
facebox-render 目前放在 github,請下載後放到 vender/plugins/facebox_render
然後在你要使用的 Controller 加入以下程式碼
include FaceboxRender
或是你直接放到 /app/controllers/application.rb 裡面也是可以。
回到 view code,當你要叫出一個 lightbox :
facebox_link_to "Login", :url => login_url
或是你也可以用 remote_link_to, remote_form_tag 等Rails內建的 Ajax Helper,差別在於 facebox_link_to 會先秀出一個 Loading lightbox,然後再送 Ajax request。
重頭戲是 action :
def new
# do some thing you want
respond_to do |format|
format.html
format.js { render_to_facebox }
end
end
這裡巧妙的運用了 respond_to 來處理 ajax request,預設的 render_facebox 會 render 不帶 layout 的HTML(即 new.html.erb)。當然我們也支援傳入 :action, :template, :partial 等常見的Rails參數,或是乾脆傳入 :html 也可以。
傳入 :msg 的話,會插入一段 <div class=”message”>your msg</div> 到裡面去,方便你做一些提示或警告訊息。
除了 render_facebox,也有 close_facebox 可以關掉 lightbox。也可以用 redirect_from_lightbox 重新讀取另一頁。
實際的應用非常方便,你可以在網頁中用 remote link 或是 remote form submit 叫出 facebox。在 facebox 中也還可以再放 remote link 或 remote form submit,接收處理的 action 可用 render_facebox 或關掉 close_facebox 抑或重新讀取頁面 redirect_from_facebox。
FaceboxRender 的隨附文件請見 README 。
P.S. 這篇文的英文版在 Handlino’s blog
Spakit 源自 registrano.com 和 Massage,是一個可以讓你將現成的網站輕鬆轉換成 SPA (single page application) 的 Rails Plugin。只需在 view 中換用 Spakit helper,不需要更動 controller code,就可將超連結和表單送出變成 Ajax 送出並更新頁面。
spakit 目前放在 github,另外也包成 gem,安裝方式如下:
gem install spakit
cd /your_rails_app/vendor/plugin
gem unpack spakit
mv spakit-0.9.0 spakit
並且 rename 成 spakit。裝好之後,首先建立一個 Spakit 專用的 Layout,一個簡單的範例如下:
# /view/layouts/spakit.rhtml
<p><%= flash[:notice] %></p>
<%= yield %>
接著就可以使用 Spakit 專用的 helpers,目前有 spakit_link_to, spakit_form_for 和 spakit_form_tag 三種可以使用,用法如下:
spakit_link_to 'new person', :url => new_person_path
spakit_form_for @person, :url => people_path
如此按下連結或送出表單後,Spakit 就會送出 Ajax request(i.e. prototype’s Ajax.Updater ),然後將回傳的 HTML 結果更新到#content 區塊。
如果你想要支援 Ajax 的 Histroy Bookmarks,建議可以採用 Really Simple History(RSH) library 來處理瀏覽器的上一頁下一頁問題,這部份的範例程式附在 plugin 的 README (使用到 jquery library,好心人有空可以幫忙寫 prototype version)。
P.S. 這篇文的英文版在 Handlino’s blog