こんにちは、太田です。前々回はJSONP、前回はXMLHttpRequestについて解説しました。今回は、ここまでの12回で取り上げた内容を使って簡単なアプリケーションを作成してみます。
アプリケーションの設計
第9回で取り上げたTwitter検索を行うJavaScriptをベースに、簡易Twitter検索クライアントを実装してみましょう。
機能は以下のとおりです。
- 任意のキーワードで検索
- 60秒おきに自動で新しい検索結果を取得
- @ユーザー名はTwitterにリンク
- URLと思われるところはリンクに
- ハッシュタグをクリックしたときはそのハッシュタグで検索
- 短縮されたURLを展開
なお、機能的にはIE 6~8もほかのブラウザと同等の実装にしますが、見た目について(具体的には角丸)はIEでは再現しません。
検索の骨組み
まずは任意のキーワードで検索する部分を見ていきましょう。まずはHTMLです。
続いて、JavaScriptです。
フォームのsubmitを使用している点がポイントで、これによりキーワードの入力後Enter(Return)したときにsubmit(検索)することができますし、(今回は実装していませんが)JavaScriptを無効にしていた場合にサーバー側で検索するように対応することも容易になっています。
なお、submitイベントの処理はaddEvent関数を定義して次のようにしてもよいでしょう。
今回のようなシンプルなアプリケーションではaddEventListener、attachEventを使うメリットは特にないので、onsubmitのシンプルな記述がよいかもしれません。
タイムラインの実装
続いて、JSONPのコールバック部分を実装していきます。まず、検索結果を表示するためのHTMLです。
id="search-result" が検索結果を表示する入れ物で、id="search-tmpl" はテンプレートです。このあたりは第9回とほとんど同じです。
さてコールバックの処理ですが、今回は「60秒おきに自動で新しい検索結果を取得」という処理を行うので、元の結果を残したまま追加するパターンを用意します。
prev_resultという変数にJSONPで取得したデータを保持しておき、そのデータがあるときはclearせずにタイムラインの追加処理だけ行うようにしています。また、prev_resultがnullのときはtimerを起動するようにしています。
自動更新の実装
先にstart_timerの中を見てみましょう。
setIntervalで1秒おきにカウントダウンを行い、0になったときにカウント用の変数を元の値に戻し、JSONPで次の結果を取得しています。
なお、timerIDとprev_resultは先程のonsubmitにおいてリセットするようにします。
HTMLの生成
では最後にwrite_timelineの処理を見ていきましょう。基本的な処理は第9回のcloneNodeによる要素の組み立てをベースに、自動更新用の処理とリンク関連の処理を加えています。
順番に見ていきましょう。
まず、treeがなければ作成します。id="search-result" な要素自身をul要素にしないのは、タイムラインをリセットする際にこのtreeを削除するだけですべての発言を削除できるからです。
続いて、前回結果のハイライトを消す処理です。
新しく追加した発言にnewクラスをつけるようにしていますが、次回の結果を得たときに前回の結果からnewクラスを削除するようにしています。新しい発言が上に来るようにしているので、前回の発言数分だけ上から処理するだけで大丈夫です。
新しい発言が上にくるようにreverseをした上で、個々の発言を作っていきます。
TwitterのAPIでは<や&などがエスケープされた状態(<、&)になっています。それを信用するならinnerHTMLに入れれば意図通りの表示ができますが、何かしらの理由でエスケープ漏れがないとも限らないので、今回はテキストノードとして扱います。そこで、<や&などを<、&に戻す処理が必要となります。
さて、テキストノードとして挿入した発言内のURLや@ユーザー名などをリンクにしてみましょう。といっても、この処理は第8回のHTML中の文字列を置換する方法で解説済みですね。
最後は短縮URLの展開処理です。こちらも第11回のJSONPの活用例で短縮URLを展開するAPIを紹介していますが、今回はあえて前回少しだけ触れたクロスオリジン通信を利用してみます。
まず、URLがある程度長い場合は短縮URLではないだろうと判断して対象外としています。今回は30文字としましたが、この値はマジックナンバーであり、改善の余地があります。/の数、ドメイン部分の長さ、?を含むかどうかなど、条件も工夫してみてもよいかもしれません。
続いて、現在のURLとAPIのURLが同一オリジンかチェックしています。同一オリジンであれば通常のXMLHttpRequestを使用します。
オリジンが異なる場合はXMLHttpRequest level 2かXDomainRequestを使用しますが、IE 6~7とOperaはそれらに対応していません。そこで、クロスオリジン通信ができない場合はJSONPを使用します。
このようにXMLHttpRequestのインタフェースを実装したオブジェクトで、内部ではJSONPを行うという力技な実装にしてみました。わざわざこういったことをせずとも、最初からJSONPを使えばよいケースなのであまり実用的ではありませんが、クロスオリジン通信のサンプルとして見て頂ければと思います。
まとめ
今回はここまでの復習として12回で取り上げた内容を使って簡単なアプリケーションを作成してみました。もし忘れているところなどがあったら是非復習してみてください。次回からはJavaScriptの基礎に再び戻って、prototypeとthisについて見ていきたいと思います。