UIEngine だ

技術者諸君これを使い給え。UIEngine(ユーアイエンジン)は携帯電話上でAJAX的なインタフェースを簡単に実現できる技術です。このブログではUJMLサンプルの紹介 UIEngineについて UJMLで作る便利なツール 等を載せています。

stopwatch.ujmlに見る、delayの使い方

2000  SDKに付属するstopwatch.ujmlについて解説する。

 stopwatch.ujmlはその名のとおりストップウォッチである。一秒毎に画面上に秒数が表示されていく。今回解説するのはこのサンプルにおける<delay>要素の使い方。まずは、ソースコード(抜粋)を参照。

<delay>に指定するミリ秒数について:

 <delay>要素で指定したミリ秒後に<script>要素内が実行されるはずだが、実行キューに他の処理がたまっていると指定した時間に処理が始まらない可能性がある。それをできるだけ避ける方法がstopwatch.ujmlに含まれている。

 これまで紹介したサンプルにも同じようなタイマーを実現したものがあるが、<delay>要素に1,000ミリ秒を指定していた。実は1,000ミリ秒を指定するよりもstopwatch.ujmlのように100ミリ秒を指定した方がより正確に画面上に秒数を描画できる。もちろん、100ミリ秒を指定した場合には太字のソースコード部分のように、都度実際の経過時間を測定し、必要があれば描画するという方法にしなければならない。

            <state var="sTimer">
                <transition value="true">
                    <delay>&DELAY_MSEC;</delay>
                    <script>
                      
// Check and see if a second has passed since the
  // last check.
                        mMSecElapsed = _msec();
                        if ((mMSecElapsed - mMSecStart) &_GTE; 1000)
                        {
                           
// Update the seconds display.
                            mLastSec = (mMSecElapsed - mMSecStart) / 1000;
                            _clear_state(sSeconds);
                            sSeconds = sSeconds;
                        }
                        
                      
// Update the timer.
                        _clear_state(sTimer);
                        sTimer = sTimer;
                    </script>

                </transition>
            </state>

※stopwatch.ujmlにはよろしくない部分もあるので念のためメモ

・ステート変数sSecondsの<state>要素内で<label>が何故か重複している。ヴィジュアル要素の子要素にヴィジュアル要素を指定しても問題無いのでコンパイルは通るが、これは意味が無い。

・sSecondsの値trueに対応する<transition>要素内にファンクションキーの描画(<fn>)があるが、毎秒再描画されることになり無駄な気がする。ファンクションキーの描画を管理するステート変数を別に用意した方が良いのでは?と思うが、その場合コンパイル時のファイルサイズが大きくなってしまう(20Byteぐらい)。どうしたものか。

2006/10/31 カテゴリー: UJML Source解説 | 個別ページ | コメント (0) | トラックバック (0)

if-def を使って効率的な開発を目指そう

Ifdef  UJMLではifdefを使うことができる。これは便利だ。デバッグ環境とリリース時とで異なる動作をさせたい、あるいは異なる値を使いたいといったときに重宝する。

 リリース時に毎回値を書き換える、ソースコードを書き換えるといったことをせずに済む。良く使うのは、UIEngineのWEBアプリケーションを開発しているときだ。デバッグ環境と本番のリリース時では異なるサーバーにアクセスさせたいときがある。私は良くデバッグ時には localhost にアクセスさせ、リリース時には本当のURLにアクセスさせるようにしている。

 使い方は以下のような感じである。

<?ujml-ifdef DEBUG?>
         mAppPath = "localhost";
<?ujml-else?>   
         mAppPath = "www.uiengineda.com";
<?ujml-endif?>   

開発効率化のためにお試しあれ。

---

【おまけ】 YouTube で見つけた11歳のすごい少女 はてなブックマーク等でも注目
YouTube - Amazing 11 year old!!!
http://www.youtube.com/watch?v=fVU27eLOclU&mode=related&search=

2006/07/09 カテゴリー: UJML Source解説 | 個別ページ | コメント (0) | トラックバック (0)

UIE社から公開中のデータバインディングモジュール(Recordset)のサンプルが新しくなった

Zipcodeconverter このブログで、UIEが公開しているデータバインディングのサンプルの解説を行ってきたが、そのサンプルのアップデート版がリリースされたようだ。

Zipcode converter Java Applet HTML Page

