เราจะพูดถึงการ implement Ajax โดยใช้ library ที่เรียกว่า “Prototype” เพื่อช่วยในการสร้างลิงค์และ form ในรูปแบบของ Ajax

1. สร้าง Rails Application

1.1 สร้าง Controller + Action

script/generate controller chap3 get_time repeat reverse

ประกอบไปด้วย

  • 1 controller
    • chap3
  • 3 Action (Method)
    • get_time, repeat, reverse

1.2 สร้าง HTML Layout และ style sheet (CSS)

1.2.1 HTML Layout

สร้าง HTML Layout : app/views/layouts/application.rhtml

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
  <head>
    <title>Ajax on Rails</title>
    <%= javascript_include_tag :defaults %>
    <%= stylesheet_link_tag "application" %>
  </head>
  <body>
    <h1>Ajax on Rails</h1>
    <%= yield %>
  </body>
</html>

จาก code ด้านบน มีการเรียกใช้ javascript_include_tag :defaults เป็นการเรียกใช้ไฟล์ javascript ที่มีอยู่โดยพื้นฐาน ( prototype.js, effects.js, dragdrop.js, and controls.js) และ yield เป็น code ruby ที่นำ content ของ action template มาแทรกใน layout นี้

1.2.2 Css

สร้าง CSS : public/stylesheets/application.css

body {
  background-color: #eee;
  color: #222;
  font-family: trebuchet;
  padding: 0;
  margin: 25px;
}
h1 {
  margin: -25px -25px 20px -25px;
  padding: 50px 0 8px 25px;
  border-bottom: 3px solid #666;
  background-color: #777;
  color: #fff;
  font: normal 28pt georgia;
  text-shadow: black 0px 0px 5px;
}
a { color: #229; }
.box {
  border: 1px solid;
  width: 100px; height: 100px;
  padding: 5px;
  font-size: .6em;
  letter-spacing: .1em;
  text-transform: uppercase;
  margin-bottom: 20px;
}
.pink {
  border-color: #f00;
  background-color: #fcc;
}
.green {
  border-color: #090;
  background-color: #cfc;
}
.hover {
  border-width: 5px;
  padding: 1px;
}
ul {
  background-color: #ccc;
  padding: 5px 0 5px 30px;
}

1.2.3 สร้าง HTML

สร้าง HTML Layout : app/views/chap3/index.rhtml และทดลองรัน http://127.0.0.1:3000/chap3&#8221; จะได้ผลดังภาพด้านล่าง
Picture_7.png

2. สร้างลิงค์แบบ Simple และ ลิงค์แบบ Ajax

2.1 สร้าง controller

แก้ไขไฟล์ controller: app/controllers/chapter3_controller.rb โดยการเพิ่มเนื้อหาใน Action เข้าไปดังนี้

class Chapter3Controller < ApplicationController

  def get_time
    sleep 1.second
    render :text => Time.now.to_s
  end

end

2.2 Simple link

แก้ไขไฟล์ index.rhtml: app/view/chap3/index.rhtml

<%= link_to "Check Time", :action => 'get_time' %>

NOTE: ซึ่งจาก code จะมีการเรียกใช้ฟังก์ชั่น helper link_to เพื่อไปทำงานยังฟังก์ชั่น get_time ถ้าเรา view source code จะแสดงผลดังนี้

<a href="/chapter3/get_time">Check Time</a>

Picture_8.png
Picture_9.png

2.3 Ajax link

แก้ไขไฟล์ index.rhtml: app/view/chap3/index.rhtml

<%= link_to_remote "Check Time (Ajax link)",
    :update => 'current_time',
    :url    => { :action => 'get_time' } %>
<div id="current_time"></div>

Picture_10.png
Picture_11.png

NOTE: มีการเรียกใช้ฟังก์ชั่น link_to_remote แทน link_to และใส่ option :update เพิ่มเข้าไป (ชี้ไปยัง HTML element ID ชื่อ current_time) เพื่อให้ Output ไปแสดงผลที่นั่น (ใน tag DIV ชื่ิอ current_time)

จะเห็นว่า หน้าเว็บเพจจะไม่ refresh ทั้งหน้า มีการรับส่งข้อมูลกันบางส่วนของหน้าเว็บ ช่วยลดโหลดการทำงานระหว่าง server + client ได้

2.3.1 Callback

นอกจากนี้ ยังมี Callback Option :before สำหรับการแสดงผลก่อนที่จะแสดง Output เพื่อการแสดงผลทำให้ดูดียิ่งขึ้น เนื่องจาก user จะเห็นว่าเว็บเพจกำลัง process อยู่

<%= link_to_remote "Check Time (Call back)",
    :update => 'current_time',
    :url    => { :action => 'get_time' },
    :before => "$('current_time').update('Loading...')" %>
<div id="current_time"></div>

Picture_12.png
Picture_13.png

NOTE: สรุป Option ของ link_to_remote

  • before : จะมีการทำงานก่อน การแสดง output
  • success : จะมีการทำงานเมื่อ การแสดงผลสำเร็จ (ไม่มี error)
  • failure : จะมีการทำงานเมื่อ เมื่อการแสดงผลมีปัญหา (มี error)
  • complete : จะมีการทำงานเมื่อ การแสดงผลเสร็จสิ้น
<%= link_to_remote "Check Time (Call back Full Option)",
    :update   => 'current_time',
    :url      => { :action => 'get_time' },
    :before   => "$('indicator').show(  )",
    :success  => "$('current_time').visualEffect('highlight')",
    :failure  => "alert('There was an error. ')",
    :complete => "$('indicator').hide(  )" %>
<span id="indicator" style="display: none;">Loading...</span>
<div id="current_time"></div>

Picture_14.png
Picture_15.png
Picture_16.png

จากตัวอย่างด้านบน, :before Ajax จะถูกเรียกใช้งานก่อน โดยการแสดงผลคำว่า “Loading…”

  • ถ้าการเรียกใช้สำเร็จ จะอยู่ในขั้นของ :success ก็จะมีการสร้าง visual effect ให้กับข้อความที่ปรากฎ (เป็น highlight แสดงแถบสีขึ้นมา)
  • แต่ถ้าไม่สำเร็จจะเป็น :failure ที่จะมีข้อความเตือนขึ้นมา
  • สุดท้าย :complete จะทำงานโดยการซ่อนข้อความ “loading…” เอาไว้ เมื่อการทำงานสิ้นสุด

2.3.2 Other Options

เราสามารถใช้ :submit callback โดยทุก field จะถูกส่งข้อมูลแบบ POST ซึ่งจะเห็นว่า เราไม่ได้ใช้ tag form แต่สามารถใช้ tag div หรือ tag tr แทนได้ :submit callback สามารถส่งข้อมูลได้

<div id="fakeForm">
  <input type="text" name="foo" value="bar" />
</div>
<%= link_to_remote "Submit fake form",
       :submit   => "fakeForm",
       :url      => { :action => 'repeat' },
       :complete => "alert(request.responseText)" %>

Picture_18.png
Picture_19.png