並び替えの処理中にクルクル回るイージケーターを表示する。

結構、憧れていたのだ...。ajax_scaffoldで、処理中にクルクル回るイージケーターに。

最小限の機能で並び替えを実装

まずは必要最小限の機能で、並び替えを実装してみた。まだ、並び替えの方向や、対象列の強調表示などのフィードバックは何もなし。

  • 列タイトルのリンクをクリックすると、その列をキーに並び替える。
  • 同じ列タイトルを繰り返しクリックすると、並び替えの方向を反転する。
<%# ---------- app/views/csvs/_listh.rhtml ---------- %>

<tr>
<% for title in @column_titles %>
  <% sort_direction = (params[:sort_field] == title) ? @next_direction : 'sorted' %>
  <th>
  <%= link_to Csv.human_attribute_name(title), 
              :sort_field => title, :sort_direction => sort_direction %>
  </th>
<% end %>
</tr>
# ---------- app/controllers/csvs_controller.rb ----------

  def list
    @next_direction = (params[:sort_direction] == 'asc') ? 'desc' : 'asc'
    order = "#{params[:sort_field] || 'id'} #{@next_direction}"
    @csv_pages, @csvs = paginate :csvs, :per_page => 10, :order => order
  end

フィードバックが無いと、状況がつかめず、実行した操作に対する不安が残る...。

ajaxで並び替え

処理中にイージケーターを回すためには、ajaxの利用が必要と考え、link_to_remoteで同じ処理を実現してみる。

  • update => 'list_update'は、ajax更新する部分。<div id="list_update">タグで、レイアウトファイル全体を指定した。
<%# ---------- app/views/csvs/_listh.rhtml ---------- %>

<tr>
<% for title in @column_titles %>
  <% sort_direction = (params[:sort_field] == title) ? @next_direction : 'sorted' %>
  <th>
  <%= link_to_remote Csv.human_attribute_name(title), 
                     :update => 'list_update', 
                     :url => {:sort_field => title, :sort_direction => sort_direction} %>
  </th>
<% end %>
</tr>
  • ajaxでは描画ファイルを明示的に指定する必要があるので、render :action => 'list'を追加した。
# ---------- app/controllers/csvs_controller.rb ----------

  def list
    @next_direction = (params[:sort_direction] == 'asc') ? 'desc' : 'asc'
    order = "#{params[:sort_field] || 'id'} #{@next_direction}"
    @csv_pages, @csvs = paginate :csvs, :per_page => 10, :order => order
    render :action => 'list'
  end
  • <div id="list_update">タグで囲まれた部分が、ajaxで更新される範囲。つまり、ページ全体にしてしまったのだ。
  • 最初、うっかり<%= javascript_include_tag :defaults %>を忘れていて、思った通りに動作せず悩んでしまった。ajaxを利用する時には必須です。
<%# ---------- app/views/layouts/csvs.rhtml ---------- %>

<div id="list_update">
<html>
<head>
  <title>Csvs: <%= controller.action_name %></title>
  <%= stylesheet_link_tag 'scaffold' %>
  <%= stylesheet_link_tag 'list_o_matic' %>
  <%= javascript_include_tag :defaults %>
</head>
<body>
<%= render :partial=>"layouts/menu2" %>
<%= render :partial=>"layouts/flash" %>

<%= yield  %>

</body>
</html>
</div>

以上で、ajaxによるページ更新になった。並び替えのリンクをクリックしても、URLは変化しなくなった。

処理中にクルクル回るイージケーターを表示

ajax_scaffoldの処理方法そのままだが、自分なりに理解してやってみた。

  • ajax_scaffoldを利用していると、public/images/indicator.gifがインストールされている。これがクルクル回るイージケーターになる。gifアニメーションの画像だ。試しにブラウザにドラッグしてみると、イージケーターがクルクル回っている画像が表示される。
  • 処理中にイージケーターを表示するために、link_to_remoteの:loading => オプションを指定した。ここで指定したことは、処理の間だけ実行されるようだ。処理が終わると元の状態に戻る。
  • :loading => オプションでは、"Element.addClassName('#{title}','loading');"というJavaScriptを指定した。id="#{title}"のタグに、class="loading"を追加する処理のようだ。
  • つまり、<th id=<%= title %>>タグは、並び替えの処理中だけ<th id=<%= title %> class="loading">という状態になる。
<%# ---------- app/views/csvs/_listh.rhtml ---------- %>

<tr>
<% for title in @column_titles %>
  <% sort_direction = (params[:sort_field] == title) ? @next_direction : 'sorted' %>
  <th id=<%= title %>>
  <%= link_to_remote Csv.human_attribute_name(title), 
                     :update => 'list_update', 
                     :url => {:sort_field => title, :sort_direction => sort_direction}, 
                     :loading => "Element.addClassName('#{title}','loading');" %>
  </th>
<% end %>
</tr>
  • スタイルシートでは、<th id=<%= title %> class="loading">タグに対する表示設定を行う。一番下のブロックで、処理中のテーブルヘッダーの背景画像に、indicator.gifを指定している。

background: lavender url(../images/indicator.gif) right 50% no-repeat;

  • この指定で、class="loading"の状態の時だけ、indicator.gifを背景画像として表示してくれるのだ。
th {
  text-align: left;
}

th a {
  font: bold 11px verdana, sans-serif;
  display: block;
}

th a, 
th a:visited {
  color: #999;
  padding: 2px 20px 2px 2px;
}

th a:hover {
  background-color: #000;
  color: #fff;
}

th.loading a,
th.loading a:hover {
  background: lavender url(../images/indicator.gif) right 50% no-repeat;
}


以上で、並び替えの処理中には、イージケーターがクルクル回ってくれる!

並び替え方向の矢印も背景画像で

  • その後、並べ替え方向を示す上下の矢印も表示するようにしてみた。>タグに、class=<%= sort_direction %> を追加しただけ。
<%# ---------- app/views/csvs/_listh.rhtml ---------- %>

<tr>
<% for title in @column_titles %>
  <% sort_direction = (params[:sort_field] == title) ? @next_direction : 'sorted' %>
  <th class=<%= sort_direction %> id=<%= title %>>
  <%= link_to_remote Csv.human_attribute_name(title), 
                     :update => 'list_update', 
                     :url => {:sort_field => title, :sort_direction => sort_direction}, 
                     :loading => "Element.addClassName('#{title}','loading');" %>
  </th>
<% end %>
</tr>
  • 矢印を背景画像として表示するスタイルシートを設定すると、並び替えの方向が表示されるようになる。
th.asc a {
background: lavender url(../images/arrow_up.gif) right 50% no-repeat;
color: #000;
}
th.asc a:hover {
background: #000 url(../images/arrow_up.gif) right 50% no-repeat;
color: #fff;
}

th.desc a {
background: lavender url(../images/arrow_down.gif) right 50% no-repeat;
color: #000;
}
th.desc a:hover {
background: #000 url(../images/arrow_down.gif) right 50% no-repeat;
color: #fff;
}


現在の見た目はこんな感じだ。