Felhasználói felületek
Ruby on Rails alapokon

Fekete Ferenc

Ruby? Rails?

Ruby? Rails?

Ajax támogatás

Metódus hívása Ruby kódban:

link_to_remote "ajax link", :url => { product_path(product) }

HTML kimeneten:

<a href="#" onclick="new Ajax.Updater('/products/show/1',
{asynchronous:true, evalScripts:true}); return false;"
>ajax link</a>

Ruby? Rails?

Rapid development/prototyping

 

Gyakori funkciók "kiemelése", újrafelhasználhatóvá tétele

Az előadás tartalma

Helper-ek

Az előadás tartalma

Remote JavaScript (RJS template)

Kezdjünk bele - Autocomplete

Autocomplete mező

Űrlap mező kitöltésére vonatkozó javaslatot tesz

Autocomplete mező

View (template)

text_field_with_auto_complete :user, :name

A helper html-t renderel a kimenetre

<input id="user_name" name="user[name]" size="30" type="text" />

<div class="auto_complete" id="user_name_auto_complete"></div>

<script type="text/javascript">
var user_name_auto_completer = new Ajax.Autocompleter('user_name', 'user_name_auto_complete', '/autocomplete/auto_complete_for_user_name', {})
</script>

Autocomplete mező

Controller

auto_complete_for :user, :name

Szerver oldalon automatikusan létrejön az összes szükséges action

 

Nézzük meg a példát működés közben!

Autocomplete demo

InPlace edit

InPlace edit

Az adatbázisban lévő tartalom szerkesztésére

InPlace edit

View (template)

in_place_editor_field :user, :name, {}, :rows => 1

A helper html-t renderel a kimenetre

<span class="in_place_editor_field" id="user_name_1_in_place_editor">Fekete Ferenc</span>

<script type="text/javascript">
new Ajax.InPlaceEditor('user_name_1_in_place_editor', '/inplace/set_user_name/1', {rows:1})
</script>

InPlace edit

Controller

in_place_edit_for :user, "name"

Az összes szükséges action létrejön

 

Nézzük meg a példát működés közben!

InPlace edit demo

Drag & Drop, sortables

Drag & Drop listák

Tartalmi egységek gyors sorrendbe rendezése

Drag & Drop listák

View (template)


<ul id="todos">
  <li id="item_1">Első elem</li>
  <li id="item_2">Második elem</li>
</ul>
sortable_element 'todos', 
  :url => { :action => "sort" , :id => @list },
  :complete => visual_effect(:highlight, 'todos')

Drag & Drop listák

Controller


  def sort
    List.find( params[:id] ).todos.each do |t|
      t.position = params[:todos].index(t.id.to_s) + 1
      t.save
    end
    render :nothing => true
  end
Próbáljuk ki!

Remote JavaScript

Remote JavaScript - RJS

Az RJS működése:

 

Egy Ajax kéréssel elérhető az oldal több, különböző részének a frissítése

Periodikusan frissülő elem

Periodikusan frissülő elem

A felhasználói felület egy részének folyamatos frissítésére

Periodikusan frissülő elem

View (template)

periodically_call_remote :url => { :action => 'spy' }, :frequency => 3

HTML kimenet

<script type="text/javascript">
//<![CDATA[
new PeriodicalExecuter(function() {new Ajax.Request('/diggspy/spy', {asynchronous:true, evalScripts:true})}, 3)
//]]>
</script>

Periodikusan frissülő elem

Controller

Tartalmi egységek lekérdezése, majd visszaküldése a kliensnek.


render :update do |page|
  page.insert_html :top, "element_id", :partial => "item_row"
  page.visual_effect :highlight, item.id
end

Próbáljuk ki!

LiveSearch

LiveSearch

LiveSearch

observe_field "search", :frequency => 0.5, :with => "phrase",
    :loading => "$('i').toggle();",
    :complete => "$('i').toggle();",
    :url => { :action => "search" }

HTTP POST

http://domain.com/controller/search?phrase=keyword

Callback

LiveSearch

HTML kimenet

<script type="text/javascript">
//<![CDATA[
new Form.Element.Observer('search', 0.5, function(element, value) {new Ajax.Request('/livesearch/search', {asynchronous:true, evalScripts:true, onComplete:function(request){$('i').toggle();}, onLoading:function(request){$('i').toggle();}, parameters:'phrase=' + value})})
//]]>
</script>

