SelectableTableのショートカットキー

概要

SelectableTableでショートカットキーを有効にする際の注意点とRubricksコンポーネント内で利用する際のノウハウ等を記述します。

ショートカットキー一覧

SelectableTableでショートカットキーを有効にすると利用可能になる機能を一覧表示します。

ショートカットキー機能
フォーカスを上に移動します
フォーカスを下に移動します
コールバック関数を実行可能です
コールバック関数を実行可能です
Enterフォーカスされている行を選択します
BackSpaceブラウザデフォルトの挙動(大抵は「戻る」)が無効化されます

問題点

ショートカットキーとして割り当てたキーは通常のブラウジングの機能としても使われています。例えば、入力フォームで何らかの入力を行おうとした時に方向キー・Enter・BackSpaceのイベントがSelectableTableに奪われてしまってまともに入力ができません。

対策

SelectableTableはビルドされたエレメントで「makeAvailable()」・「makeUnavailable()」メソッドを実行することでその動作状態を切り替えることができます。先程の例で言えば、入力ボックスのonfocusイベントでSelectableTableを停止して、onblurイベントで再開すればよいわけです。

しかし、地道に全てのイベントを定義していくのは現実的ではなく茨の道となります。使用するためには該当システム全体においてなんらかの仕組みを用意する必要があるでしょう。

Rubricksにおける対応

使用箇所

Rubricks上でSelectableTableを利用する場合、それがリストエリア上に配置される場合はショートカットキーを有効にします。その他の場所で利用される場合には基本的に無効にします。(飽くまで公式コンポーネントの規約です)その際、createメソッドの第四引数に「true」を指定します。これによって生成されるSelectableTableがSelectableTableManagerに登録され、管理されます。

Rubricksでは入力フォームは基本的にモーダル状態で表示されます。この機能はSpinelzのWindow及びRubricksライブラリのFormEditorで実現されています。そのため、モーダル状態になる時には自動的に管理下の全てのSelectableTableが停止し、モーダル状態が解除される時に再開されます。

個別に処理が必要な部分

SelectableTableで表示する内容に対してフィルタを用意している場合は、選択時にモーダル状態にはならないため、個別に処理が必要となります。フィルタ内のテキストボックスのonfocusイベントに「SelectableTableManager.stop();」を、onblurイベントに「SelectableTableManager.start();」を指定して下さい。また、フィルタによってSelectableTableが再ビルドされた時の挙動を制御するために、フィルタ全体を囲むフォームのonsubmitイベントに「rubricks.common.blur();」を、フィルタによって出力されるコード内に「$('xxxxxxx').focus();」を記述して下さい。

左右キーのショートカット

左右キーにはページネーションの改頁を割り当てます。下記のように対応してください。

  • ページネイトのナビゲーションリンクのidを「xxx_list_navigation_top」及び「xxx_list_navigation_bottom」とする
  • functionPostPressLeftオプションに「function(){SelectableTableLib.navi('previous');}」を割り当てる
  • functionPostPressRightオプションに「function(){SelectableTableLib.navi('next');}」を割り当てる

Filter

<%= form_remote_tag(:url=>{...}, :html=>{:onsubmit=>'rubricks.common.blur();'}, :update=>'xxx_frame') %>
  <input type="text" id="filter_query" name="filter[query]" onfocus="!SelectableTableManager.stop();" onblur="!SelectableTableManager.stop();" />
  <input type="submit" value="Search" >
</form>

Controller

def xxx
  if params[:filter] && params[:filter][:query]
    @search = true #フィルタによって検索されたかどうかを判定する
  end
end

View

<div class="text_center">
  <%= pagination_remote_links(@pages, {:params => {:update => 'xxx_frame', :url => {...}}}, {:id => 'xxx_list_navigation_top'}, true) %>
</div>
<table id="xxx_list">
  <tbody>
    <% @xxx_list.each do |xxx| %>
      <tr id="<%= xxx.id %>"><td><%= hl(xxx.name) %></td></tr>
    <% end %>
  </tbody>
</table>
<div class="text_center">
  <%= pagination_remote_links(@pages, {:params => {:update => 'xxx_frame', :url => {...}}}, {:id => 'xxx_list_navigation_bottom'}, true) %>
</div>
<script type="text/javascript">
  rubricks.xxx.xxx_list = SelectableTableCreator.create(
    'xxx_list',
    {
      flagKeypressAvailable:true,
      functionPostPressLeft:function(){SelectableTableLib.navi('previous');},
      functionPostPressRight:function(){SelectableTableLib.navi('next');},
      prefixTrId:'xxx_list_'
    },
    rubricks.xxx.xxx_list,
    true
  );
  <% if @search %>
    $('filter_query').focus();
  <% end %>
</script>