背景を暗くするモーダルウィンドウで表示したい!(Control.Modalの使い方)その2
前回までに、モーダルウィンドウが表示できるようになった。今回は調子に乗って、ユーザー環境設定ページに加え、パスワード変更、ユーザ情報編集*1ページもモーダルウィンドウ化することにした。(管理者以外の一般ユーザーが操作するサブページは全てモーダルウィンドウ化することにした。)前回まで設定が終わっているiframe: trueのモーダルウィンドウなら、その作業はとっても簡単だ!
モーダルウィンドウの追加
- モーダルウィンドウで表示したいページへのリンクに、:class=>"modal"を追記する。
- キャンセルリンクをモーダルウィンドウを閉じるJavaScriptに変更する。
- submitボタンを押した後のページ遷移を同じページの再表示に変更する。
以下、パスワード変更ページのモーダルウィンドウ化の作業例
- app/views/layouts/_menu2.rhtml
- 1 :class=>"modal"を追記
...(途中省略)... <div id="navcontainer"> <ul id="navlist"> <%= link_if_authorized_current 'CSVリスト', {:controller=>'csvs', :action=>'list'}, :wrap_in=>"li" %> <%= link_if_authorized_current '設定', {:controller=>'defaults', :action=>'edit_preference'}, :wrap_in=>"li", :class=>"modal" %> <%= link_if_authorized_current 'パスワード変更', {:controller=>'user', :action=>'change_password'}, :wrap_in=>"li", :class=>"modal" %><%#<------追記 %> ...(途中省略)...
- app/views/user/change_password.rhtml
- 2 キャンセルリンクをモーダルウィンドウを閉じるJavaScriptに変更
<%#= link_to _('Cancel'), :action => 'home' %> <%= link_to_function 'キャンセル', "parent.Control.Modal.close();" %><%#<------変更後 %>
- app/controllers/user_controller.rb
- 3 submitボタンを押した後のページ遷移を同じページの再表示に変更
def change_password return if generate_filled_in if do_change_password_for(@user) #redirect_back_or_default :action => 'change_password' render :action => 'change_password' #<------変更後 end end
このように、ちょっとした変更でモーダルウィンドウ化することが可能だ。しかし、やっているうちに細かなところが気になってくるものだ。現状、ウィンドウのサイズが640×480固定(以下のJavaScriptの中で設定しているため)であるが、それぞれのサブページに最適な大きさに変更したくなってきた。
- app/views/layouts/_menu2.rhtml
- レイアウト(メニューの描画を担当)
- 現状は、以下のように、JavaScriptの中でサイズを固定してしまっている。
...(途中省略)... <%= javascript_tag <<END_javascript_tag // $$('a.modal')は、<a class="modal">である要素オブジェクト(element)を全て取得する。 $$('a.modal').each(function(link){ new Control.Modal(link,{ iframe: true, width: 640, height: 480 }); }); END_javascript_tag %>
モーダルウィンドウごとにサイズを指定する
そこで、Control.Modalのページで紹介されている、id属性を利用した方法でやってみた。上記のclass属性を利用したモーダルウィンドウで表示するJavaScriptを、以下のように変更する。
- app/views/layouts/_menu2.rhtml
- レイアウト(id属性でモーダルウィンドウを表示する)
<%#= javascript_tag <// イベントを監視して、ウィンドウがロードされたら、id属性のURLをモーダルウィンドウで開く。 // $('modal_preference')は、id属性がmodal_preferenceである要素オブジェクト(element)を示す。 Event.observe( window,'load',function(){ // ユーザー環境設定用のウィンドウ new Control.Modal( $('modal_preference'),{ iframe: true, width: 576, height: 360 }); // パスワード変更用のウィンドウ new Control.Modal( $('modal_password'),{ iframe: true, width: 768, height: 480 }); // ユーザー情報編集用のウィンドウ new Control.Modal( $('modal_user'),{ iframe: true, width: 768, height: 520 }); }); END_javascript_tag %>
上記JavaScriptの変更に伴って、今までclass="modal"としていた箇所を、例えばid="modal_preference"と変更すれば、576×360サイズのユーザー環境設定用のモーダルウィンドウで表示することが出来る。リンクの中で、上記JavaScript中の$('id属性の名前')を、id属性に設定すれば、一致するウィンドウ属性で表示してくれるようになるのだ。ビューでは、以下のようにid属性を指定した。
- app/views/layouts/_menu2.rhtml
- 1 :id=>"modal_preference"に変更
...(途中省略)... <div id="navcontainer"> <ul id="navlist"> <%= link_if_authorized_current 'CSVリスト', {:controller=>'csvs', :action=>'list'}, :wrap_in=>"li" %> <li><%= link_if_authorized_current '設定', {:controller=>'defaults', :action=>'edit_preference'}, :id=>"modal_preference" %></li> <li><%= link_if_authorized_current 'パスワード変更', {:controller=>'user', :action=>'change_password'}, :id=>"modal_password" %></li> ...(途中省略)...
-
-
- id属性を利用する時は、:wrap_in=>"li"オプションは使えない...。:wrap_in=>"li"と :id=>"modal_preference"を同時に使うと、liタグとaタグの両方に同じ名前のid属性が設定されてしまい、JavaScriptが正常に動かなくなってしまうようだ。そのため、:wrap_in=>"li"を削除して、idタグで直接囲う方法に変更した。
- モーダールウィンドウを表示するJavaScriptの設定は、Control.ModalのAdvanced Usageで紹介されている通り、もっと細かな設定も可能だ。
-
パラメーターでウィンドウサイズを指定
ところが、たかがウィンドウサイズを設定するだけで、慣れないJavaScriptをその都度追記しなくてはならないのは、とても面倒に思えてきた...。モーダルウィンドウが増えたら、管理するのも大変だ。JavaScriptの中で、ウィンドウサイズもパラメーターとして受け取ることが出来れば良いのだ。試行錯誤の結果、class属性で指定する方法に戻して、以下のようにやってみた。
- app/views/layouts/_menu2.rhtml
- レイアウト(class属性でモーダルウィンドウを表示する)
- メソッド getAttribute("属性名称") を利用すると、属性名称の値を取得することが出来るようだ。
- 変数linkには、class="modal"であるaタグの1つが、オブジェクトとして代入されている。
<%= javascript_tag <<'END_javascript_tag' // $$('a.modal')は、<a class="modal">である要素オブジェクト(element)を全て取得する。 $$('a.modal').each(function(link){ new Control.Modal(link,{ iframe: true, width: link.getAttribute("width"), height: link.getAttribute("height") }); }); END_javascript_tag %>
- app/views/layouts/_menu2.rhtml
- :class=>"modal"に戻して、:width、:height属性を指定
...(途中省略)... <div id="navcontainer"> <ul id="navlist"> <%= link_if_authorized_current 'CSVリスト', {:controller=>'csvs', :action=>'list'}, :wrap_in=>"li" %> <%= link_if_authorized_current '設定', {:controller=>'defaults', :action=>'edit_preference'}, :wrap_in=>"li", :class=>"modal", :width=>576, :height=>360 %> <%= link_if_authorized_current 'パスワード変更', {:controller=>'user', :action=>'change_password'}, :wrap_in=>"li", :class=>"modal", :width=>768, :height=>480 %> ...(途中省略)...
これで、複数のウィンドウに自由にサイズ指定できるようになった!
参考ページ
JavaScriptについて、以下のページが大変参考になりました。感謝です。
*1:画面左上のユーザー名のリンクで移動するページ