LiveSearch

A search.rjs template tartalma


# a találati listát a megadott div-be rendereljük
page.replace_html "serp", :partial => "serp"

# megváltoztatjuk a p.count tag tartalmát
page.replace_html "count", 
    "<strong>#{@results.length}</strong> találat 
    a '<strong>#{@phrase}</strong>' kifejezésre"

# kap egy highlight-ot is
page.visual_effect :highlight, "count"

LiveSearch demo!

Még több RJS

Néhány példa az RJS képességeiből

Még több RJS

Függvényhívás

# ruby
page.call 'displayError', 'An error occurred'

// generated javascript
displayError('An error occurred');

Elemek elrejtése

# ruby
page.hide('first', 'second')

// generated javascript
Element.hide("first", "second");

Még több RJS

HTML beillesztés

# ruby
page.insert_html(:bottom, 'products', '<li>Refrigerator</li>')

// generated javascript
new Insertion.Bottom("products", "<li>Refrigerator</li>");

HTML csere

# ruby
page.replace 'banner', '<div id="banner">Rails Rules</div>'

// generated javascript
Element.replace("banner", "<div id=\"banner\">Rails Rules</div>");

Még több RJS

Sortable/Drag & Drop

# ruby 
page.sortable 'project-65', :url => { :action => 'sort' }
// generated javascript 
sortable.create("project-65", {onUpdate:function(){ new Ajax.Request('/projects/sort', { asynchronous:true, evalScripts:true, parameters:Sortable.serialize("project-65") } )} });

Fejelsszünk valamit!

 

DataGrid

DataGrid

DataGrid

Rekordok táblázatba rendezése 1. - Controller


# lekérdezzük az összes felhasználót, az összes tulajdonságot 
(és az összes kapcsolótáblát és kapcsolatot)

def index
  @users = User.find( :all )
end

# tömb, elemei az user objektumok
@users

DataGrid

Rekordok táblázatba rendezése 2. - _grid.rhtml

A Model "columns" tulajdonságának értékeiből automatikusan oszlopcímeket képezünk


<table id="datagrid">
  <tr>
    <% User.columns.each do |column| %>
      <th>
        <%= column.human_name %>
      </th>
    <% end %>
  </tr>
</table>

DataGrid

Rekordok táblázatba rendezése 3. - _grid.rhtml

A táblázatot feltöltjük adatokkal


    <% @users.each do |u| %>
      <tr>
        <td>
          <%= u.id %>
          <%= u.name %>
          <%= u.address %>
          <%= u.phone %>
        </td>
      </tr>
    <% end %>

DataGrid

Adatok rendezése mezők szerint: növekvő, csökkenő sorrend



def sort
  @users = User.find( :all, :order => "#{params[:sort_by]} #{params[:order]}" )
end

DataGrid

JavaScript, Ajax használat


# táblázat oszlopcímeihez linkek
link_to_remote "növekvő", :url => { 
                            :action => "sort", 
                            :sort_by => column.name, 
                            :order => "asc" } 

link_to_remote "csökkenő", :url => { 
                            :action => "sort", 
                            :sort_by => column.name, 
                            :order => "desc" }

DataGrid

JavaScript, Ajax használat: paraméterek fogadása


<a href="#" onclick="new Ajax.Request('/grid/sort?order=desc&sort_by=name', 
{asynchronous:true, evalScripts:true}); return false;">csökkenő</a>


# params[:sort_by] = "name"
# params[:order] = "DESC"


def sort
  @users = User.find( :all, :order => "#{params[:sort_by]} #{params[:order]}" )
end

DataGrid

Mezők szerkesztése: InPlace edit 1.


<span class="in_place_editor_field" id="user_name_<%= u.id %>_in_place_editor">
  <%= u.name %>
</span>

<script type="text/javascript">
  //<![CDATA[
   new Ajax.InPlaceEditor('user_name_<%= u.id %>_in_place_editor',
                          '/grid/set_user_name/<%= u.id %>', {rows:1})
  //]]>
</script>

DataGrid

Mezők szerkesztése: InPlace edit 2.

"Megmondjuk" a Controllernek, hogy fogadja az editor kéréseit


  # "Bármely" tulajdonsághoz legyen szerkeszthető
  
  User.content_columns.each do |column|
    in_place_edit_for :user, column.name
  end

 

Datagrid demo

Köszönöm a figyelmet!