IE9でprototype.js + Shadowbox.jsを使う場合のメモ
2012.06 05

IE9なら、モダンブラウザに近づくから面倒なIE対応は減るはず、というのは幻想で余計に手間が増えるケースもあります。今回は限定されたシチュエーションですが、JavaScriptライブラリを使う場合の対応をまとめました。

事の発端はIE9利用時のフィードバック

サムネイル表示にShadowbox.jsというライブラリを使用していました。これはいわゆるLightbox系なのですが、導入した当時はjQuery移行が活発で、prototype.jsをベースにしたものがあまり無かった中では貴重な存在でした。

今回、リリースから4年ほど経過しているシステムの追加機能をリリースしたのですが、IE9の場合にサムネイル表示されない現象が発生しました。再現してみると、クリックすると画像への直リンクとなってしまいます。

問題はprototype.jsの古さとdoctype

prototype.jsは1.7 RC3でIE9のフルサポートが完了したようです。また、Shadowbox.jsのフォーラムではdoctypeをhtml5にしたら正常に動いたということで、prototype.js 1.7 stableにアップデートしつつdoctypeをxhtml 1.0からhtml5としたところ、標準モードで問題なく動作するようになりました。IE7とIE8についても問題ありません。(IE6はもういいでしょう・・・)

イベントモデルの変更が原因?

IE9ではDOM L3のサポートで独自のattachEvent実装などがなくなっているようです。prototype.jsのソースを少し読んでみると、新しいものではブラウザ判定の処理が異なっており、イベントハンドラにまつわる記述に変更があります。この辺が影響しているようです。

ブラウザサポートはライブラリやソースのメンテナンス、リファクタリングを伴う契約に

問題は、こういった検証や修正は請求対象となるか否かでしょう。今回は無償対応としたのですが、こういったケースを想定した保守費用や継続的製作費を説明もしくは計上しておくのも、製作者サイドには大事かと思います。Androidの世界はもっと大変かもしれません。

ソフトウェアの最大のメリットは、「後から直せる」ことです。しかし、こういった特定のベンダに依存した環境で製作を行なっていくことは、「後出しジャンケンされる」ということでもあります。

SIerの世界では、そういったケースにそなえた予算取りなどが確立している所も多いですが、正直、がんじがらめにされたユーザが訳もわからず搾取されているケースもあります。AppleがFlashを全面廃止した時と同じように一寸先は闇ですが、3年以上の稼働を想定したシステムなどは、こういったケースでクライアントに理解を得られるよう平時からの情報共有が大事だと改めて思いました。

この記事へのコメント

jFeedMixer – 複数RSSフィードを統合してウェブサイトに表示するjQueryプラグイン
2010.08 30

このエントリはjFeedMixer専用ページへ移行しました。今後は、そちらを御覧ください。 複数ブログで管理しているRSSフィードを統合して、ウェブサイト上に表示させることができるjQueryプラグイン、jFeedMix […]

このエントリはjFeedMixer専用ページへ移行しました。今後は、そちらを御覧ください。

複数ブログで管理しているRSSフィードを統合して、ウェブサイト上に表示させることができるjQueryプラグイン、jFeedMixer 0.2.0 をリリースします。このプラグインはGoogle AJAX Feed API を使用しているので、ご利用の場合は、AJAX API Keyを事前に取得する必要があります。

jFeedMixer 0.2.0 – github

jFeedMixerを使うシチュエーション

複数ブログを管理していて、メインサイトのトップページに各ブログのRSSフィードを時系列順で表示したい。

デモ

デモページへ

jFeedMixerの使い方

scriptタグで各ライブラリを読み込み、任意のdivを指定してjFeedMixerを呼び出します。





表示オプション

feeds: ["feed URL", "…"]  必須
複数のフィードURLを指定できます。RSS、Atomなどが表示されるURLを指定してください。
countPerFeed: 数値 オプション(デフォルト: 5)
1フィードURLあたり取得するフィード数です。例えば、「5」と指定して、feedsに2つのURLを指定した場合は10件のフィードが表示されることになります。
countLimit: 数値 オプション(デフォルト: 10)
表示フィードの最大件数を指定します。countPerFeedと併用でき、feedsに2つのURLを指定し、countPerFeedを10と指定した場合、全体の件数は20件ですが、このオプションを指定すると、上位10件が表示されます。
feedFormat: "http://your.site.com/js/feed.jfm.html" オプション

