Lightbox系のライブラリとして任意のJavaScriptライブラリを使ってもOKなShadowbox.js。
非常に便利でおすすめ。私はprototype.jsをよく使うのでそれと併せています。jQuery対応のものばかりで肩身が狭いですが。
Shadowbox.jsの仕様として、下記のようにheadタグ内のscriptタグで初期化する必要があります。
//日本語表示、画像とHTMLをレンダリング対象とする
Shadowbox.init({language : "ja", player: ["img", "html"]});
このためAjax.Updaterなどで部分的に反映された要素はShadowbox.jsのイベントハンドラ登録が行われていない状態です。
そこで、下記の要領でAjax.Updaterを使用後に再度イベントハンドラ登録を行うと要素の更新後もShadowbox.jsを利用できます。
私の場合はForm.EventObserverと併用しているので、その中でcallしているAjax.Updater内に記述しています。
new Ajax.Updater(id,
url,
{
asynchronous:true,
evalScripts:true,
onComplete:function(request){
//その他の処理
//最後にイベントハンドラの登録をし直す
Shadowbox.setup();
},
onLoading:function(request){
//その他の処理
//現在のイベントハンドラをすべてクリア
Shadowbox.clearCache();
},
parameters:value
})
prototype.js以外のライブラリを使用している場合も、同様にonCompleteやonLoadingに相当するイベントにフックさせれば大丈夫だと思います。
参考:
Shadowbox.js API
追記 2010.01.04
IE6, IE7の場合、Shadowbox.clearCache()を呼ばず、Shadowbox.setup()のみ呼び出すと
正常に動きます。原因はソースを追ってみないとわかりませんが、とりあえず。
また、Shadowbox.setup()の呼び出しタイミングはCGIから返されるHTMLの末尾でscriptタグ内に記述した方が良いです。
DOMのロードとJavaScript実行のタイミングを調整するためです。
前回のエントリでIE7でAjaxリクエストの挙動がローカルとリモートで異なる件に触れた。
で、その後の調査結果。
IE7でJavaScriptを含んだプログラムを動かすと、ActiveXコントロールを含んでいるけど大丈夫?というポップアップがブラウザ上で表示される。動いてくれないと困るので、「はい」と答える。これが落とし穴。
この時点でActiveXObjectを使って動く前提とブラウザは思いこんでしまう模様。にも関わらず、XMLHttpRequest判定を前に持ってきているので、そっちでリクエストを投げようとするのが不整合の原因のようだ。
そう、つまりリモートにコンテンツを配置した場合はXMLHttpRequestで扱うとブラウザが思ってくれるので、エラーはでなくなるということだろう。うん、やっぱりXMLHttpRequestに統一してくれとして言えない。
ここからは最近なんとなく思うこと。Ajaxってもう、終わりな気がする。というかHTMLで何でも表現するのはいい加減限界だし、DojoやExt.jsのようなリッチUIを用意するのもブラウザ互換吸収とかで苦労するし、無理がきていると感じる。
なのでUI部分をFlashにという流れが今は主流なのだけど、コントロールの出来でいったらSilverlightのが上だろと思うので、棲み分けを作る側が理解して使い分けるのが正解なんだという当たり障りのない結論に落ち着いた。
とりあえず、業務アプリのUIはSilverlightでいきたい。今はまだFlashかなと思う。後々の浸透度次第か。
ActiveXObjectの判定タイミングは前か後か?
とある案件でここと同じであろう現象に遭遇。
IE7からXMLHttpRequestとActiveXObject両方に対応するようになっており、ActiveXObjectの判定は後ろに持っていくべきと言われている。
が、実際のところローカルで実行するとXMLHttpRequestの判定は通るけれども、GETリクエストを投げたところで「アクセスが拒否されました」というエラーが。これはバグと言いたい。
で、結局ActiveXObjectの判定を前にもってくることで解決。腑に落ちない。
if (window.ActiveXObject) {
req = new ActiveXObject("Microsoft.XMLHTTP");
if (req) {
req.open("GET", url, false);
req.send();
}
} else if (window.XMLHttpRequest) {
req = new XMLHttpRequest();
req.open("GET", url, false);
req.send(null);
}
ちょっとしたテストをすると、XMLHttpRequestでもActiveXObjectでもtrueとIE7はなる。うーん、善し悪しだこれは。
そうじゃない、ちゃんと仕様を統一してください。
ちなみに、上記の修正を行う前にはFirefoxとChromeは問題なし。IE7とSafariはNG。
やはりいらない子なのか。
とある案件のクライアントは、それまでIE6を使用していたことを考慮すると、IE7の使用率が増えたことでこういった不具合が起きている可能性があるかもしれない。この案件のリリース時はIE7対応しないという契約だったので、よくよく考えてみればこれって、有償にしていいんじゃないか?
冗談はさておき、ブラウザのバグとか仕様解釈の違いをこれだけシェアの大きいソフトウェアで製作者に押しつけたままというのは不満。だけど、それもプログラマの仕事という事実なのは否定できない。