Home

blog.cuegraphix.com

jQueryのFlexigridを使ってみた(2) データ成形編

前回 Flexigrid のパラメータのメモを残しましたが、表をHTMLに表示する際、データベースのデータをそのまま表示するのではなく、表示用に変換させてから表示するという場合が少なくありません。

たとえば表に画像を表示したり、詳細ページのリンクを張ったりと。

出力する JSON なり XML 自体を変換して出力してやれば済む話なんですが、タグをそのまま出力するのでエスケープ処理をさせたりしなくちゃならない。
なんとなくここまできたら表示部は表示部で分離させたい!となりました。

で、いろいろ模索してると見つけました!

パラメータに preProcess というメソッドを指定することができ、データ取得時の表示直前に全読み込みデータを引数として渡されます。

たとえば下記のようなデータを読み込むとします。

{
page: 1,
total: 5,
rows: [
{id:'1',cell:['1','normal','テスト1','2009/07/07 15:32:27']},
{id:'2',cell:['2','sad','テスト2','2009/07/06 21:04:30']},
{id:'3',cell:['3','smile','テスト3','2009/07/06 13:18:29']},
{id:'4',cell:['4','smile','テスト4','2009/07/05 19:46:41']},
{id:'5',cell:['5','sad','テスト5','2009/07/05 15:25:15']}
]
}

そして、Flexigrid を次のように設定して出力してみます。

$("#flex1").flexigrid({
	url: 'post.json',
	dataType: 'json',
	colModel : [
		{display: 'ID', name : 'id', width : 40, sortable : true, align: 'center'},
		{display: '気分', name : 'feel', width : 40, sortable : false, align: 'center'},
		{display: '件名', name : 'name', width : 200, sortable : true, align: 'left'},
		{display: '作成日', name : 'date', width : 120, sortable : true, align: 'left'},
		{display: 'リンク', name : 'link', width : 80, sortable : false, align: 'center'}
		],
	width: 600,
	height: 'auto'
});

このような結果になります。
flexigrid1

このデータを preProcess メソッドを設定し表示を変更します。
まずデータ内容を変更させるデータ受け取り関数を作成します。

function _preProcess( data ){
	$.each( data.rows,
		function(i,val) {
			val.cell[1] = '<img src="img/'+val.cell[1]+'.gif" width="12" height="12" />';
			
			var date = new Date(Date.parse(val.cell[3]));
			val.cell[3] = (date.getMonth()+1) + "月" + date.getDate() + "日" + date.getHours() + "時" + date.getMinutes() + "分";
			
			val.cell[4] = '<a href="hoge.php?id='+val.cell[0]+'">詳細</a>';
		}
	);
	return data;
}

・セル1の気分データを同名の画像を表示するように変更
・セル3の日付データを日本語表記に変更
・セル4はデータとして存在しないが追加してIDを引数とした詳細ページへのリンクを設定

という処理をします。
そして、Flexigrid の設定を変更します。

$("#flex1").flexigrid({
	url: 'post.json',
	dataType: 'json',
	colModel : [
		{display: 'ID', name : 'iso', width : 40, sortable : true, align: 'center', labelFunction: function(data){ return '<a href="aaaaa.cgi?id='+data+'">詳細</a>'; }},
		{display: '気分', name : 'feel', width : 40, sortable : false, align: 'center'},
		{display: '件名', name : 'name', width : 200, sortable : true, align: 'left'},
		{display: '作成日', name : 'date', width : 120, sortable : true, align: 'left'},
		{display: 'リンク', name : 'link', width : 80, sortable : false, align: 'center'}
		],
	width: 600,
	height: 'auto',
	preProcess: _preProcess  /* ←追加 */
});

表示したのが下記です。
flexigrid2

デモ

これで表示部とデータ出力を完全に分けられるのではないかと思います。

jQueryのFlexigridを使ってみた

データを簡単にテーブルにフォーマットしてくれるjQuery プラグイン Flexigrid を使ってみた。

Flexigrid
http://www.flexigrid.info/

Google Code
http://code.google.com/p/flexigrid/

DBから吸い出して管理画面などでさくっとテーブルにしたい場合に非常に便利!

具体的にどんなことができるのかはマイコミジャーナルさんの記事がわかりやすいのでリンク
わずか数行で”ものすごいテーブル”に! – jQueryプラグイン「Flexigrid」