以前のエントリーで、このサンプルがわかりにくくとっつきにくいため、新しくUIEngineを学び始めた人もこのモジュールを使わずに独自にモジュールを作るという世の中的非効率を産み出していたと思う。そのエントリーの声が聞こえたかどうかは定かでは無いが、以下の内容が修正・追加されたとのこと。

・PHPのサンプルがWindowsでも動作するようになった。
・サーバー側で生成されるバイナリーの元コード(UJML)がサンプルに追加された。

 ちなみに、当ブログでこのモジュールについて触れたエントリーは以下のもの

・UIEvolutionのラボで公開されているRecordsetについて考察 ソースコードにコメントで解説
・UIEvolutionのラボで公開されているRecordset のソースコード解説 サーバーサイド RecordSet.php
・UJMLサンプル137:RecordSetサンプルの超簡易サンプル
・「孤独なシナプス」さんの取り組みを見て思うこと

2006/07/09 カテゴリー: UJML Source解説, ブログ(お知らせ)? | 個別ページ | コメント (0) | トラックバック (0)

「孤独なシナプス」さんの取り組みを見て思うこと

Kodokuna_server 孤独なシナプスさんがサーバー側のデータをクライアントに取り込むことを実現しようとがんばっている。今のところ、単純なバイナリーを生成し、サーバー側のデータをujbc化してクライアントに渡す方法を取ったようだ。

孤独なシナプス
http://d.hatena.ne.jp/yellowseadog/20060624/1151135451

私もRSSをUIEngineアプリに読ませようとして全く同じ試みをした。もちろん、それが自分が作ったスクリプトであっても作成されるujbcはUIEngineの仕様に準拠してさえいれば問題無く動作する。ちなみに私が取り組んだときのものは「RSS→ujbc化してUIEngineで表示させられるようになった。」。

 ここに来て思うことは、UIE社が公開したデータバインディングのサンプルはとっつきにくいに違いないということだ。極めて使いやすいモジュールになっていれば「孤独なシナプス」さんも自分でバイナリー生成コードをPHPで書くようなことは無かったのではないか?と予想する。

 孤独なシナプスさんはPHPで以下のようなものを書いているが、UIEが公開したRecordSet.phpも似たようなものだ。うーん実にもったいないではないか。是非、あちらでうまれた知識をこちらに容易に移転できるように、そんな環境を作って生きたいものである。

function generateUJBC( $str )
{
    return    "ujbc\x03\x00\x00\x00\x00\x1ACopyright UIEvolution Inc.\x02\x0A".
            "\x03".
            "\x00\x11sRequestSucceeded".
            "\x00\x0FmResponseString".
            pack( "n", strlen($str) ).
            $str.
            "\x10\x09\x00\x60\x02\x49\x01\x03\x4A\x00\x00\x04\x01\x22\x00\x05\x01\x21\x01\x08\x01\x00\x00";
}

---

【おまけ】YouTubeで面白い動画を見つけたので紹介
YouTube - Jump On It
http://www.youtube.com/watch?v=f4SaDAE_YtQ&search=soccer

2006/07/08 カテゴリー: UJML Source解説 | 個別ページ | コメント (0) | トラックバック (0)

UJMLサンプル137:RecordSetサンプルの超簡易サンプル

Samples_137_bind  前回、前々回とUIEvolutionから開発者向けに公開されたサーバー/クライアントのデータバインディング用ソースコードの解説をしてきた。

UIEvolutionのラボで公開されているRecordset のソースコード解説 サーバーサイド RecordSet.php

UIEvolutionのラボで公開されているRecordsetについて考察 ソースコードにコメントで解説

UIEvolutionからこのデータバインディングツールをどのようにして使うか?というチュートリアルのようなものは出ていないので、今回、公開されたコードから不要なものを落とし、簡易サンプルとすることでチュートリアル的な役割を果たせたらと思っている。

◆動作環境

 もし手元で動作を見たい場合には、手元にPHPが動作する環境が必要になる。そのほかはUIEngineのSDKがあれば期待通り動くはずだ。

◆セットアップ方法

 ソースコードは圧縮してDLできるようにした。サーバー側のPHPスクリプトは

http://localhost/uie/sample.php

のようにアクセスできる場所に配置する。クライアントのソースはそのまま解凍し、SDKでmain.ujmlを開けばOKだろう。

◆動作

 サーバー側のsample.phpにて

