Category Archives: JavaScript

JavaScript,我真是搞不懂你啊!@JSDC.TW 2012

這是我在 JSDC.TW 给的 Lightning talk: “JavaScript,我真是搞不懂你啊!” 的現場錄影。因為投影片其實只是內嵌影片,所以看影片就好了。

講這個題目的目的完全只是娛樂效果(非戰)。因為成為 LT 講者可以免報名進場,所以就厚著臉皮來表演 Wat 看看,聽起來是有得到一些笑聲 XD 如果想進一步知道 JavaScript 為什麼會這樣處理,可以參考 解析 JavaScript,我真是搞不懂你啊! @JSDC 2012 這一篇文章。

Rails3 如何換使用 jQuery

在 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: Rails 無縫使用 lightbox

FaceboxRender 是我最近寫的第二個 Ajax UI plugin,它讓你在 Rails 中可以無縫使用 lightbox 效果,搭配使用的 Javascript library 正如其名是 Facebox。首先你得先裝好 jQuery 和 Facebox:

  1. 下載 jQuery (建議你可以考慮用 jRails 完全換掉 Prototype library)
  2. 下載 facebox
  3. 把 facebox js file 放到 /public/javascripts/
  4. 把 facebox css file 放到 /public/styleshees/
  5. 把 facebox all image files 放到 /public/facebox/
  6. 設定好 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: A SPA Rails plugin

Spakit 源自 registrano.comMassage,是一個可以讓你將現成的網站輕鬆轉換成 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

Jester (JavaScript版本的ActiveResource)

終於有人寫出來了。Rails 1.2 的 REST 只是 server-side,運用各種語言把對應的 client-side 實作出來是遲早的事情。

就如同 Ruby 版的 ActiveResourceJester是一個 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 (/) 了,吱吱。

ppk on JavaScript (2) Events

要達到 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等) Continue reading ppk on JavaScript (2) Events