こんばんは、Webプログラマの篠田です。
自転車で通勤をしているのですが、コート無しで疾走していると朝晩の寒さで辛い思いをしています。
今日からはコートを装備してやってきたので、もう寒さに挫けそうになることもなさそうです。
さて、本日はJavaScript(JS)特にjQueryプラグインの「jQuery modal」についてお話したいと思います。
WebプログラマといってもPHPだけを触っているわけではありませんよ(笑)
jQuery.modal.jsでハマる
「jQuery.modal.js」というのはモーダルウィンドウを簡単に作ることができるjQueryプラグインの1つです。
【公式サイト】
http://jquerymodal.com/
その「jQuery.modal.js」を使う際に、ある特定の条件がそろうと、ハマるというお話です。
問題が起きる条件
(1)モーダルウィンドウ内のコンテンツをAjaxを使って出力する
(2)モーダルウィンドウで表示されたコンテンツ内に、クリックイベントがある
(3)クリックイベントで開閉式コンテンツのようなことをする
発生する問題
すべての条件がそろった状態で、下記の手順で操作をすると問題が発生します。
(1)初回、モーダルウィンドウ表示時には、クリックイベントが正常に動作する
(2)モーダルウィンドウをキャンセルまたは、画面遷移が発生しない処理でモーダルウィンドウを閉じる
(3)もう一度、モーダルウィンドウを開いてクリックイベントを実行すると動かない
【ポイント】
この上記の問題は、Chromeのデベロッパーツールでのデバックではエラーが一切表示されませんでした。
※エラーが出ないエラーほど厄介なことはありません。
問題の記述方法を見る
まずは、公式で紹介されているAjaxを使ってのモーダルウィンドウの表示の仕方を見てみます。
1 |
<a href=“Ajaxで呼び出したいURL" id="manual-ajax">second example</a> |
1 2 3 4 5 6 7 8 |
<script> $('#manual-ajax').click(function(event) { event.preventDefault(); $.get(this.href,function(html) { $(html).appendTo('body').modal(); }); }); </script> |
これを実行することで、「外部ファイルを読み込みモーダルウィンドウで表示できる」と公式では説明しています。
というか、これしか書かれていません。
このプログラムにはある前提があります。
それが、「モーダルウィンドウ内では、動的処理を行わない」というものです。
つまり、「表示して終わり」というものであればこれで問題ありません。
ですが、「動的処理を含むモーダルウィンドウ」では正常に動作しないのです。
Ajaxでの原因
実は、「jQuery.modal.js」のAjax処理の特徴なのですが、この方法で実行すると呼び出し先のHTMLの内容を、呼び出し元のHTML内にDOMによって書き込みます。
そして、「キャンセル」などでモーダルウィンドウを閉じると、モーダルウィンドウ自体は消えるのですが、実は「display:none」で見えなくしているだけということが分かりました。
つまり、1回目は正常に動くが2回目以降で不具合が発生するのは、消えたと思っていたコンテンツが実は見ないようになっているだけで、実際にはHTML内に書かれていたということです。
例えば、クリックイベント等で下記のようなセレクタの操作を想定します。
1 |
$(‘セレクタ名’).addClass('open’); |
本来であれば、対象のセレクタに「open」というクラスを追加するとなるのですが、同じ名前のセレクタが複数あった場合、正常に動かない可能性があります。
Ajaxでの解決方法
原因が、「一度開いたことのあるモーダルウィンドウ」だとわかれば、先に開いていたモーダルウィンドウを削除してから、新しいモーダルウィンドウを呼び出してあげれば解決します。
具体的なコードは下記のようになります。
1 2 3 4 5 6 7 8 9 10 |
<script> $('#manual-ajax').click(function(event) { $(‘.modal’).remove(); //追加コード event.preventDefault(); $.get(this.href,function(html) { $(html).appendTo('body').modal(); }); }); </script> |
クラス「modal」は、「jQuery.modal.js」の指定で記述義務があるので書かれているはずですので、「modal」を持つボックスをすべて削除するために「remove()」メソッドを実行します。
その次に新しいモーダルウィンドウを呼び出してあげれば、モーダルウィンドウ内での処理が正常に動作するようになります。
まとめ
便利なモジュールやライブラリを使う際に、デモで紹介されていないような使い方をするときにハマるということはよくあります。
特に不具合が出ているにも関わらず、エラーとして検出できない場合は、DOMの更新結果を見ながら原因を1つ1つ地味に探していくしかありません。
これで少しでも同じような事案で悩んでいる方の作業コストが下がればとおもいます。
ではまたー。