$data = array(array("0","01"), array("012", "0123"));
$rset = new RecordSet(0, $data, 2, 3);

としてデータをセットし、クライアント側でそれを表示する。ただそれだけである。

ソース等ダウンロード:
クライアント Download 137_recordset_sample.lzh
サーバー Download uie.lzh

2006/07/07 カテゴリー: UJML Samples, UJML Source解説 | 個別ページ | コメント (0) | トラックバック (0)

UIEvolutionのラボで公開されているRecordset のソースコード解説 サーバーサイド RecordSet.php

Ziptocity_php 前回、クライアントサイド(UJML)で重要となるソース llmodel.ujms について解説した。「もう少し丁寧に頼む」という声もあったりなかったりだが、まずは一通り解説するために先に進む。

※このエントリーは初めて本ブログに来た方が読むには敷居が高い。まずは、初心者向けまとめページに目を通すことをおすすめする。

UIEvolutionのラボで公開されているRecordsetについて考察 ソースコードにコメントで解説

 今回解説するのはサーバーサイドのスクリプトの使い方である(PHPを主として解説していく)。サーバーサイドの処理を簡単に解説すると、

「RecordSet.phpというモジュールを活用し、動的にujbcを生成する。」

ということである。公開されているサンプルの ziptocity.php のソースコードは以下の通りである。
※色分けは今のところXMLのみ対応なので、一色で見にくいのは見逃して欲しい。

<?php
require "RecordSet.php";
$command = "cut -d ',' -f 2,3,4 zips.txt |grep " . $HTTP_GET_VARS['uid']; 
$text_record=exec($command);
list($file_zip,$file_state,$file_city, $fline) = split(',', $text_record, 3);   

$data = array(array("post"), array("2"), array("true"), array($file_city,$file_state) );
$rset = new RecordSet(0, $data, 2, 3);
header('Content-type: application/ujml');
header("Content-Transfer-Encoding: binary");
$bytes = $rset->generate();
$new_length = strlen($bytes);
header("Content-Length: $new_length");
print $bytes;
?>

重要なのは太線部分である。まず、

$data = array(array("post"), array("2"), array("true"), array($file_city,$file_state) );

で、クライアントに渡したいデータを生成している。データ内容は無視して欲しい。とにかく

「配列で渡したいデータを作成する。」

のだ。そして、

$rset = new RecordSet(0, $data, 2, 3);

で、ujbc 作成させる。最初の引数 0 はUJML側のhandlerと対応、最後の二つは recordsets.ujms の変数 mFields の配列サイズに対応している。

※このmFieldsの配列サイズがずれていると期待通りに動作しないので注意!
Import variable "RecordSet.sData" failed.
というエラーメッセージが出たら、配列サイズが同じになっていないのであわせること!サンプル作成中にここがずれていることに気づかず3時間以上格闘していた。

 このように使い方は極めて簡単である。RecordSet.phpのPerl版、Ruby版、JSP版、それぞれ同じような仕組みで動いているのでいずれも簡単である。

 今回はここまで。

2006/07/07 カテゴリー: UJML Source解説 | 個別ページ | コメント (0) | トラックバック (0)

UIEvolutionのラボで公開されているRecordsetについて考察 ソースコードにコメントで解説

Recordset_sample 今回はUIEvolution社から公開されたデータバインディングサンプルのソースコードを解説する。当ブログでも何度か部分的な解説をしてきたが、これから何回かで自分用のものを作る際の修正点を含めて解説していく予定だ。予定は未定だが。

※このエントリーは初めて本ブログに来た方が読むには敷居が高い。まずは、初心者向けまとめページに目を通すことをおすすめする。

 ちなみに以前、当ブログで解説したエントリーはこちら

「Zipcode converter app」で学ぶ その1 _link()の使い方

 ソースコードはもちろんUIEvolution開発者のブログ

UIEvolution Developer Blog.
http://www.uievolution.com/blogs/developer/

にて以前公開された、

UIEvolution Developer Blog.: Databinding
http://www.uievolution.com/blogs/developer/2006/04/databinding.html

を活用する。

 まず重要なファイルは llmodel.ujms というものだ。このファイルでサーバーからのデータをパースする。バインドするデータのモデルを変更したらこのファイルを変更する必要がある。ここを正しく書き換えることさえできれば、UIEから公開されたものを使いこなせるようになったと言えるだろう。

 では、いきなりだが llmodel.ujms のソースコードを貼り付け、コメントにてその解説を入れる。

