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

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

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

HTMLの生成

では最後にwrite_timelineの処理を見ていきましょう。基本的な処理は第9回のcloneNodeによる要素の組み立てをベースに,自動更新用の処理とリンク関連の処理を加えています。

検索結果の作り込み処理

function write_timeline(data){
  var keyword = searchvalue.value;
  var results = data.results;
  if (!tree) {
    tree = document.createElement('ul');
    tree.className = 'twl';
  }
  var items = tree.childNodes.length;
  results.reverse();
  if(prev_result){// 前回の結果からnewクラスを取り除く
    var len = prev_result.results.length;
    for (var i = 0;i < len; i++){
      var _li = tree.childNodes[i];
      _li.className = _li.className.
        replace(/(\s)+new(\s*|$)/,'');
    }
  }
  for (i = 0, len = results.length;i < len; i++){
    var usr = results[i];
    var user = usr.from_user;
    /* 要素を作る */
    var li = tmpl.cloneNode(true);
    var link = li.getElementsByTagName('a')[0];
    var icon = link.getElementsByTagName('img')[0];
    var name = link.getElementsByTagName('span')[0];
    var entry = li.getElementsByTagName('p')[0];
    var time = li.getElementsByTagName('div')[0];
    var source   = time.getElementsByTagName('a')[0];
    var username = time.getElementsByTagName('a')[1];
    var timelink = time.getElementsByTagName('a')[2];
    /* CSS用にclassを設定 */
    li.className = (((i+1+items)%2) ?
        'odd' : 'even') + ' new';
    /* リンクや画像などの属性を設定 */
    username.href = link.href = 
        'http://twitter.com/' + user;
    var src = usr.profile_image_url;
    if (src.indexOf('http') === 0) {
      icon.src = src;
    }
    icon.width = 48;
    icon.height = 48;
    timelink.href = 'http://twitter.com/' +
                user +'/status/' + usr.id;
    var d = new Date(usr.created_at);
    var date = d.getFullYear() + '/' + (d.getMonth()+1) +
           '/' + d.getDate() + ' ' + d.getHours() + ':' +
           ('0'+d.getMinutes()).slice(-2);
    /* エスケープされた文字を戻す */
    var node = document.createTextNode(usr.text.
        replace(/&(lt|gt|quot|amp);/g,function(_$,_1){
          return {lt:'<', gt:'>', quot:'"', amp:'&'}[_1];
        })
    );
    /* テキストノードの挿入 */
    entry.appendChild(node);
    linkfy(entry, '@(\\w+)', '[^\\w@]|$',
        'http://twitter.com/');
    linkfy(entry, '#(\\w+)', '[^\\w#]|$',
        'http://search.twitter.com/search?q=%23');
    linkfy(entry, '(https?://.*)',
        '[  \\)\\]\'\"\n]|$', '');
    expandUrl(entry);
    highlight(entry, keyword);
    if (usr.source){
      var match = usr.source.match(/"(http.*?)"/);
      if(match){
      source.href = match[1];
        source.appendChild(document.createTextNode(
          'from '+usr.source.match(/>(.*?)</)[1]
        ));
      }
    }
    var at_usr = '@' + user;
    username.appendChild(document.createTextNode(at_usr));
    timelink.appendChild(document.createTextNode(date));
    name.appendChild(document.createTextNode(user));
    /* 要素の組み立て */
    tree.insertBefore(li, tree.firstChild);
  }
  /* 画面に反映 */
  if (!tree.parentNode || !tree.parentNode.parentNode){
    timeline.appendChild(tree);
  }
}

順番に見ていきましょう。

treeの用意

  if (!tree) {
    tree = document.createElement('ul');
    tree.className = 'twl';
  }

まず,treeがなければ作成します。id="search-result" な要素自身をul要素にしないのは,タイムラインをリセットする際にこのtreeを削除するだけですべての発言を削除できるからです。

続いて,前回結果のハイライトを消す処理です。

ハイライトの消去

  if(prev_result){// 前回の結果からnewクラスを取り除く
    var len = prev_result.results.length;
    for (var i = 0;i < len; i++){
      var _li = tree.childNodes[i];
      _li.className = _li.className.
        replace(/(\s)+new(\s*|$)/,'');
    }
  }

新しく追加した発言にnewクラスをつけるようにしていますが,次回の結果を得たときに前回の結果からnewクラスを削除するようにしています。新しい発言が上に来るようにしているので,前回の発言数分だけ上から処理するだけで大丈夫です。

個々の発言の作成#1

  var items = tree.childNodes.length;
  results.reverse();
  for (i = 0, len = results.length;i < len; i++){
    var usr = results[i];
    var user = usr.from_user;
    /* 要素を作る */
    var li = tmpl.cloneNode(true);
    var link = li.getElementsByTagName('a')[0];
    var icon = link.getElementsByTagName('img')[0];
    var name = link.getElementsByTagName('span')[0];
    var entry = li.getElementsByTagName('p')[0];
    var time = li.getElementsByTagName('div')[0];
    var source   = time.getElementsByTagName('a')[0];
    var username = time.getElementsByTagName('a')[1];
    var timelink = time.getElementsByTagName('a')[2];
    /* CSS用にclassを設定 */
    li.className = (((i+1+items)%2) ?
        'odd' : 'even') + ' new';
    /* 後述 */
  }

新しい発言が上にくるようにreverseをした上で,個々の発言を作っていきます。

著者プロフィール

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

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

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