デフォルト:

			%title【%blogTitle】(%date)[%category]
		
フィード表示のフォーマットを指定できます。「.jfm.html」を含むファイル名を指定した場合、ファイル中で指定したテンプレートを利用して結果を出力します。サンプルファイルのテンプレートは以下のようになっています。

			
%title %blogTitle
%date %category
使用可能なパラメータは以下のとおりです。

  • %link: フィードへのリンク(URL)
  • %title: フィードのタイトル
  • %date: フィードの投稿日
  • %blogTitle: フィードを管理するブログのタイトル
  • %blogURL: フィードを管理するブログのURL
  • %category: フィードのカテゴリ
beforeFeeds: "<dl>" オプション(デフォルト: "<ul>")
feedFormatオプションで指定した出力結果全体の「前」に付加される文字列を指定できます。
afterFeeds: "</dl>" オプション(デフォルト: "</ul>")
feedFormatオプションで指定した出力結果全体の「後」に付加される文字列を指定できます。
dateFormat: "日付フォーマット" オプション(デフォルト: "yyyy.mm.dd")
フィードの投稿日を表示する際のフォーマットを指定できます。

  • yyyy: 西暦
  • mm: 月(1桁の場合はゼロパディング)
  • dd: 日(1桁の場合はゼロパディング)
  • H: 時(1桁の場合はゼロパディング)
  • i: 分(1桁の場合はゼロパディング)
  • s: 秒(1桁の場合はゼロパディング)
feedFormatオプションで指定した出力結果全体の「後」に付加される文字列を指定できます。
カテゴリが複数の場合、指定の区切り文字を挿入して表示します。

補足

  • 表示されるフィードはdiv > ul > li > フィード の形式で表示されます。
  • 表示結果などの詳しい説明は README_ja を御覧ください。
  • 要望、質問などは info@calmtech.netまで。

ライセンス

jFeedMixerはGPL、MITライセンスのもと作成されています。

リリースノート

  • 2010.08.30 jFeedMixerを公開
  • 2010.08.31 カテゴリ表示、表示の最大件数オプションを追加
  • 2010.09.07 テンプレート指定、前後に任意テキスト表示のオプションを追加

この記事へのコメント

Shadowbox.jsをAjax.Updaterと併用する
2009.10 29

Lightbox系のライブラリとして任意のJavaScriptライブラリを使ってもOKなShadowbox.js。 非常に便利でおすすめ。私はprototype.jsをよく使うのでそれと併せています。jQuery対応のも […]

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のその後
2009.06 27

前回のエントリでIE7でAjaxリクエストの挙動がローカルとリモートで異なる件に触れた。 で、その後の調査結果。 IE7でJavaScriptを含んだプログラムを動かすと、ActiveXコントロールを含んでいるけど大丈夫 […]

前回のエントリでIE7でAjaxリクエストの挙動がローカルとリモートで異なる件に触れた。

で、その後の調査結果。
IE7でJavaScriptを含んだプログラムを動かすと、ActiveXコントロールを含んでいるけど大丈夫?というポップアップがブラウザ上で表示される。動いてくれないと困るので、「はい」と答える。これが落とし穴。

この時点でActiveXObjectを使って動く前提とブラウザは思いこんでしまう模様。にも関わらず、XMLHttpRequest判定を前に持ってきているので、そっちでリクエストを投げようとするのが不整合の原因のようだ。

そう、つまりリモートにコンテンツを配置した場合はXMLHttpRequestで扱うとブラウザが思ってくれるので、エラーはでなくなるということだろう。うん、やっぱりXMLHttpRequestに統一してくれとして言えない。