ただこのプラグインあまりリファレンスがない・・・
jsを開けばオプションは一目瞭然なのだが、自分メモとして残しておきます。

オプションパラメータ一覧

UIパラメータ

width
テーブルの横幅。数値もしくは auto が利用可能。auto に設定した際は横のリサイズは無効。
デフォルト:auto
height
テーブルの高さ。数値もしくは auto が利用可能。auto に設定した際は縦のリサイズは無効。
デフォルト:200
striped
格子行を利用するかどうか。
デフォルト:true
novstripe
列の区切りを表示しないかどうか。(no vertical stripe)
デフォルト:false
minwidth
各列の最小幅
デフォルト:30
minheight
テーブルの最小高さ
デフォルト:80
resizable
リサイズを可能にするかどうか。true にすると width および height が auto でなければそれぞれ右端、下端にリサイズアイコンが表示される
デフォルト:true
title
テーブルのキャプション。設定するとタイトル行が表示される。
showTableToggleBtn
テーブルの表示非表示ボタンを設置するかどうか。title に文字が設定されている場合のみ有効。
デフォルト:false
minColToggle
最小列数。この設定した列数以下は非表示にできなくする。
デフォルト:1
showToggleBtn
列を非表示にするボタンポップアップを表示するかどうか。
デフォルト:true
singleSelect
行の複数選択を可能にするかどうか。
デフォルト:false

Ajaxによる動的出力で利用するパラメータ

url
Ajax のリクエストされるURL。XML もしくは JSON 出力
method
送信メソッド
デフォルト:POST
dataType
読み込むデータのタイプ。json or xml。必ず小文字で指定しなければならないことに注意!
デフォルト:xml
errormsg
エラーが発生した際のメッセージ
usepager
ページャーを使用するかどうか。
デフォルト:false
nowrap
セル内で折り返しを許可するかどうか
デフォルト:true
page
現在表示しているページ数。読み込んだ JSON もしくは XML で上書きされる。
total
格納されているデータの総行数。読み込んだ JSON もしくは XML で上書きされる。
sortname
ソートする列。指定しないと送信時 undefined が POST されてしまうので必須。
sortorder
ソートの方向。asc or desc。指定しないと送信時 undefined が POST されてしまうので必須。
query
検索されたキーワード。
qtype
検索対象の列名
rp
1ページに表示する行数。
デフォルト:15
useRp
1ページに表示する行数を変更できるセレクトボックスを表示するかどうか。
デフォルト:true
rpOptions
useRp を有効にした際のセレクトボックス値の配列。
デフォルト:[10,15,20,25,40]
pagestat
現在表示しているページの説明文フォーマット
表示開始行:{from}、表示終了行:{to}、総数:{total}が利用できる。
デフォルト:Displaying {from} to {to} of {total} items
procmsg
読み込み中時フッターに表示されるメッセージ。
デフォルト:Processing, please wait …
no msg
検索データが存在しなかった場合のメッセージ。
デフォルト:No items
autoload
HTML表示時に自動的に読み込みを開始するかどうか。
デフォルト:true
hideOnSubmit
送受信中に現在表示データ行を隠すかどうか。(?)
デフォルト:true
blockOpacity
hideOnSubmit を有効にした際の表示データ行の透明度。(?)
デフォルト:0.5

その他パラメータ

colModel
列の設定オブジェクトをもつ配列
display:列の表示名
name:列のユニークID(テーブルカラム名)必須
width:列幅
sortable:列のソートを有効にするかどうか
align:文字の配置
hide:非表示にするかどうか
searchitems
検索対象となる列の配列
display:検索対象を選択するセレクトボックスの表示文字
name:列のユニークID(テーブルカラム名)必須
isdefault:初期選択されているかどうか。
buttons
ヘッダにボタンを表示する際のボタン情報を格納した配列
name:ボタン表示文字
bclass:ボタンの表示クラス
onpress:ボタンを押された際に呼び出されるメソッド

separator:セパレータを表示

イベントハンドラメソッド

onToggleCol
列の表示非表示が変更された際に呼び出されるイベントハンドラメソッド。
onChangeSort
ソートが変更された際に呼び出されるイベントハンドラメソッド。
onSuccess
表示が成功した際に呼び出されるイベントハンドラメソッド。
onSubmit
データの送受信が行われる直前に呼び出されるイベントハンドラメソッド。