※コメントがうまく緑色になっていない部分があるが、ご容赦頂きたい。

<?xml version="1.0"?>
<!DOCTYPE ujml PUBLIC "-//UIEVOLUTION//DTD UJML 1.5//EN" ""[

<!ENTITY MAX_LIST_COUNT "50">

<!ENTITY % modelconsts SYSTEM "llmodelconsts.ent">
  %modelconsts;
 
<!ENTITY % recordset SYSTEM "recordset.ent">
  %recordset;

 
<!ENTITY HPOST  "0">
 
<!ENTITY RECORDSET_HANDLE_COUNT "2">

<!-- uiengineda.blogs.com お、jsp,perl,ruby,php版があるのね。 -->
<!--
 
<!ENTITY LOCALHOST_SERVLET_CONTEXT "http://localhost:8080/rsdemo/">
 
<!ENTITY POST_URL "ziptocity.jsp">
 
<!ENTITY LOCALHOST_SERVLET_LANGUAGE "Java recordset compiler">
 
 
<!ENTITY LOCALHOST_SERVLET_CONTEXT "http://lab.uievolution.com/cgi-bin/">
 
<!ENTITY POST_URL "ziptocity.pl">
 
<!ENTITY LOCALHOST_SERVLET_LANGUAGE "Perl recordset compiler">
 
 
<!ENTITY LOCALHOST_SERVLET_CONTEXT "http://lab.uievolution.com/cgi-bin/">
 
<!ENTITY POST_URL "ziptocity.rb">
 
<!ENTITY LOCALHOST_SERVLET_LANGUAGE "Ruby recordset compiler">
-->


 
<!ENTITY LOCALHOST_SERVLET_LANGUAGE "PHP recordset compiler">
 
<!-- <!ENTITY LOCALHOST_SERVLET_CONTEXT "http://lab.uievolution.com/rs/">  --> 
 
<!ENTITY LOCALHOST_SERVLET_CONTEXT "../../../rs/">
 
<!ENTITY POST_URL "ziptocity.php"> 


 
<!-- ここの定数もモデル独自の実装となるので適宜書き換える -->
 
<!-- zipcode to city/state recordset data format -->
 
<!ENTITY POST_HEADER_RECORD "0">
 
<!ENTITY POST_HEADER_SIGNATURE_VALUE "post">
 
<!ENTITY POST_LIST_SIZE_RECORD "1">
 
<!ENTITY POST_STATUS_RECORD "2">
 
<!ENTITY POST_CITYSTATE_RECORD "3">

]>

<!--
    uiengineda.blogs.com
    サーバー側のデータとバインドするためのモデル
    モデルを変更する場合にはこのソースコードを変更して対応する
    重要なのはたぶんこの辺↓
   
<state var="RecordSet.sEvents" index="&HPOST;">
   
    インデントがばらばらだが、しばらく気にしないで頂戴な。TODO 修正
    強制的に整形してくれるEmeditorのプラグインなかったかな? TODO 探す
-->

<!--
  llmodel.ujms
  Copyright (c) 2006, UIEvolution, Inc.

  Convert zipcode to city/state, client side.
-->


<ujml>
  <partition>
    <state-machines>
      <state-machine name="LLModel">
        <state-variables>
          <!-- load state notification/completion -->
          <!-- postScoreResponse -->
          <state-var name="sPostResponseLoaded" type="int" visibility="public"/>
        </state-variables>

        <variables>

           <var name="mstServletContext" type="string"/>

           <var name="mUserCity" type="string"/>
           <var name="mUserState" type="string"/>
           <var name="mbPosted" type="boolean"/>

          <!-- high score data -->
           <var name="mcHighScores" type="int"/>
           <var name="mstHighScoreDisplayString" type="string" size="&MAX_LIST_COUNT;"/>

          <var name="mLoadHandle" type="int" size="&RECORDSET_HANDLE_COUNT;"/>
        </variables>

        <functions>
            <!-- ここから共通関数 特に変更の必要無し -->
            <!-- set different servlet context for testing -->
            <function name="setServletContext" type="void" visibility="public">
                <parameters>
                    <var name="st" type="string"/>
                </parameters>
                <script>
                    mstServletContext = st;
                </script>

            </function>
            <function name="getServletContext" type="string" visibility="public">
                <return><eval>mstServletContext</eval></return>
            </function>
            <function name="getServerLanguage" type="string" visibility="public">
                <return><eval>"&LOCALHOST_SERVLET_LANGUAGE;"</eval></return>
            </function>
            <!-- revert to built in default servlet context -->
            <function name="resetServletContext" type="void" visibility="public">
                <script>
                    setServletContext(
"");
                </script>

            </function>
            <!-- ここまで共通関数 -->


            <!-- ここからモデル毎に書き換えること! -->
            <!-- score posting function -->
          <function name="zipLookup" type="void" visibility="public">
              <parameters>
                  <var name="stZip" type="string"/>   
              </parameters>
              <variables>
                <var name="stParams" type="string"/>
                <var name="stServletContext" type="string"/>
              </variables>
            <script>

              if (_strlen(stZip) == 0)
              {
                  stZip =
"98052";
              }
              else
              {
                mUserCity = stZip;
              }

              stParams = _strcat(
"&amp;uid=", stZip);

              stServletContext =
