เป็นการใช้หลักการของ Ajax รูปแบบหนึ่ง ซึ่งผู้ใช้สามารถเลือกไปที่วัตถุบน web site แล้วเลื่อนให้วัตถุนั้นๆ สามารถไปยังที่ไหนในหน้า web เพื่อดำเนินการต่อไปได้ ทำให้ web site ดูน่าสนใจมากยิ่งขึ้น

ต้องมีการเรียกใช้ javascript ดังนี้

<%= javascript_include_tag "prototype" %>
<%= javascript_include_tag "dragdrop" %>

การเรียกใช้ javascript ด้านบน ต้องเพิ่มในส่วนของการแสดงผล นั่นก็คือ view นั่นเอง

สิ่งที่ต้องเตรียม

  • ฐานข้อมูล ที่มีตารางชื่อ products ดังนี้
CREATE TABLE `products` (
  `id` int(11) NOT NULL auto_increment,
  `title` varchar(150) NOT NULL default '',
  `image_url` varchar(200) NOT NULL default '',
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=18 ;

  • สร้าง Model ชื่อ product ดังนี้
 ruby script/generate model Product

เขียน views : index.rhtml ดังนี้

<%= javascript_include_tag "prototype" %>
<%= javascript_include_tag "dragdrop" %>
<%= stylesheet_link_tag "cartDrag", :media => "all" %>

<div style="margin-bottom:20px;height:120px;">

<% for product in @products %>
  <%= image_tag "#{product.image_url}",
        :id => "product_#{product.id}",
        :alt => product.title,
        :class => "products"  %>
  <%= draggable_element "product_#{product.id}", :revert => true %>
<% end %>
</div>

<div style="height:40px;padding-top:10px;">
<p id="indicator" style="display:none;margin-top:0px;">
  <%= image_tag "indicator.gif" %> Updating cart...
</p>
</div>

<h2>Your cart: </h2>
<div id="cart" ">
  <div id="items">
    <%= render :partial => "cart" %>
  </div>
  <div style="clear:both;"></div>
</div>

<div id="wastebin">
   Drop items here to remove them from the cart.
</div>

<%= drop_receiving_element "cart",
      :update => "items", :url => { :action => "add" },
      :accept => "products", :hoverclass => "cart-active",
      :loading => "Element.show('indicator')",
      :complete => "Element.hide('indicator')" %>

<%= drop_receiving_element "wastebin",
      :update => "items", :url => { :action => "remove" },
      :accept => "cart-items", :hoverclass => "wastebin-active",
      :before => "Element.hide(element)",
      :loading => "Element.show('indicator')",
      :complete => "Element.hide('indicator')" %>

อธิบาย code ดังนี้

<%= javascript_include_tag "prototype" %>
<%= javascript_include_tag "dragdrop" %>
<%= stylesheet_link_tag "cartDrag", :media => "all" %>

อธิบาย code

เป็นการ include javascript ชื่อ prototype.js และ dragdrop.js

style sheet ชื่อ cartDrag.css เพื่อเรียกใช้ต่อไป


<% for product in @products %>
  <%= image_tag "#{product.image_url}",
        :id => "product_#{product.id}",
        :alt => product.title,
        :class => "products"  %>
  <%= draggable_element "product_#{product.id}", :revert => true %>
<% end %>

อธิบาย code

ส่วนแรกของ code ด้านบนเป็นการวนลูปแสดงข้อมูลสินค้า จาก database โดยข้อมูล รูปภาพ สินค้ามาแสดงผล และกำหนดให้แต่ละรูปภาพมี id และ title แตกต่างกันขึ้นอยู่กับข้อมูลใน database

ส่วนที่สองคือ tag draggable_element เป็นการกำหนดให้ ภาพสินค้าแต่ละภาพสามารถถูกเลื่อนไปมาได้ จาก product_#{product.id}


<div style="height:40px;padding-top:10px;">
<p id="indicator" style="display:none;margin-top:0px;">
  <%= image_tag "indicator.gif" %> Updating cart...
</p>
</div>

อธิบาย code

เป็นการกำหนดพื้นที่การทำงานภายใต้ tag div ซึ่งภายในจะมีการใส่รูปภาพของตัว indicator ซึ่งจะแสดงผลพร้อมกับข้อความว่า ” Updating cart…”เมื่อมีการเรียกให้ทำงาน


<h2>Your cart: </h2>
<div id="cart" ">
  <div id="items">
    <%= render :partial => "cart" %>
  </div>
  <div style="clear:both;"></div>
</div>

อธิบาย code

กำหนดพื้นที่การทำงานในส่วนของตะกร้าสินค้า ด้วย tag div “items”


<div id="wastebin">
   Drop items here to remove them from the cart.
</div>

อธิบาย code

กำหนดพื้นที่การทำงานในส่วนของถังขยะ หรือการยกเลิกสินค้า ด้วย tag div “wastebin”


<%= drop_receiving_element "cart",
      :update => "items", :url => { :action => "add" },
      :accept => "products", :hoverclass => "cart-active",
      :loading => "Element.show('indicator')",
      :complete => "Element.hide('indicator')" %>

อธิบาย code

บอกว่าถ้าส่วนของพื้นที่การทำงานใน tag div ชื่อ “cart” ได้รับ element หรือ มี element มาที่นี่ จะต้องทำงานดังนี้

  • ทำงานที่ฟังก์ชัน add() (ใน controller) โดยผลลัพธ์ที่ได้จะออกมาแสดงผลบนพื้นที่ tag div ชื่อ “items”
  • มีการทำงานไปที่ Element.show(‘indicator’) แสดงภาพ indicator ออกมา
  • เมื่อทำงานเสร็จ Element.hide(‘indicator’) นำภาพ indicator ซ่อนไว้ไม่ไห้เห็น

<%= drop_receiving_element "wastebin",
      :update => "items", :url => { :action => "remove" },
      :accept => "cart-items", :hoverclass => "wastebin-active",
      :before => "Element.hide(element)",
      :loading => "Element.show('indicator')",
      :complete => "Element.hide('indicator')" %>

อธิบาย code

บอกว่าถ้าส่วนของพื้นที่การทำงานใน tag div ชื่อ “wastebin”ได้รับ element หรือ มี element มาที่นี่ จะต้องทำงานดังนี้

  • ทำงานที่ฟังก์ชัน remove() (ใน controller) โดยผลลัพธ์ที่ได้จะออกมาแสดงผลบนพื้นที่ tag div ชื่อ “items”
  • มีการทำงานไปที่ Element.show(‘indicator’) แสดงภาพ indicator ออกมา
  • เมื่อทำงานเสร็จ Element.hide(‘indicator’) นำภาพ indicator ซ่อนไว้ไม่ไห้เห็น

เขียน controller

  def index
    session[:cart] ||= {}
    @products = Product.find(:all)
  end

  def add
    product_id = params[:id].split("_")[1]

    session[:cart][product_id] =
      session[:cart].include?(product_id) ?
      session[:cart][product_id]+1 : 1

    render :partial => 'cart'
  end

  def remove
    product_id = params[:id].split("_")[1]

    if session[:cart][product_id] > 1
      session[:cart][product_id] = session[:cart][product_id]-1
    else
      session[:cart].delete(product_id)
    end

    render :partial => 'cart'
  end

เขียน _cart.rhtml partial

<% session[:cart].each do |product,quantity| %>
<div>
  <% quantity.times do |i| %>
    <% image_url =  Product.find(product).image_url %>
    <%= image_tag "#{image_url}",
          :class => "cart-items",
          :id => "item_#{product}_#{i}",
          :style => "position:relative;" %>
    <%= draggable_element "item_#{product}_#{i}", :revert => true %>
  <% end %>
  <span>
    <%= Product.find(product).title + " (#{quantity})" %>
  </span>
</div>
<% end %>
<%= "Here's your shopping cart." if session[:cart].empty? %>

ผลลัพธ์

  • แสดงการเขียน drag and drop อย่างง่ายๆ

drag01.png

  • คลิ้กที่รูปภาพ จะเห็นว่ารูปภาพสามารถเลื้อนไปตามเมาส์

drag02.png

  • นำรูปภาพไปวางในส่วนที่เรียกว่าตะกร้า โดย double click ในตำแหน่งที่จะวาง

drag03.png

  • ทดสอบนำสินค้ามาใส่ตะกร้า

drag04.png

  • ยกเลิอกสินค้าที่มีในตะกร้า โดยการคลิ้กที่สินค้าในตะกร้า แล้วนำไปวางในตำแหน่งของถังขยะ

drag05.png

  • ผลลัพธ์สุดท้ายของตะกร้าสินค้า

drag06.png

Reference