その他メソッド

preProcess
データを受信した直後にデータを成形するため(と思われる)に呼び出される。
引数:読み込みデータ
戻り値:成形データ

Flexigrid API メソッド

flexigrid( options )
テーブルを Flexigrid 化する。コンストラクタ。
flexReload()
データの再読み込みを行う。
flexOptions( options )
オプションパラメータの変更を行う。
flexToggleCol( culumn_id, visible )
列の表示・非表示を切り替える。
flexAddData( data )
データを追加する。
noSelect
データ行の文字列をカーソルで選択できないようにする。
へー。そんなことできるんだー。

これで合ってるかな?
もし違ってればやさしくツッコミください。

extends Progression 拡張機能コンテストで Progression 開発者賞受賞

半年ほどブログ放置してすいません・・・

extends Progression 拡張機能コンテスト
http://extends.progression.jp/

Progression 開発者賞というものをいただいてしまいました!
感謝感激です。
しかも、予定にはなかった Progression 開発者賞という賞を新設していただくという暖かい配慮に心より感謝感謝です。
extends Progression 拡張機能コンテスト関係者の皆様本当にありがとうございました!

今回応募したものは LiquidLayout というライブラリです。
フルフラッシュサイトを作るときに、AS3になってからもっとやっかいになってしまった表示オブジェクト等の配置をカンタンにしちゃえというライブラリです。
ExDocument をルートシーンに使用していれば、LiquidLayout も利用可能という代物になっており、Progression に限らず利用できてしまうので、このあたりが Progression 開発者賞を新設していただけるという関係者の皆様を困惑させてしまう結果になってしまったようです。taka:niumさんすいません!

提出したプレゼン資料
(Slideライブラリ使用。左右キーで移動します)

サンプルデモ
(設定を変えたり、画面をぐりぐりリサイズしてご確認ください)

ソース一式
(サンプルデモで使用したクラスファイルも同梱しています)

Tweener を同じような構造をとっており、addLayout メソッドでオブジェクトとパラメータを追加して使用します。
数値で指定した画面位置からの距離、数値を文字列で渡すことによりパーセンテージでの指定が可能です。

Tweener ライブラリと大きく異なる部分は、Tweener は静的メソッドでアクセスするのに対し、LiquidLayout はインスタンスを生成して使用します。

var lauout:LiquidLayout = new LiquidLayout( document );
layout.addLayout( mc, { center: 0, middle: 0 } );

この部分は最後まで悩んだというか今現在でも悩んでいるのですが、オブジェクトの最大幅・最小幅・最大高さ・最小高さなどを、インスタンス本体が持っていることにあります。
もし、あるコンテンツだけ異なる設定をしたいとなった場合に、静的では対応が難しかったためインスタンス生成する形をとりました。

Flasherの方々はなにかしらのライブラリを使用されていると思いますが、もし LiquidLayout 気に入った!となれば使っていただけると幸いです。
また、こうしたほうがいいんじゃない?などご意見いただけるともっと幸いです。

Continue reading

ショックウェーブ解散

Shockwave.com運営会社ショックウェーブエンターテインメントが解散。
1月31日をもって終了します。

CATMANやStainboyを見て疲れを癒して、ちょっとの休憩でジグソーパズルやZOO KEEPERをやってしまって、仕事が手に付かないくらいはまったことが1度や2度ではないので、やっぱりさびしいものがありますね。。

こちらから最後のメッセージが見れます。
Shockwave から皆様へ 9年6ヶ月分の感謝を込めて

embedSWFの引数メモ(Progression3.1.2)

Progression3.1.2にアップデートで、SWFObject がバージョン 2.1 にアップデートされたことに伴い progression.js も大きく変更されているようで、embedSWFという関数で表示できるようになっている。

ただ、僕が今現状で作っているサイトで最初に読み込むファイル名を preloader.swf という名前から別のものに変更してしまっており、index.html 内にその記述がどこにもないので、渡すことの出来そうな引数を調べてみたのでメモ。

渡すことの可能な引数と初期値一覧