ここからは最近なんとなく思うこと。Ajaxってもう、終わりな気がする。というかHTMLで何でも表現するのはいい加減限界だし、DojoやExt.jsのようなリッチUIを用意するのもブラウザ互換吸収とかで苦労するし、無理がきていると感じる。
なのでUI部分をFlashにという流れが今は主流なのだけど、コントロールの出来でいったらSilverlightのが上だろと思うので、棲み分けを作る側が理解して使い分けるのが正解なんだという当たり障りのない結論に落ち着いた。

とりあえず、業務アプリのUIはSilverlightでいきたい。今はまだFlashかなと思う。後々の浸透度次第か。

この記事へのコメント

IE7でローカルからXMLHttpRequestを使うとエラー?
2009.06 19

ActiveXObjectの判定タイミングは前か後か? とある案件でここと同じであろう現象に遭遇。 IE7からXMLHttpRequestとActiveXObject両方に対応するようになっており、ActiveXObje […]

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対応しないという契約だったので、よくよく考えてみればこれって、有償にしていいんじゃないか?

冗談はさておき、ブラウザのバグとか仕様解釈の違いをこれだけシェアの大きいソフトウェアで製作者に押しつけたままというのは不満。だけど、それもプログラマの仕事という事実なのは否定できない。

この記事へのコメント

jQueryベースのフォーム入力チェックを実装中
2009.04 23

CSS-Nite Aomoriで5分プレゼンを行うので、その準備中。 それと並行して、自分のサイトをWordPressベースで作ってみた。というか、テーマとして作るという宿題がほったらかしだったという。 で、RubyでY […]

CSS-Nite Aomoriで5分プレゼンを行うので、その準備中。
それと並行して、自分のサイトをWordPressベースで作ってみた。というか、テーマとして作るという宿題がほったらかしだったという。

で、RubyでYAML形式の定義を元にFormを自動生成したくて、ちまちま書いているのだけど、せっかくだしvalidationはjQueryで作ってみることにした。巷にあふれているものではあるけど、自分の勉強がてらだ。

jQuery自体はバージョンいくつの頃だろう・・・だいぶ前に、prototype.jsとjQueryどちらをベースにしていくか?というテーマがプロジェクト内であって、jQueryの挙動が気に入らず、prototype.jsでいくことに。Railsもprototype.jsが前提なんだけど、あまりにjQueryの名前を聞くようになったし、今だと良くなってるのかもね?と思って使ってみた。バージョンは1.3.2。

 確かにCSSセレクタを使ってDOMにアクセスできるのは快適だし、直感的に書けるコードも多いのだけど、ちょっとHTMLやセレクタが複雑になってくると、思うように要素がとれなかったり、Arrayで値が返ってくるのかjQueryオブジェクトが返ってくるのかがまちまちだったりと、複雑なことやろうとすればするほど、DOM直接いじってる方が楽だな・・・とか思ってしまう。正しい使い方ができてないのだろうか?

$の挙動からいけば、やはりprototype.jsが自分には合っているようだ。というか、まずブラウザ側の挙動を統一してほしい。それに尽きる。挙動の違いを吸収してほしくて、javascriptフレームワーク使っているようなもんだし。今更すぎる内容だけど、改めて使ってみても、やはり思うことは同じだったりする。

となると、棲み分けなのだろうという結論。すでに固定のHTMLがあって、それに対して簡易的なエフェクトやDOM操作を行うなら、jQueryは非常に効率的だと思う。逆に何らかのデータフォーマットやHTTPレスポンスを元にHTML生成したりと、動的な実装をしたいのであればprototype.jsかなと思う。

エフェクトやGUIなどオールインワンのライブラリを求めるなら、Ext.jsかDojoあたりなのだろうか。思い立つことがあれば、今度はそっち側を試してみようと思う。

この記事へのコメント

作者について

青森県内でソフトウェア・システム開発を行うフリーランスのプログラマー。元々は集中監視システム開発に従事。現在はウェブサイト製作・オンラインシステムの開発案件を中心に、プログラミングのスキルトレーニングや講演も行う。

TEL 0172-55-7030  FAX 0172-55-7031
10:00 - 18:00 土日祝休

恐れ入りますが、お急ぎの場合を除いて、メールにてお問い合わせください。