這是我在 JSDC.TW 给的 Lightning talk: “JavaScript,我真是搞不懂你啊!” 的現場錄影。因為投影片其實只是內嵌影片,所以看影片就好了。
講這個題目的目的完全只是娛樂效果(非戰)。因為成為 LT 講者可以免報名進場,所以就厚著臉皮來表演 Wat 看看,聽起來是有得到一些笑聲 XD 如果想進一步知道 JavaScript 為什麼會這樣處理,可以參考 解析 JavaScript,我真是搞不懂你啊! @JSDC 2012 這一篇文章。
這是我在 JSDC.TW 给的 Lightning talk: “JavaScript,我真是搞不懂你啊!” 的現場錄影。因為投影片其實只是內嵌影片,所以看影片就好了。
講這個題目的目的完全只是娛樂效果(非戰)。因為成為 LT 講者可以免報名進場,所以就厚著臉皮來表演 Wat 看看,聽起來是有得到一些笑聲 XD 如果想進一步知道 JavaScript 為什麼會這樣處理,可以參考 解析 JavaScript,我真是搞不懂你啊! @JSDC 2012 這一篇文章。
在 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 這個檔案,內容換成 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:
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
終於有人寫出來了。Rails 1.2 的 REST 只是 server-side,運用各種語言把對應的 client-side 實作出來是遲早的事情。
就如同 Ruby 版的 ActiveResource,Jester是一個 JavaScript Library 可以讓你操作 Rails-style resources,而且語法跟 ActiveResource 十分類似(除了new變bulid)。這樣的東西可以幹麻呢? 它(應該要)可以幫助我們輕易做出 使用 RESTful service 的 Ajax Application (please see Ajax and REST, Part 1, Part 2 )
不過,咳咳~ 它目前 1.是 synchronous 的 (作者正著手改成 asynchronous ,應該不難多 callback 參數即可) 2.用XML,如果可以支援 JSON會更棒 3. Depends on Prototype 跟 ObjTree 兩個 Library。
題外話,最近 Rails Edge 把 RESTful routing 的 semi-colon (;
) 改成 forward-slash (/
) 了,吱吱。
要達到 unobtrusive JavaScript (最新譯名: 不亂入JavaScript) 的境界,就必須對 Event-Driven 有深入的認識,這章對 Events 議題做了很詳盡的解說,前一陣子看YUI Event的時候,裡面提到的兩個IE fix都不太了解緣由,看過這章之後就恍然大悟啦。
相對於 W3C DOM 跟 XMLHttpRequest,Events有更多的 Browser Wars 留下來的問題,有著 Microsoft 蓄意的不相容問題,你必須注意這些實做差異,有些解法甚至有些 tricky,而且必須 case by case,沒有泛用型的偵測法則,例如沒有簡單的 if (W3C model) {.. } else if ( Microsoft model ) { … } 可以用。
Events 可分成三種類型 1. 滑鼠事件 mouse 2. 鍵盤事件 keyboard 3. 界面事件 interface events (例如 form submit,readystatechange等)