AJAX で、動的にテーブルを作る方法(中・上級)

先のエントリーAJAX で、動的にテーブルを作る方法(初級)では、感じをつかむために、ベタにテーブルを作成していたため、重複するロジック/コードが多かった。ここではそれをフレームワークっぽくした。こういう軽量なコードを理解した上で、ひな型として自分で持っておくと見通しがよくてよいと思う。 この JavaScript ではできるだけ Java のアプレットにならった構造やメソッド名に近づけた。つまり、
  1. 基本メソッドは、
    • createXMLHttp …xmlhttp オブジェクトを作成する。
    • get …サーバと HTTP 通信する。
    • repaint …サーバから来た XML データを使って画面を書き換える。
    • create …最初の1回だけ画面を作る。
    • init …この JavaScript の呼び出しもとの HTML から呼ばれる。
    • setTemplate …サーバから得られた XML データが表示される部分を作成する。下の例を元にカスタマイズする
    • update …サーバから得られた XML データを setTemplate で作成した id に埋め込む。下の例を元にカスタマイズする
  2. 基本プロパティは定数の場合はすべて大文字で表し、配列には英単語の複数形「s」を付けることにした。
    • INTERVAL …AJAX での通信間隔(ミリ秒)
    • OBJECT …XML データ中で、たとえば ~ イテレーションの中の タグ。その場合は OBJECT = 'book'; と、タグ名を指定する。
    • TAGS(配列) …たとえば、book タグに含まれる要素である title、author、publisher タグ
    • LABELS(配列) …テーブルのヘッダのカラムで表示したい内容
    • TH_ALIGNS(配列) …テーブルで、左から順に各カラム中のヘッダの位置
    • TD_ALIGNS(配列) …テーブルで、左から順に各カラム中のデータ位置
    • URL …AJAX で通信する URL
  3. こうすると自分で実装(カスタマイズ)する部分、すなわちメソッドは
    • setTemplate …テーブルの元となるテンプレート HTML を吐くようにする。
    • update …INTERVAL 間隔で呼び出され、テーブルのデータを更新するようにする。
    …の 2つだけでよい。
以下はこのスクリプトを呼び出す HTML 部分の例。 2007/01/10 追記: IE では、DIVタグに付けた ID を JavaScript から利用する場合は、JavaScript の前に DIV を宣言しなければならないらしい。document.getElementByID(...) is null or not an object というエラーが出る。Firefox だとその順番は関係がない。 また、document.getElementByID(DIV_DATA).insertBefore(table, null); は、IE だと table オブジェクトに tbody オブジェクトを追加してからでないとダメらしい。
<div id="data"></div>

<script src="https://<font color="red"><strong>your</strong></font>domain.com/your_javascript.js" type="text/javascript">
</script>
<script type="text/javascript"><!--

var INTERVAL = 4000; // 1sec = 1000
var OBJECT    = 'TAG';
var TAGS      = new Array('title', 'author', 'publisher');
var LABELS    = new Array('Title', 'Author', 'Publisher');
var TH_ALIGNS = new Array('center', 'center', 'center');
var TD_ALIGNS = new Array('left', 'center', 'right');  // テーブルデータの各カラム中の位置
var URL = 'https://<font color="red"><strong>your</strong></font>domain.com/your_server_process.php';
var DIV_DATA = 'data';

init();
// --></script>
動的なテーブルを作る、よりジェネリックな JavaScript は次の通り。このフレームワークでは setTemplate には何を書いてもよいが、ここでは table オブジェクトを作成することにより、HTML 中で id="data" に埋め込まれる部分にテーブルを当てはめている。また、テーブルを作成すると同時に各カラムに id="タグ名+数字" として、後に update メソッドで XML から抽出したデータを当てはめている。
//<![CDATA[

var isInitialized = false;
var isLock = false;