url:"preloader.swf",
replaceElementId:"attention",
width:640,
height:480,
adjustHorizontal:false,
adjustVertical:false,
centering:true,
version:"9.0.45",
useExpressInstall:true,
flashvars:{},
params:{
	bgcolor:"#FFFFFF",
	wmode:"window",
	allowfullscreen:true,
	allowscriptaccess:"samedomain"
}
attributes:{}

params の中は SWFObjectにそのまま渡されるだけだと思うので、Flashのparam設定が使えると思われます。
http://www.adobe.com/go/tn_12701

  • url
    読み込みを開始するSWFへのパス
  • replaceElementId
    SWFを表示するHTML要素のID属性名
  • width
    SWFの横幅(SWFForceSizeの最小幅(?))
  • height
    SWFの高さ(SWFForceSizeの最小高さ(?))
  • adjustHorizontal
    横幅100%表示にするかどうか
  • adjustVertical
    高さ100%表示にするかどうか
  • centering
    画面の中央表示をするかどうか(?)
  • version
    Flash Playerのバージョン
  • useExpressInstall
    Express Installを適用するかどうか
    (ただし、expressinstall.swfのパスは”contents/scripts/swfobject/expressinstall.swf”で固定のようです。)
  • flashvars
    FlashVars
  • params
    params
  • attributes
    attributes

Progressionクラスベースオートアップデート

Progressionを3.0.8から3.1.2へやっと先日アップデートしました。

そこで、オートアップデートを使用すると、下記のエラーが発生し失敗。

... 問題が発生したためアップデート処理を中断します。
... バックアップデータを復元します。 

プロジェクトの復元に失敗しました。バックアップデータから手動で復元してください。

プロジェクトフォルダを見てみると、フォルダは存在するもののファイルというファイルがもぬけの殻・・・
エラーログにバックアップデータがあると書いてあるということと、アップデート前に事前にプロジェクトの全バックアップを取っていたのですが、それでも冷や汗が出ました。。

調べてみると、Progression Forumでflabakaさんがオートアップデート機能について情報共有されていて、どうやら現在進行しているプロジェクトはSubVersionで管理していて、それで生成される「.svn」というフォルダがよろしくないことが判明。
flabakaさんのこちらの記事で詳しく説明されてます。
flabaka – libsフォルダにカスタムクラスを入れてると、オートアップデートが使えない!

flabakaさんの記事によると、「.svn」フォルダを全削除すればおkとありますが、プロジェクト自体をSubVersion管理しているのでそうするわけにも行かず、別ディレクトリに新たなプロジェクトを作成(テストプロジェクトなどのアップデートでも可)して、リソースノートとにらめっこしながら「libs」ファイルの中身を上書きという形を取りました。

3.0.8 から 3.1.2 へのアップデートだったので、追加クラス・変更クラスについては上書きで問題ないと思いますが、削除クラスとしては HIGEWheel.as だけかなと思います。

削除:org.libspark.utils.ui.HIGEWheel

追加:org.libspark.ui.SWFWheel

これに伴い /src/libs/org/libspark/utils のフォルダも必要なくなります。

今回の教訓としてはとりあえずなんかするときはバックアップを取っておこうと心に誓いました。

Continue reading

基本クラスの変更で警告

_level0.KAYACさんのフォント埋め込み時のパブリッシュの高速化の方法を使ってフォントの埋め込みを行うんですが、あるシンボルを「コンパイルされたクリップに変換」をしていると、どうやらその後どのムービークリップシンボルの基本クラスが変更できない模様。

「コンパイルされたクリップに変換」されたシンボルがある状態で、その後作成したシンボルにflash.display.MovieClipの拡張クラスを基本クラスに指定すると、

警告

「指定されたクラスは定義済みで自身のサブクラスを拡張しているので、基本クラスは使用されません。基本クラスを使用する場合は、自動生成される [クラス] フィールドでクラス名を指定するか、デフォルトの基本クラス ‘flash.display.MovieClip’ を [基本クラス] フィールドに入力してください」

と長々と警告。

書き出しにはなんら問題ないらしく、_level0.KAYACさんのフォント埋め込みはパブリッシュが早く非常によいので、シンボルの基本クラスを変更するときだけコンパイルクリップをライブラリから削除して、シンボルの基本クラスを設定した後、もう一度作成するか退避させていたコンパイルクリップを戻してくるという方法で回避することにします。

CastMovieClipを多用しすぎるのも危険?