"&LOCALHOST_SERVLET_CONTEXT;";
              if (_not(_streq(mstServletContext,
"")))
              {
                stServletContext = mstServletContext;
              }

              mLoadHandle[&HPOST;] = RecordSet.openEx(
"&HPOST;",
                        _strcat(stServletContext,
"&POST_URL;"),
                        stParams, true);

              _clear_state(sPostResponseLoaded);
              sPostResponseLoaded = &LLMODEL_LOAD_PENDING;;

            </script>

          </function>
          <function name="getUserCity" type="string" visibility="public">
            <return><eval>mUserCity</eval></return>
          </function>
          <function name="getUserState" type="string" visibility="public">
            <return><eval>mUserState</eval></return>
          </function>

          <function name="getPostStatus" type="boolean" visibility="public">
            <return><eval>mbPosted</eval></return>
          </function>
            <!-- ここまで -->

    </functions>

<states>
<!-- ああ、こういうコードになっちゃうのねやっぱり 汎用的なものだからしょうがないか -->
<!--
    uiengineda.blogs.com
    ここ以降はモデル独自の実装になるので毎回書き換えないといけない
    ポインタの移動を適切にやる必要があるので、サーバー側で生成されるデータの仕様を理解している必要有り
    その辺を隠蔽できるとスマート
-->

<!-- record set event catching -->
          <state var="RecordSet.sEvents" index="&HPOST;">
          <transition value="0">
              <variables>
                  <var name="iLoadStatus" type="int"/>
                  <var name="iPostStatus" type="int"/>
                  <var name="cPostListItems" type="int"/>
              </variables>
            <script>
               
<!-- たぶん_link()が成功するとここに来る by uiengineda-->
                iLoadStatus = &LLMODEL_LOAD_FAILED;;
// うまくデータロードできたかどうかのフラグを「失敗」で初期化
                mbPosted = false;

                if (RecordSet.moveTo(mLoadHandle[&HPOST;], &POST_HEADER_RECORD;) == mLoadHandle[&HPOST;])
                {
                  
// 先頭のフィールドの値が所定の値"post"と同じかどうかチェック(今のところ何のためにやっているか不明)
                    if (_streq(RecordSet.getField(mLoadHandle[&HPOST;], 0), "&POST_HEADER_SIGNATURE_VALUE;"))
                    {
                      
// レコードのサイズが入っているところまでポインタを移動?
                        RecordSet.moveTo(mLoadHandle[&HPOST;], &POST_LIST_SIZE_RECORD;);
                      
// レコードのサイズを取得
                        cPostListItems = _string_to_int(RecordSet.getField(mLoadHandle[&HPOST;], 0));
                        if (cPostListItems &gt;= 1)// サイズが1以上
                        {
                           
// ステータスが入っているところにポインタを移動
                            RecordSet.moveTo(mLoadHandle[&HPOST;], &POST_STATUS_RECORD;);
                           
// データを取得してtrueかどうか判定、trueなら上手く読めたということか?
                            if (_streq(RecordSet.getField(mLoadHandle[&HPOST;], 0), "true"))
                            {
                                mbPosted = true;
                            }
                        }
                      
// サイズが2の場合
                        if (cPostListItems == 2)
                        {
                           
// 州と町のデータが入っているところにポインタを移動
                            RecordSet.moveTo(mLoadHandle[&HPOST;], &POST_CITYSTATE_RECORD;);
                           
// 町の値
                            mUserCity = RecordSet.getField(mLoadHandle[&HPOST;], 0);
                           
// 州の値
                            mUserState = RecordSet.getField(mLoadHandle[&HPOST;], 1);
                        }

                      
// 成功しましたとさ
                        iLoadStatus = &LLMODEL_LOAD_SUCCEEDED;;
                    }
                    else
                    {
                        iLoadStatus = &LLMODEL_LOAD_FAILED;;
                    }
<!-- end if signature checking -->
                }

                RecordSet.close(mLoadHandle[&HPOST;]);

                _clear_state(sPostResponseLoaded);
                sPostResponseLoaded = iLoadStatus;;
            </script>

          </transition>
          <transition value="1">
              <!-- underlying error preventing a recordset retrieval -->
              <script>
                  RecordSet.close(mLoadHandle[&HPOST;]);
                  _clear_state(sPostResponseLoaded);
                  sPostResponseLoaded = &LLMODEL_LOAD_FAILED;;
              </script>

          </transition>
        </state>
        </states>
      </state-machine>
    </state-machines>
  </partition>