function createXMLHttp() {

  try {
    return new ActiveXObject('Msxml2.XMLHTTP');
  } catch(e) {
    try {
      return new ActiveXObject('Microsoft.XMLHTTP');
    } catch(e1) {
      try {
        return new XMLHttpRequest();
      } catch(e2) {
        return null;
      }
    }
  }
}

function create(xml) {
  isLock = true;
  setTemplate(xml);
  update(xml);
  isLock = false;
}

function init() {
  get(URL);
  setInterval("get('" + URL + "')", INTERVAL);
}

function repaint(xml) {
  !isInitialized ? create(xml) : update(xml);
}

function get(url) {

  if(isLock) return;

  var xmlhttp = null;

  if ((xmlhttp = createXMLHttp()) == null) {
    window.alert("XMLHTTP Initialization Failed.");
  } else {
    xmlhttp.abort();
  }

  xmlhttp.onreadystatechange = function() {
    // readyState value
    // 0: uninitialized / 1: loading
    // 2: loaded /  3: interactive /  4: complete
    if (xmlhttp.readyState == 4
    &&  xmlhttp.status     == 200) { // 200 HTTP OK
      xml = xmlhttp.responseXML;
      repaint(xml);
    }
  }
  xmlhttp.open('GET', url + '&t=' + new Date(), true);  // for avoiding IE's cache
  xmlhttp.setRequestHeader('Content-Type', 'text/html');
  xmlhttp.overrideMimeType('text/xml');  // optional
  xmlhttp.send(null);
}

function update(xml) {

  if(xml) {

    if(xml.documentElement) {  // for IE

      var objects = xml.documentElement.getElementsByTagName(OBJECT);

      for (var i = 0; i < objects.length; i++) {

        for (var j = 0; j < LABELS.length; j++) {

          var value = null;
          try {
            value = objects[i]
                  .getElementsByTagName(TAGS[j])
                  .item(0)
                  .firstChild
                  .nodeValue;
          } catch(e) {
          }
          switch(TAGS[j]) {
            case 'title':  // for example...
              value = '<strong>' + value + '</strong>';
              break;

            case 'author':  // for example...
            case 'date':
              value = value  ? value : 'n/a';
              break;
          }

          document.getElementById(LABELS[j] + i).innerHTML = value;

        } // End of for j
      } // End of for i
    }
  }
}

function setTemplate(xml) {

  if(xml) {

    if(xml.documentElement) {  // for IE

      var objects = xml.documentElement.getElementsByTagName(OBJECT);

      var table = document.createElement('table');
      var tr, td, text;

      for (var i = -1; i < objects.length; i++) {

        tr = document.createElement('tr');
        for (var j = 0; j < LABELS.length; j++) {

          if(i < 0) {  // ヘッダ

            text = document.createTextNode(LABELS[j]);
            td   = document.createElement('th');
            td.setAttribute('style',  'text-align:' + TH_ALIGNS[j] + ';');
            td.setAttribute('valign', 'center');

          } else {

            text = document.createTextNode('');
            td   = document.createElement('td');
            td.setAttribute('style',  'text-align:' + TD_ALIGNS[j] + ';');
            td.setAttribute('valign', 'center');
          }

          td.insertBefore(text, null);
          tr.insertBefore(td,   null);
          td.setAttribute('id', LABELS[j] + i);
        }
        table.insertBefore(tr, null);

      } // End of for

      document.getElementById(DIV_DATA).insertBefore(table, null);
      isInitialized = true;
    }
  }
}
//]]>
トラックバック URL: https://perltips.twinkle.cc/trackback/160
Posted on 2007-01-03 by yas |
AJAX で、getElementsByTagName で DOM にアクセスする
Trackback from Perl Tips: まずは以下のような XML データを考える。 <books> ......
Posted by Perl Tips (未認証ユーザ) on 2007/01/01(月) 10:58
AJAX で、動的にテーブルを作る方法(初級)
Trackback from Perl Tips: AJAX でサーバから XML データを読み込んでそこからテーブルを作る。今回......
Posted by Perl Tips (未認証ユーザ) on 2007/01/01(月) 10:58