こんな生意気なことを言えばtaka:nium様に怒られるかもしれないが、ちょっと先日困ったことが発生したのでアップ。

非常に便利なのでなにかとシンボルを作るときもCastMovieClipを継承したMovieClipを作成しているわけなんですが、先日DataGridのCellRendererのスキンをいじくりたいことがあって、それらもCastMovieClip継承のクラスを作って入れ込んでみた。

そしたら、どうにもこうにも動きがもっさりしている・・・
僕のソースがきっと悪いんだと思って、あれやこれやをコメントアウトしてみるがどうにも改善しない。
それで単純にリンケージの基本クラスだけを変更してみたものでテスト。

この3種類を作ってテスト。
Google Chromeのタスクマネージャで確認してみる

そうすると、CastMovieClip・ExMovieClipを継承したほうでは、DataGrid内でマウスを動かしたりスクロールさせたりすると、メモリが増える増える!

普通にMovieClip継承でも増えるんやけど、増え方が尋常じゃない・・・
カラム数が増えると当たり前だけど増え幅も増大する。。
そして一度上がったものは減ってくれない・・・・

もうちょい単純なソースで検証してみる。
ただただENTER_FRAMEで追加削除を繰り返すのみのクラスを作って検証。
生成するものをCastMovieClipかMovieClipかを切り替えて書き出してみる。

package
{
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.Event;
	import jp.progression.casts.CastDocument;
	import jp.progression.casts.CastMovieClip;
	import jp.progression.Progression;

	public class AddCastIndex extends CastDocument
	{
		public var prog:Progression;

		public function AddCastIndex()
		{
		}

		protected override function _onInit():void
		{
			prog = new Progression( "index", stage );

			prog.root.onInit = function():void
			{
				var cast:CastMovieClip;
				var ny:Number = 0;
				var container:Sprite = new Sprite();
				var enterFrame:Function = function( e:Event ):void
				{
					if ( cast ) { container.removeChild( cast ); }
					cast = new CastMovieClip();
					cast.graphics.beginFill( 0 );
					cast.graphics.drawRect( 0, 0, stageWidth, 20 );
					ny = ( ny + 20 ) % stageHeight;
					cast.y = ny;
					container.addChild( cast );
				}
				prog.container.addChild( container );
				container.addEventListener( Event.ENTER_FRAME, enterFrame );
			}
			prog.goto( prog.firstSceneId );
		}
	}
}<

ENTER_FRAME時に一個しか生成しないので、微妙な差だけど、やっぱりCastMovieClipのほうが増加率は高い。

中をまさぐって検証するには敷居が高すぎるのでやめておこう・・・
でもCastMovieClipを使わないなんてもうできない体になっちゃって、そんな世界僕の中にはもうないけど、こういう使い捨てで済むMovieClipやSpriteはCast(Ex)系を継承せずに単純にMovieClipやSpriteを継承するほうがよさそう。

ってゆうのであってるのかな??

Continue reading

ProcessEvent イベントフローについて(2)

前回のままだと、特殊な使い方すぎてイベントフローの検証になってないので、ユーザーイベントでの遷移に変更して検証。

前回のクラスに移動用ボタンを設置したIndexクラスを作成します。