</ujml>

2006/07/07 カテゴリー: UJML Source解説 | 個別ページ | コメント (0) | トラックバック (0)

「Zipcode converter app」で学ぶ その1 _link()の使い方

 UIEからWEBアプリケーション開発において重要になる、データバインディングのためのサンプルコードが公開された。このサンプルはUIEngine上でWEBアプリケーションを開発するために重要なノウハウを教えてくれる。今回からこのコードを中心にして解説を進める予定。
※この解説は重要だと思う項目から解説する。そのため、ソースコードファイルの途中から解説してる可能性が高い。

 ソースコードはこちらの、「Zipcode converter app」にある、"Download here"から取得することができる。

 今回解説するのは、recordset.ujms というファイルに入っている openEx という関数だ。およそ100行目ぐらいにあるだろう。

 この関数について

概要:指定されたurlに_link()する。接続が上手くできなかったときの処理もちゃんとできるようにする。ちなみに_link()はサーバー上に配置されたリソースにアクセスするための関数。
引数:
handler サーバーとの通信を一意に識別するためのIDみたいなもの。サーバーとの通信は非同期に行うのでIDが必要。
url 接続先のURL
params リクエストするときのパラメーター
fDiscard キャッシュされているものを削除するかどうか true:削除する。

戻り値:
-1 開きが無いので_link()しなかったということ
数値 _link()処理を一意に識別するための番号

 まず下のコードブロック1は関数の宣言及び、関数内で使用する変数を宣言している。visibility="public" としているが、この解説は次回以降に回す。

---- コードブロック1
                    <function name="openEx" type="int" visibility="public"><!-- ★1:関数名と戻り値を宣言 -->
                        <parameters><!-- ★2:関数の引数 -->
                            <var name="handler" type="string"/>
                            <var name="url" type="string"/>
                            <var name="params" type="string"/>
                            <var name="fDiscard" type="boolean"/>
                        </parameters>
                        <variables><!-- ★3:関数内の script で使用する変数 -->
                            <var name="i" type="int"/>
                            <var name="result" type="int"/>
                            <var name="stFullURL" type="string"/>
                        </variables>
----

 まず、_link()できるかどうかを判定している。recordset.ujmsでは一度に_link()実行できる数を制限している(&MAX_OPEN_RECORDSETS;)。ここで、空きがあるか判定し、無ければresultが-1のままということだ。

---- コードブロック2
                        <script>
                            result = -1;

                            <!-- ★4:_link()を実行できるか判定する -->
                            <!-- mIsOpen[]の値が全てtrueだったら空いて無いということ -->
                            <!-- find an available handle -->
                            while (result == -1 &_AND; i &lt; &MAX_OPEN_RECORDSETS;)
                            {
                                if (mIsOpen[ i ])
                                {
                                    i = i + 1;
                                }
                                else
                                {
                                    result = i;
                                }
                            }
