これでできる! クロスブラウザJavaScript入門

第13回 簡単なアプリケーションの作成

この記事を読むのに必要な時間:およそ 8 分

こんにちは,太田です。前々回はJSONP,前回はXMLHttpRequestについて解説しました。今回は,ここまでの12回で取り上げた内容を使って簡単なアプリケーションを作成してみます。

アプリケーションの設計

第9回で取り上げたTwitter検索を行うJavaScriptをベースに,簡易Twitter検索クライアントを実装してみましょう。

機能は以下のとおりです。

  • 任意のキーワードで検索
  • 60秒おきに自動で新しい検索結果を取得
  • @ユーザー名はTwitterにリンク
  • URLと思われるところはリンクに
  • ハッシュタグをクリックしたときはそのハッシュタグで検索
  • 短縮されたURLを展開

なお,機能的にはIE 6~8もほかのブラウザと同等の実装にしますが,見た目について(具体的には角丸)はIEでは再現しません。

検索の骨組み

まずは任意のキーワードで検索する部分を見ていきましょう。まずはHTMLです。

検索フォームのHTML

<form id="searchform">
  <input type="search" id="searchvalue" value="JavaScript">
  <select id="searchlang">
    <option value="all">all</option>
    <option value="ja">ja</option>
  </select>
  <input type="submit" value="検索">
</form>

続いて,JavaScriptです。

検索フォームのJavaScript

var searchform = document.getElementById('searchform');
var searchvalue= document.getElementById('searchvalue');
var searchlang = document.getElementById('searchlang');
var timer = document.getElementById('timer');
var lang = '';
var TwitterAPI = 'http://search.twitter.com/search.json';
function getJSONP(query){
  var script = document.createElement('script');
  script.src = TwitterAPI + query;
  document.body.appendChild(script);
}
searchform.onsubmit = function(){
  lang = searchlang.value;
  getJSONP('?callback=TwitterCallback&lang='+lang+'&q=' +
    encodeURIComponent(searchvalue.value));
  return false; // submitをキャンセル(ページ遷移させない)
};

フォームのsubmitを使用している点がポイントで,これによりキーワードの入力後Enter(Return)したときにsubmit(検索)することができますし,⁠今回は実装していませんが)JavaScriptを無効にしていた場合にサーバー側で検索するように対応することも容易になっています。

なお,submitイベントの処理はaddEvent関数を定義して次のようにしてもよいでしょう。

submitイベントの処理

var addEvent = (document.addEventListener) ?
    function(node,type,handler){
      node.addEventListener(type,handler,false);
    }
  : function(node,type,handler){
      node.attachEvent('on' + type, function(evt){
        handler.call(node, evt);
      });
  };
addEvent(searchform,'submit',function(evt){
  lang = searchlang.value;
  getJSONP('?callback=TwitterCallback&lang='+lang+'&q=' +
    encodeURIComponent(searchvalue.value));
  // submitをキャンセル(ページ遷移させない)
  if (evt.preventDefault) {
    evt.preventDefault();
  } else {
    evt.returnValue = false;
  }
});

今回のようなシンプルなアプリケーションではaddEventListener,attachEventを使うメリットは特にないので,onsubmitのシンプルな記述がよいかもしれません。

タイムラインの実装

続いて,JSONPのコールバック部分を実装していきます。まず,検索結果を表示するためのHTMLです。

タイムラインの骨組み

<div id="search-result" class="twsrrlt"></div>
<div id="timer"></div>
<ul id="search-tmpl" style="display:none;">
 <li>
   <a class="usr" target="_blank">
     <img width="48" height="48"><br>
     <span></span>
   </a>
   <p class="entry"></p>
   <div class="time">
     <a class="source" target="_blank"></a>
     <a class="username" target="_blank"></a>
     <a class="timelink" target="_blank"></a>
   </div>
 </li>
</ul>

id="search-result" が検索結果を表示する入れ物で,id="search-tmpl" はテンプレートです。このあたりは第9回とほとんど同じです。

さてコールバックの処理ですが,今回は「60秒おきに自動で新しい検索結果を取得」という処理を行うので,元の結果を残したまま追加するパターンを用意します。

コールバックの処理

var tmpl = document.getElementById('search-tmpl').
    getElementsByTagName('li')[0];
var timeline = document.getElementById('search-result');
var tree;
var prev_result;
function TwitterCallback(data){
  if (prev_result){
    // 前回の結果に継ぎ足す場合
    write_timeline(data);
  } else {
    clear();
    write_timeline(data);
    start_timer();
  }
  prev_result = data;
}
function clear(){
  if(tree){
    timeline.removeChild(tree);
    tree = null;
  }
}

prev_resultという変数にJSONPで取得したデータを保持しておき,そのデータがあるときはclearせずにタイムラインの追加処理だけ行うようにしています。また,prev_resultがnullのときはtimerを起動するようにしています。

自動更新の実装

先にstart_timerの中を見てみましょう。

start_timerの処理

var TIME = 60, timerID;
function start_timer(){
  var time = TIME;
  timerID = setInterval(function(){
    time--;
    timer.innerHTML = time;
    if(time === 0){
      time = TIME;
      if (prev_result){
        getJSONP(prev_result.refresh_url +
            '&callback=TwitterCallback&lang='+lang);
      }
    }
  }, 1000);
}

setIntervalで1秒おきにカウントダウンを行い,0になったときにカウント用の変数を元の値に戻し,JSONPで次の結果を取得しています。

なお,timerIDとprev_resultは先程のonsubmitにおいてリセットするようにします。

submitイベントの処理#2

searchform.onsubmit=function(){
  prev_result = null;
  clearInterval(timerID);
  lang = searchlang.value;
  getJSONP('?callback=TwitterCallback&lang='+lang+'&q=' +
      encodeURIComponent(searchvalue.value));
  // submitをキャンセル(ページ遷移させない)
  return false;
};

著者プロフィール

太田昌吾(おおたしょうご,ハンドルネーム:os0x)

1983年生まれ。JavaScriptをメインに,HTML/CSSにFlashなどのクライアントサイドを得意とするウェブエンジニア。2009年12月より、Google Chrome ExtensionsのAPI Expertとして活動を開始。

URLhttp://d.hatena.ne.jp/os0x/

コメント

コメントの記入