package
{
	import jp.progression.casts.CastButton;
	import jp.progression.casts.CastDocument;
	import jp.progression.commands.AddChild;
	import jp.progression.commands.Goto;
	import jp.progression.commands.RemoveChild;
	import jp.progression.commands.Trace;
	import jp.progression.Progression;
	import jp.progression.scenes.SceneId;
	import jp.progression.scenes.SceneObject;

	public class Index extends CastDocument
	{
		public var prog:Progression;

		public function Index()
		{

		}

		protected override function _onInit():void
		{
			prog = new Progression( "index", stage );

			prog.onProcessStart     = function() { trace( "onProcessStart :" + prog.eventType ); }
			prog.onProcessScene     = function() { trace( "onProcessScene :" + prog.eventType ); }
			prog.onProcessComplete  = function() { trace( "onProcessComplete :" + prog.eventType + "\n------" ); }
			prog.onProcessEvent     = function() { trace( "onProcessEvent :" + prog.eventType ); }
			prog.onProcessError     = function() { trace( "onProcessError :" + prog.eventType ); }
			prog.onProcessInterrupt = function() { trace( "onProcessInterrupt :" + prog.eventType + "\n------" ); }

			var b1:CastButton = new CastButton();
			b1.graphics.beginFill( 0xFF0000 );
			b1.graphics.drawRect( 0, 0, 100, 100 );
			b1.sceneId = new SceneId( "/index/scene2" );

			var b2:CastButton = new CastButton();
			b2.graphics.beginFill( 0x0000FF );
			b2.graphics.drawRect( 0, 0, 100, 100 );
			b2.sceneId = new SceneId( "/index/scene3" );

			prog.root.addScene( new SceneObject( "scene1", {
				onLoad: function():void {
					this.addCommand(
						new Trace( "scene1 : onLoad" )
					);
				},
				onInit: function():void {
					this.addCommand(
						new Trace( "scene1 : onInit" ),
						new AddChild( prog.container, b1 )
					);
				},
				onGoto: function():void {
					this.addCommand(
						new Trace( "scene1 : onGoto" ),
						new RemoveChild( prog.container, b1 )
					);
				},
				onUnload: function():void {
					this.addCommand(
						new Trace( "scene1 : onUnload" )
					);
				}
			} ) );

			prog.root.addScene( new SceneObject( "scene2", {
				onLoad: function():void {
					this.addCommand(
						new Trace( "scene2 : onLoad" )
					);
				},
				onInit: function():void {
					this.addCommand(
						new Trace( "scene2 : onInit" ),
						new AddChild( prog.container, b2 )
					);
				},
				onGoto: function():void {
					this.addCommand(
						new Trace( "scene2 : onGoto" ),
						new RemoveChild( prog.container, b2 )
					);
				},
				onUnload: function():void {
					this.addCommand(
						new Trace( "scene2 : onUnload" )
					);
				}
			} ) );

			prog.goto( new SceneId( "/index/scene1" ) );
		}
	}
}

まず /index/scene1 に行くと赤いボタンが配置され、クリックすると /index/scene2 に飛び青いボタンが表示され、そのボタンをクリックすると設定されていない /index/scene3 に遷移するよう要求しエラーを発生させます。

出力結果

onProcessStart :null
onProcessScene :load
onProcessEvent :load
onProcessEvent :descend
onProcessScene :load
onProcessEvent :load
scene1 : onLoad
onProcessEvent :init
scene1 : onInit
onProcessComplete :init
------
onProcessStart :init
onProcessEvent :goto
scene1 : onGoto
onProcessEvent :unload
scene1 : onUnload
onProcessScene :load
onProcessEvent :load
scene2 : onLoad
onProcessEvent :init
scene2 : onInit
onProcessComplete :init
------
onProcessStart :init
onProcessEvent :goto
scene2 : onGoto
onProcessEvent :unload
scene2 : onUnload
[ERROR] 移動先のシーンが存在しません, 目的地 = /index/scene3
onProcessError :load

scene2 の onInit イベント内で中断実行を行う処理に変更してみる。

onInit: function():void {
	this.addCommand(
		new Trace( "scene2 : onInit" ),
		function():void { this.interrupt(); },
		new Trace( "中断実行後" )
	);
}<

出力結果

onProcessStart :null
onProcessScene :load
onProcessEvent :load
onProcessEvent :descend
onProcessScene :load
onProcessEvent :load
scene1 : onLoad
onProcessEvent :init
scene1 : onInit
onProcessComplete :init
------
onProcessStart :init
onProcessEvent :goto
scene1 : onGoto
onProcessEvent :unload
scene1 : onUnload
onProcessScene :load
onProcessEvent :load
scene2 : onLoad
onProcessEvent :init
scene2 : onInit
中断実行後
onProcessInterrupt :init
------

interrupt メソッドに引数 true を渡して、強制中断実行に変更するとそのあとの処理は実行されず終了する。

function():void { this.interrupt( true ); }
  • onProcessStart で始まり正常終了した場合は onProcessComplete で終わる
  • onProcessEvent と SceneObject イベントは対で実行され、onProcessEvent が常に先に実行される
  • onProcessScene イベントはシーンに入る直前に実行される
  • 階層化されていれば通過シーン到達直前もすべて onProcessScene は実行される

ProcessEvent イベントフローについて(1)

Sceneでのイベントフローはいろんな方が書いておられるので非常に勉強になりますが、ProcessEventについてはあまり見つけられなかったので、試してみました。