----

 以降は、上のコードブロック2で空きがあると判定された場合のみ実効される処理がメイン(★6から)。まず、_link()前に必要な値を初期化する。ここでは、今何番(result)でどこに(url)リンクするのか?の値を格納し初期化している。

 「★7」これがこの関数の肝だろう。これは、_link()が正しくできなかった場合のためのものだ。sRequestFailedHandlerをtrueにすることで、onRequestFailedイベントをキャッチできるようにしている。この方法は_link()処理をクライアント側で管理するための極めて重要なtipsと言える。

 「★8」でキャッシュを削除する指令があったら、キャッシュを削除している。

 「★9」では_link()を実行しているが、mURLToDiscard[result] = stFullURL;としているところも、★7で解説した通り重要なことである。_link()した内容はデバイス中にキャッシュされる。そのキャッシュをクリアするためには_link()実行時に指定したURL文字列と同じURLで、_discard("url")という具合に実行する必要がある。これはそのための準備である。

---- コードブロック3
                            <!-- ★5:_link()の実行 -->
                            if (result != -1)
                            {
                                <!-- ★6:初期化 -->
                                <!-- allocate/initialize handle -->
                                mIsOpen[ result ] = true;
                                mHandler[ result ] = handler;
                                mURL[ result ] = url;
                                mCurRec[ result ] = 0;
                                mNumRecs[ result ] = 0;

                                <!-- ★7:onRequestFailedイベントをキャッチできるようにステート変数sRequestFailedHandlerをtrueにセット -->
                                <!-- listen for network load failures -->
                                _clear_state(sRequestFailedHandler[result]);
                                sRequestFailedHandler[result] = true;

                                <!-- ★8:キャッシュを消す指定があったらキャッシュを削除 -->
                                <!-- fetch the data; client will get a notification event when the data is ready -->
                                if (fDiscard)
                                {
                                    _discard(mURLToDiscard[result]);
                                }

                                <!-- ★9:リンクを実行 -->
                                stFullURL =  _strcat(  url, "?handle=", result, "&amp;maxRS=", &MAX_OPEN_RECORDSETS;, "&amp;maxF=", &MAX_FIELDS_PER_RECORD;, params );
                                mURLToDiscard[result] = stFullURL;
                                 _link( _strcat( "data", result ), stFullURL , 10000);
                            }
                        </script>
                        <return>
                            <eval>result</eval>
                        </return>
                    </function>
----

とりあえず初回はここまで。以降続くかどうかわからないが、重要なポイントを見つけたら解説したい。

2006/04/23 カテゴリー: UJML Source解説 | 個別ページ | コメント (0) | トラックバック (0)

UIEngine/UJML初心者向け

  • 01 初心者向けまとめページ
  • 02 UJMLサンプル一覧(001-025)
  • 03 UJMLサンプル一覧(026-050)
  • 04 UJMLサンプル一覧(051-075)
  • 05 UJMLサンプル一覧(076-100)
  • 06 UJMLサンプル一覧(101-125)
  • 07 学ぶ前に読む10の記事
  • 08 UIEに入りたい人用10の記事
  • 09 UIEngine関連10のブログ

最近の記事

  • 2013年になっておりました
  • 2010年もあと少しですね
  • Bellevue
  • 事業の譲渡とか情けとか
  • Google App Engine Java と Axis
  • プログラミングの楽しさ
  • いろんな変化とか - linkedin 使えない -
  • More Joel on Software
  • 浦島太郎とチップスター
  • 自分の足跡について考えてみた tracのtimelineとGoogleの検索履歴

ブログリンク

  • HOW DO YOU LIKE SILICON VALLEY?
  • It's not about the DBMS

カテゴリー

  • centos
  • FlashLite^^
  • gnizr
  • JAVA
  • PHP
  • Pligg
  • SDKを使い込む
  • Seasar
  • UIEngine 疑問
  • UIEngine注目指数
  • UJML Samples
  • UJML Source解説
  • UJML 初心者向け
  • wordpress
  • ひたすら開発
  • インサイド UJML
  • ブログ(お知らせ)?
  • プログラム
  • プロトタイプ
  • ユーザーインターフェース
  • 働きやすい環境整備\(^^)/
  • 勉強while(true)
  • 技術全般++;

おまけ

フィードを購読
Blog powered by TypePad

アーカイブ

  • 1 月 2013
  • 12 月 2010
  • 6 月 2010
  • 4 月 2010
  • 11 月 2009
  • 10 月 2009
  • 6 月 2009
  • 5 月 2009
  • 1 月 2009
  • 12 月 2008

もっと見る