« ActionScript上でECMAScriptを動かす | main | AS3 Language Specification他邦訳 »

2006年03月10日

getElementByIdをActionScriptで実装する

ちょっとモチベーションがあがってきたので、久しぶりのHackネタ。

ちょっと前にAjax周りでJavaScript触って、一番感動したものにdocument.getElementByIdという関数があります。この関数はページ内エレメントをid番号で取得する、ってものなんですけどこれがまた超便利。

元々Flashでは、アニメーションや演出の都合でMovieClipの階層構造がコロコロ変更されることが多くて、そのせいでMCの参照パスがぶっ壊れまくることがよくあります。そんなとき、id番号でMCの階層無視して欲しいMCが参照できたらメチャメチャ便利じゃないかと。いや別に_global関数でもいいけど・・・

でgetElementByIdを擬似実装してみました。

class net.fladdict.util.IdManager{
	private static var _idTable:Object	
	private static var _initialized:Boolean = false

public static function getElementById( id:String ){
if( ! _initialized ) _initialize()
return _idTable[id]
}

public static function setId( obj:Object, id:String){
if( ! _initialized ) _initialize()
_idTable[id] = obj
}

public static function removeId( id ){
delete _idTable[id];
}

private static function _initialize(){
_idTable = {}
_initialized = true;
}
}

IdManager.setId(id, mc)でMCを登録すると、IdManager.getElementById(id)でいつでも取得できるようになります。

しかしsetIdを毎回呼び出すのもMC内のコードがIdManagerに依存するのもアレなので、MovieClip.prototypeを弄くりまわすと、面白くなってまいります。

MovieClip.prototype.addProperty("id", 
							 function(){
								 return  this.__fladdict_id
							 },
							 function( idStr:String ){
								 if(idStr) IdManager.removeId(idStr);
								 IdManager.setId(this, idStr);
								 this.__fladdict_id = idStr
							 }
);

こうすると、myMovieClip.id = "hogehoge" とするだけで、getElementByIdでムービークリップの参照を取得できるようになります。コンポーネント化してライブラリにいれるか、#importとかで1フレーム目に入れとくとよいかと。

まだ実験段階なので、改良案とかある人色々教えてくださいませ。

あと最近、忙しくて世間の流れをチェックできてないんですが、FlashOOP主導でいろんなコード共有する話ってどうなってるんでしょう。こういう実験的な奴色々と提供できるんですが。

<追記>
ウチのサイトって<PRE>と<BLOCKQUOTE>タグ使うとなぜかレイアウトがぶっ壊れる・・・ そろそろCSSリメイクしないとなぁ

投稿者 Taka : 2006年03月10日 00:34

book

dotfla.gif

bookmark

はてなブックマークに追加

del.icio.usに追加

trackbacks

this entry's trackback URL:
http://www.fladdict.net/cgi-bin/mt3/mt-tb.cgi/483

comment

実際試して無いから動くかどうか分かりませんが、ここは一つ、prototype.jsっぽく、getElementByIdを$にバインドするってどうですかね。

_global.$ = function (id) {
return IdManager.getElementById(id);
}

$('mc1').foo();
$('mc2').bar();

見た目が綺麗。でも普通の変数と同じ感覚で扱ってると毎回関数が呼ばれる罠。

by keita : 2006年03月10日 01:53

あー、それは思った。
ついでに、第二パラメータでnamespaceも実装しちまったほうがよいかもね。
そうすれば、コンポーネントとかクラス内でid使っても衝突しなくなるし。

by Taka : 2006年03月10日 08:56

面白&役立ち記事が多くて、毎日チェックさせていただいてます。

getElementByID()をFlashに持ってくるのは、便利でよさそうに思いました。

で、この記事見てて考えたんですが、オブジェクトの選択方法全般に関してセレクターをまとめると、応用が利くのではないかと。

(全然違う分野からですが)Photoshopは多彩な選択方法のおかげで、いろんな処理が楽になってますが、Flashでも、階層構造とパス指定だけじゃなく、上記のID指定を含めていろいろ選択方法があればやりやすいかもしれないです。

とりあえず思いついたのはこんなとこ↓ですが・・・
・idによる選択
・同じオブジェクト型による選択
・連番選択
・オブジェクト名の正規表現による選択
・選択範囲の結合
・選択範囲の一部削除
・選択範囲の保存

by Y : 2006年03月10日 13:15

こんばんは。

自分も似たようなクラスを以前作りました。
自分の場合は、シングルトンクラスにしてました。

Container.instance.getComponentById("id");
こんな感じにしてみました。

by arkw : 2006年03月13日 02:24

コメントしてください




保存しますか?