GAE や Google Closure Library などの話題を扱います。python 初心者です。

2010年3月30日火曜日

Closure Library - TreeControl

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
Closure Library の goog.ui.tree.TreeControl を試してみた。
TreeControl (Closure Library API Documentation - JavaScript)

TreeControler とはエクスプローラなどでおなじみのこんなやつ。


デモコードがあるので、それを参考に簡単なサンプルHTMLを作成してみた。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <script src="http://closure-library.googlecode.com/svn/trunk/closure/goog/base.js"></script>
    <script>
      goog.require('goog.dom');
      goog.require('goog.ui.tree.TreeControl');
    </script>

    <link rel="stylesheet" href="/css/demo.css">
    <link rel="stylesheet" href="/css/tree.css">

 <script>
  var testData = ['ROOT',
  [['folderA',
   [['A1', [['fileA1-1'], ['fileA1-2']]],
    ['A2', [['fileA2-1'], ['fileA2-2']]]]],
   ['folderB',
   [['B1', [['fileB1-1'], ['fileB1-2']]],
    ['B2', [['fileB2-1'], ['fileB2-2']]]]]]];

 </script>
  </head>
 <body>
  <h1>Closure Libraray: tree control  sample</h1>
  <hr/>
  <div id="treeContainer" style="width:400px"></div> 
<script>
 function makeTree() {
  var treeConfig = goog.ui.tree.TreeControl.defaultConfig;
  treeConfig['cleardotPath'] = "/images/tree/cleardot.gif";
  var tree = new goog.ui.tree.TreeControl('root', treeConfig);

  createTreeFromTestData(tree, testData);

  tree.render(goog.dom.$('treeContainer'));
 }

 function createTreeFromTestData(node, data) {
  node.setHtml(data[0]);
  if (data.length > 1) {
   var children = data[1];
   var childNotCollapsible = 3; // Hard coded to reduce randomness.

   for (var i = 0; i < children.length; i++) {
    var child = children[i];
    var childNode = node.getTree().createNode('');

    node.add(childNode);
    createTreeFromTestData(childNode, child);

    if (i == childNotCollapsible && child.length > 1) {
     childNode.setIsUserCollapsible(false);
     childNode.setExpanded(true);
     nonCollapseNode = childNode;
    }

   }
  }
 }

 makeTree();
</script>


 </body>
</html>

closure-library付属の tree関係の画像(images/tree/*)と CSS(css/tree.css) を適切な場所に置いておくのがポイント。

実行するとこんな感じ。

2010年3月1日月曜日

Closure Library - XhrManager (3) 全部終わったかどうかを知る

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
XhrManager検証続き。

今回はXhrManagerを使い複数のリクエストを送った場合、それらすべてが終了したことを知る方法を調べる。

XhrManager 自体にはそういった機能は無いので基本的に自前で実装する必要がありそうだ。考えられる方法としては、リクエストの状態を管理しておき(未送信 or 送信済)、すべての状態が”送信済”になるかを判断する、というのがある。

具体的な方法は2つ考えられて、一つは XhrIo の処理終了毎に条件をチェックして全部終わっていたら所定の関数を呼ぶ方法。通常はこれで十分。

もう一つは一定間隔で状態をチェックし、全部終了していれば所定の関数を呼ぶ方法。一つ目に比べると複雑になるが、処理全体のタイムアウト処理を入れることができるのがメリットとしてある。


この2番目の処理にうってつけなのが以前紹介した goog.async.ConditionalDelay。

これを使うと一定間隔[ms]で関数が呼ばれ、この関数が true を返すまでは繰り返すという動作が作れる。

今回の場合、
条件:すべてのリクエストが送信済
間隔:ポーリング間隔(500ms〜1000ms ぐらいで十分?)


前回までのサンプルに手を入れて ConditionalDelay を使った終了処理を実装してみよう。
xhrio3.html
<script>
  goog.require('goog.async.ConditionalDelay');
  goog.require('goog.net.XhrManager');
  goog.require('goog.ui.CustomButton');
  goog.require('goog.ui.decorate');
</script>

<script>
    var xhrm_ = new goog.net.XhrManager(1, {}, 1, 10, 3000);

  function output(msg) {
    var console = goog.dom.$('console');
    console.innerHTML = console.innerHTML + msg + "<br/>";
  }

  function handleResponse(e) {
    var xhr = e.target;
    output(xhr.getStatus() + " : " + xhr.getResponseText());
  }

  function start(e) {
      delay.start(500, -1);
      btn_start.setEnabled(false);
      btn_cancel.setEnabled(true);
      for (i=0; i < 10; i++) {
          xhrm_.send(
              i, '/echo?name=' + i, 'GET', null, {}, 1, handleResponse);
        output('send: ' + i);
      }
  }
  function cancel(e) {
      btn_start.setEnabled(true);
      btn_cancel.setEnabled(false);
      for (i=0; i < 20; i++) {
          xhrm_.abort(i, true);
      }
      alert('cancel');
  }

  var delay = new goog.async.ConditionalDelay(
    function() {
        var count = xhrm_.getOutstandingCount();
        goog.dom.$('info').innerHTML = 'getOutstandingCount: ' + count;
        return (count == 0);
    });

delay.onSuccess = function() {
      btn_start.setEnabled(true);
      btn_cancel.setEnabled(false);
      alert('success!');
}

サンプルでは状態管理は行わず安易に XhrManagerの処理中件数(getOutstandingCount)だけで判断している。

実行してみよう。
処理中は getOutstandingCount の値が増減する。やがて終わると..
出た。

goog.async.ConditionalDelay はタイムアウト指定もできるので、複数リクエスト全体の処理時間に対してのタイムアウト処理も行うことができる。この組み合わせは、なかなか便利だ。