Progressionインスタンスのイベントハンドラメソッドには

  • onProcessStart
  • onProcessScene
  • onProcessComplete
  • onProcessEvent
  • onProcessError
  • onProcessInterrupt

が用意されています。
これがSceneObjectのonLoadやonInitからみてどんなタイミングで実行されるのかテストするために、次のようなIndexクラスを作成します。

package
{
	import jp.progression.casts.CastDocument;
	import jp.progression.commands.Goto;
	import jp.progression.commands.Trace;
	import jp.progression.Progression;
	import jp.progression.scenes.SceneId;
	import jp.progression.scenes.SceneObject;
	
	public class Index extends CastDocument
	{
		public var prog:Progression;
		
		public function Index()
		{
			
		}
		
		protected override function _onInit():void
		{
			prog = new Progression( "index", stage );
			
			prog.onProcessStart     = function() { trace( "onProcessStart :" + prog.eventType ); }
			prog.onProcessScene     = function() { trace( "onProcessScene :" + prog.eventType ); }
			prog.onProcessComplete  = function() { trace( "onProcessComplete :" + prog.eventType ); }
			prog.onProcessEvent     = function() { trace( "onProcessEvent :" + prog.eventType ); }
			prog.onProcessError     = function() { trace( "onProcessError :" + prog.eventType ); }
			prog.onProcessInterrupt = function() { trace( "onProcessInterrupt :" + prog.eventType ); }
			
			prog.root.addScene( new SceneObject( "scene1", {
				onLoad: function():void {
					this.addCommand(
						new Trace( "scene1 : onLoad" )
					);
				},
				onInit: function():void {
					this.addCommand(
						new Trace( "scene1 : onInit" ),
						// scene2へ移動
						new Goto( new SceneId( "/index/scene2" ) )
					);
				},
				onGoto: function():void {
					this.addCommand(
						new Trace( "scene1 : onGoto" )
					);
				},
				onUnload: function():void {
					this.addCommand(
						new Trace( "scene1 : onUnload" )
					);
				}
			} ) );
			
			prog.root.addScene( new SceneObject( "scene2", {
				onLoad: function():void {
					this.addCommand(
						new Trace( "scene2 : onLoad" )
					);
				},
				onInit: function():void {
					this.addCommand(
						new Trace( "scene2 : onInit" ),
						// 強制的にエラーを発生させる
						new Goto( new SceneId( "/index/scene3" ) )
					);
				},
				onGoto: function():void {
					this.addCommand(
						new Trace( "scene2 : onGoto" )
					);
				},
				onUnload: function():void {
					this.addCommand(
						new Trace( "scene2 : onUnload" )
					);
				}
			} ) );
			
			prog.goto( new SceneId( "/index/scene1" ) );
		}
	}
}

出力結果

onProcessStart :null
onProcessScene :load
onProcessEvent :load
onProcessEvent :descend
onProcessScene :load
onProcessEvent :load
scene1 : onLoad
onProcessEvent :init
scene1 : onInit
onProcessStart :init
onProcessEvent :goto
scene1 : onGoto
onProcessEvent :unload
scene1 : onUnload
onProcessScene :load
onProcessEvent :load
scene2 : onLoad
onProcessEvent :init
scene2 : onInit
onProcessStart :init
onProcessEvent :goto
scene2 : onGoto
onProcessEvent :unload
scene2 : onUnload
[ERROR] 移動先のシーンが存在しません, 目的地 = /index/scene3
onProcessError :load
onProcessInterrupt :load
onProcessInterrupt :load

想像通りですが、SceneEvent が発生した際には onProcessEvent が実行されてから、シーンの各イベントハンドラが実行されるようです。
ただこの検証だとscene1に到達した瞬間のコマンドリスト内で強制的にscene2へGoToで飛ばしているので、中断実行であるonProcessInterrupt が入ると思っていたんですが、scene1 : onInitの次は onProcessStart :init が実行されてますね。
多分最後に2つ出力されているonProcessInterrupt のどちらかがこれに相当するのでしょうか?

scene1 の onGoto 内に new Wait( 1000 ) のようにWaitコマンドを挟むと、onProcessInterrupt がその時点で出力されます。もしかすると中断実行も非同期処理になっているのかな?

Continue reading

Home

Search
Feeds
Meta

Return to page top