2007年7月30日星期一

Flash Player HTTP 資料請求行為   [+/-]

Ticore's Blog

以往 ActionScript 1.0、2.0 使用 LoadVars、loadVariables 甚至是 Flash Remoting
發出的 HTTP Request 都無法用程式加以終止或是縮短 Timeout 時間
遇到連續發出的請求,甚至還會造成客戶端瀏覽器當掉

ActionScript 3.0 已經對此作了一些改善
以下則是一些 AS HTTP Request 行為整理:

  • AS3 - flash.net.URLRequst
    1. URLLoader 連續發出 Request 時,前面的 Request 均會被終止,
      只有最後一個可以繼續執行
    2. URLLoader 發出 Request 後,可以用 URLLoader.close 終止下載動作

  • AS3 - flash.net.NetConnection (Remoting)
    1. 連續發出 Request 時,前面的 Request 均會繼續執行
    2. 即使呼叫 NetConnection.close,刪除 NetConnection 實體,
      也無法終止一連串下載動作

  • AS2 - LoadVars, loadVariables, loadVariablesNum, NetConnection (Remoting)
    1. 連續發出 Request 時,前面的 Request 均會繼續執行
    2. 即使 unloadMovie, loadMovieNum(0) 也無法終止一連串下載動作

  • AS2 - loadMovie, loadMovieNum
    1. 使用 loadMovie 連續發出 Request 時,前面的 Request 均會被終止,
      只有最後一個可以繼續執行
    2. 使用 loadMovie 讀取資料時,可以用 unloadMovie 終止下載動作

這樣看來,假如想要在 ActionScript 2.0 使用較佳 HTTP Request 控制
有必要採用 SWF 作為資料交換的格式
需要動態產生 SWF 的功能
這個 OpenSource 可以省去不少功夫 SWX: SWF Data Exchange Format

Read more...

2007年7月27日星期五

AS3 Compiler Strict Mode Bug   [+/-]

Ticore's Blog

之前介紹了 AS3 技巧 - 利用 with 跳過編譯器 Strict Mode 檢查
這次則是編譯器 Strict Mode 的誤判
當 with block 內 function 參考到外層變數
在 Strict Mode 下,會出現編譯錯誤

Bug 示範:

var f = 123;
with ({}) {
 var fun:Function = function () {
  trace(f);
 };
}
fun();
1120: Access of undefined property f.

解決方式,於 function 內再嵌套一層 with block:

var f = 123;
with ({}) {
 var fun:Function = function fun() {
  with ({}) {
   trace(f);
  }
 };
}
fun(); // 123

這個問題同時出現在 Flash CS3, CS4、Flex 2.0, 3.2 編譯器上

相關連結:
ActionScript "with" Block Scope 遮蔽效應
AS3 技巧 - 利用 with 跳過編譯器 Strict Mode 檢查

Read more...

Flash SWF 9 檔案規格已經公佈了   [+/-]

Ticore's Blog

有興趣可以到以下網址申請

Flash Player Developer SDKs

Read more...

2007年7月26日星期四

AS3 利用 Proxy 打造可存放 Namespace Property 容器   [+/-]

Ticore's Blog

ActionScript 3.0 新增 namespace member 功能
不過這功能需要在 class 預先宣告好,才能使用
假如沒有預先宣告 namespace member
即使將 class 宣告為 dynamic,也無法動態增加 namespace property
相同的情況在 Object, Array, Dictionary 容器也是一樣

不過所幸 AS3 有 Proxy 可用
只要不與 flash_proxy class member 衝突
皆可對 Proxy 進行 namespace property 操作

以下便是利用 Proxy 實作出來的容器:

package {
 import flash.utils.*;
 public dynamic class NSObject extends Proxy {
  
  private var keysObj:Object;
  
  public function NSObject():*{
   keysObj = {};
   keysObj[""] = {};
  }
  
  flash_proxy override function setProperty (varName:*, value:*):void{
   //trace("setProperty : " + varName, value);
   if (varName is QName) {
    if (keysObj[varName.uri] == null) {
     keysObj[varName.uri] = {};
    }
    keysObj[varName.uri][varName.localName] = value;
   } else {
    keysObj[""][varName] = value;
   }
  }
  
  flash_proxy override function deleteProperty (varName:*):Boolean{
   //trace("deleteProperty : " + varName);
   if (varName is QName) {
    return delete keysObj[varName.uri][varName.localName];
   } else {
    return delete keysObj[""][varName];
   }
  }
  
  flash_proxy override function hasProperty(varName:*):Boolean{
   //trace("hasProperty : " + varName);
   if (varName is QName) {
    return keysObj[varName.uri].hasOwnProperty(varName.localName);
   } else {
    return keysObj[""].hasOwnProperty(varName);
   }
  }
  
  flash_proxy override function callProperty(varName:*, ...rest:Array):* {
   //trace("callProperty : " + varName);
   if (varName is QName) {
    return keysObj[varName.uri][varName.localName].apply(null, rest);
   } else {
    return keysObj[""][varName].apply(null, rest);
   }
  }
  
  flash_proxy override function getProperty(varName:*):* {
   //trace("getProperty : " + varName);
   if (varName is QName) {
    return keysObj[varName.uri][varName.localName];
   } else {
    return keysObj[""][varName];
   }
  }
  
 }
}

使用範例:

package {
 import flash.display.*;

 public class main extends MovieClip {
  
  namespace ns1 = "http://www.ticore.com/1";
  namespace ns2 = "http://www.ticore.com/2";
  
  public function main():*{
   
   var nsObj:NSObject = new NSObject();
   nsObj.ns1::prop = "Property 1";
   nsObj.ns2::prop = "Property 2";
   trace(nsObj.ns1::prop); // Property 1
   trace(nsObj.ns2::prop); // Property 2
   
  }
  
 }
}
Read more...

2007年7月25日星期三

Flash AS 1.0 偵測特殊符號 on KeyPress 事件   [+/-]

Ticore's Blog

在 Flash ActionScript 1.0 偵測按鍵事件
最簡單的方式就是利用 Button 加上以下的程式

on (keyPress '7') {
   trace("keyPress '7'");
}

假如遇到法文字母就會出現問題

on (keyPress 'è') {
   trace("keyPress 'è'");
}

解決方式很簡單,只要把 Button 改為 MovieClip 就好了

問題出處:[問題]打字遊戲[法文版]-使用法式鍵盤

Read more...

2007年7月24日星期二

我的 Essential ActionScript 3.0 也收到了   [+/-]

Ticore's Blog

觀望了一陣子,直到一個月前才訂購
那時候假如再上 Amazon 訂就太晚了
所以我是到天瓏書局訂購
便利商店取貨,加運費總共是 NTD. 1827

稍微翻過書內容,覺得還不錯
不過少了一些東西~
像是 AS 3.0 重要的新功能 RegExp, Proxy, ApplicationDomain (RSL) 都沒提到
還有 Object Serialization 只有在 Interface 一章展示一個簡單的 Class
但是完全沒有用到 AS 3.0 Object Serialize 功能 Read more...

AS3 Dictionary 居然無法用 QName 當 Key   [+/-]

Ticore's Blog

Dictionary 是 ActionScript 3.0 新的容器類別
具有 Weak Reference 功能
可以將 Object 當作 Key,存入其它 Value
不過剛才想要用 QName 當作 Key 存入 Dictionary
居然會出現錯誤訊息~~

原因可能是這個動作被 AVM 當作利用 QName 存取 Dictionary Class Member

var dict:Dictionary = new Dictionary();
try {
 dict[new QName("http://www.ticore.com", "t")] = null;
} catch (e:Error) {
 trace(e);
 // ReferenceError: Error #1056: 無法在 flash.utils.Dictionary 上建立屬性 http://www.ticore.com::t。
}
Read more...

2007年7月23日星期一

Flash Media Server 效能調校   [+/-]

Ticore's Blog

這篇文章寫了很多關於 FMS 效能調校的方式
非常值得參考~

bpurcell.org - Flash Media Server 2.0 Performance Tuning on Windows

Read more...

AS3 Class 靜態程式碼區塊使用其它 Class 順序   [+/-]

Ticore's Blog

ActionScript 3.0 中 global, package, class
都可以塞入靜態程式碼區塊
其中 class 的程式碼區塊最早被執行
假如在 class 靜態區塊使用到其它 class
就需要注意到先後順序的問題~

以下是測試程式:

package {
 import flash.display.*;
 public class main extends MovieClip {
  public function main ():*{
  }
 }
 {
  try {
   trace(new Obj1()); // [object Obj1]
   trace(new Obj2()); // [object Obj2]
  } catch (e:Error) {
   trace(e);
  }
 }
}


try {
 trace(new Obj1()); // [object Obj1]
 trace(new Obj2()); // [object Obj2]
} catch (e:Error) {
 trace(e);
}

class Obj1 {
 {
  try {
   new Obj2();
  } catch (e:Error) {
   trace(e);
   // TypeError: Error #1115: ::Obj2 不是建構函式。
  }
 }
}

class Obj2 {
 {
  try {
   trace(new Obj1()); // [object Obj1]
  } catch (e:Error) {
   trace(e);
  }
 }
}

相關連結:
ActionScript 3 靜態初始子
AS3 global, package 程式碼區塊初始化順序

Read more...

AS3 global, package 程式碼區塊初始化順序   [+/-]

Ticore's Blog

除了 Class 內的靜態初始區塊之外
global, package 也都可以加入程式碼區塊
以下對於這些區塊執行順序作一個測試

package {
 import flash.display.*;
 {
   trace("package init 1");
 }
 public class main extends MovieClip {
  {
   trace("main class init 1");
  }
  public function main ():*{
   trace("main();");
   new Obj();
  }
  {
   trace("main class init 2");
  }
 }
 {
   trace("package init 2");
 }
}

trace("global init 1");

class Obj {
 {
  trace("Obj class init 1");
 }
 public function Obj():*{
  trace("Obj();");
 }
 {
  trace("Obj class init 2");
 }
}

trace("global init 2");

輸出結果:

main class init 1
main class init 2
Obj class init 1
Obj class init 2
package init 1
package init 2
global init 1
global init 2
main();
Obj();

相關連結:
ActionScript 3 靜態初始子
AS3 Class 靜態程式碼區塊使用其它 Class 順序

Read more...

2007年7月22日星期日

AS3 技巧 - 利用 with 跳過編譯器 Strict Mode 檢查   [+/-]

Ticore's Blog

ActionScript 3.0 語法變的相當嚴謹
編譯期檢查也是~~
假如編譯時該 Class or Interface or *.swc 不存在於 Classpath 下
就會出現錯誤訊息

Flash CS3 與 Flex 2.0 Builder 都有提供關閉 Strict Mode 編譯選項
不過一旦關閉就會喪失全部編譯檢查的功能

介紹一個小技巧,可以局部跳過編譯期 Strict Mode 檢查

只要利用 with 程式碼區塊就可以了
以下是簡單的示範

假設 Main Class 在編譯期無法取得 RSL Class
在 Main Class 讀取外部 RSL
讀取完畢之後,利用 with 區塊直接實體化 RSL Class

Main Class:

package {
 import flash.display.*;
 import flash.net.*;
 import flash.events.*;
 import flash.system.*;
 import flash.utils.*;
 
 public class main extends MovieClip {
  
  private var extLibLoader:Loader;
  
  public function main ():*{
   init();
  }
  
  public function init():*{
   extLibLoader = new Loader();
   var req:URLRequest = new URLRequest("ExtLib.swf");
   var lcxt:LoaderContext = new LoaderContext(false, ApplicationDomain.currentDomain);
   extLibLoader.contentLoaderInfo.addEventListener(Event.INIT, onLibInit);
   extLibLoader.load(req, lcxt);
  }
  
  public function onLibInit(evtObj:Event):*{
   trace("onLibInit();");
   with({}) {
    // Begin non-strict mode
    
    new ObjClass();
    
    // End non-strict mode
   }
  }
 }
}

當然,ActionScript 2.0 也可以用這個方式來逃避編譯期檢查
不過 AS2 比較鬆散,很多方式都可以跳過檢查

相關連結:
ActionScript "with" Block Scope 遮蔽效應
AS3 Compiler Strict Mode Bug

Read more...

2007年7月20日星期五

AS3 Document Class 實體化怪異現象   [+/-]

Ticore's Blog

繼上次的問題 RSL Document Class 實體化造成 Player Crash Bug
縮小範圍測試,不用 RSL
僅額外產生 Document Class 實體

測試 1, 在建構式產生額外 Document 實體:

package {
 import flash.display.*;
 import flash.errors.*;
 import flash.utils.*;

 public class main extends MovieClip {
     
  static public var m:MovieClip;

  public function main():* {
   init();
  }
        
  public function init():* {
   try {
    if (m == null) {
     m = new main();
    }
   } catch (e:Error) {
    trace(e);
   }
  }
 }
}

結果會出現 Error

Error: Error #2136: SWF 檔案 file:///C|/......./main.swf 包含無效的資料。

測試 2, 在靜態初始子產生額外 Document 實體:

package {
 import flash.display.*;
 import flash.errors.*;
 import flash.utils.*;

 public class main extends MovieClip {

  {
    if (m == null) {
     m = new main();
    }
  }

  static public var m:MovieClip;

  public function main():* {
  }
 }
}

這樣就可以成功產生了~
實在是非常怪異
不知道 Document Class 與一般 Class 有什麼樣的差異造成這樣的結果

相關連結:
RSL Document Class 實體化造成 Player Crash Bug
利用 static 區塊建立額外 Document Class 實體
Flex Embed 外部資源技巧

Read more...

2007年7月19日星期四

RSL Document Class 實體化造成 Player Crash Bug   [+/-]

Ticore's Blog

又是一個會造成 Flash Player 9 Crash 的 Bug
當利用 ApplicationDomain 讀取外部 Runtime Shared Library (RSL) 完畢後
在 Main Movie 取得 RSL Document Class 之後,加以實體化
就會造成 Fash Player 9 Crash 了

RSL Document Class 內無特別的程式
但是要讓 Bug 觸發,需要在 RSL Stage 上隨便畫一點東西

RSL Document Class:

package {
 import flash.display.*;
 public class rsl extends MovieClip {
 }
}

Main Document Class:

package {
 import flash.display.*;
 import flash.net.*;
 import flash.events.*;
 import flash.system.*;
 import flash.errors.*;
 
 public class main extends MovieClip {
  
  private var rslLoader:Loader;
  
  public function main():*{
   init();
  }
  
  public function init():*{
   rslLoader = new Loader();
   var req:URLRequest = new URLRequest("rsl.swf");
   var lcxt:LoaderContext = new LoaderContext(false, ApplicationDomain.currentDomain);
   rslLoader.contentLoaderInfo.addEventListener(Event.INIT, onLoadInit);
   rslLoader.load(req, lcxt);
  }
  
  public function onLoadInit(evtObj:Event):*{
   try {
    var rsl:Class = ApplicationDomain.currentDomain.getDefinition("rsl") as Class;
    new rsl();
   } catch (e:Error) {
    trace(e);
   }
  }
 }
}

這個 Bug 在以下版本 Flash Player 測試過會發生:
Flash Player 9.0.28.0
Flash Player 9.0.47.0
Flash Player 9.0.60.120

Flash Player 9.0.60.235 之後已經對此作修正

相關連結:
AS3 Document Class 實體化怪異現象
利用 static 區塊建立額外 Document Class 實體

Read more...

2007年7月17日星期二

Degrafa - A Flex Graphics Framework   [+/-]

Ticore's Blog

MS SilverLight 提供相當完整的 XML 描述向量圖形的方式
Flex 在這方面顯得非常缺乏
只能採用 AS3 程式畫圖,或是嵌入 Flash 預先畫好的 Assets

Degrafa 便是補 Flex 這方面的不足
讓 Flex Developer 也可以用 XML 描述圖像
不過目前還沒有 release

據稱 Degrafa 可以用以下的 XML 畫出 11 條垂直線:

<Strokes>
    <mx:Stroke id="OrangeStroke" color="#EE9819" />
</Strokes>
<Geometry:Line Stroke="{OrangeStroke}"
    x="10" y="10" x1="0" y1="100"/>
<Geometry:Line Stroke="{OrangeStroke}"
    x="10" y="10" x1="0" y1="100">
    <Geometry:repeater>
        <Repeaters:LineRepeater count="11" moveOffsetX="10"
            moveOffsetY="0" offsetX="10" offsetY="0"/>
    </Geometry:repeater>
</Geometry:Line>
Read more...

2007年7月13日星期五

AS技巧 - 快速移除重複陣列元素改版   [+/-]

Ticore's Blog

上一篇有提到 ActionScript 利用 Object 移除重複陣列元素
由於是利用 toString() 決定相等性
遇到 Complex Object 會有問題
這次加入較多判定因子
可以用來區分 Complex Object

ActionScript 2.0 getUniqueArray:

Object.prototype.hashCode = function():String  {
 if (this instanceof String) {
  return "String@" + this;
 }
 if (this.__hashCode__ == null) {
  this.__hashCode__ = this.toString() + "@" + Math.random();
 }
 return this.__hashCode__;
};

ASSetPropFlags(Object.prototype, "hashCode", 7, 0);
ASSetPropFlags(Object.prototype, "__hashCode__", 7, 0);


function getUniqueArray(ary:Array):Array {
 var obj:Object = {};
 for (var i:Number = 0; i < ary.length; ++i) {
  obj[ary[i].hashCode()] = ary[i];
 }
 var newAry:Array = [];
 for (var s:String in obj) {
  newAry.push(obj[s]);
 }
 return newAry;
}

// 測試程式
var ary:Array = [];
ary.push("a");
ary.push("a");
trace(getUniqueArray(ary)); // a

var ary:Array = [];
ary.push(1);
ary.push("1");
trace(getUniqueArray(ary)); // 1,1

var ary:Array = [];
var subAry1:Array = ["a"];
ary.push(subAry1);
ary.push("a");
trace(getUniqueArray(ary)); // a,a

var ary:Array = [];
var subAry1:Array = ["a", "b"];
var subAry2:Array = ["a", "b"];
ary.push(subAry1);
ary.push(subAry2);
trace(getUniqueArray(ary)); // a,b,a,b
trace(getUniqueArray(ary).length); // 2

相關連結:
AS 技巧- 利用Object 快速移除Array 內重複元素

Read more...

AS 技巧 - 利用 Object 快速移除 Array 內重複元素   [+/-]

Ticore's Blog

ActionScript 原生的 Object 其實很類似 Java 語言內的 HashMap
且 Object 內 Key 值是不允許重複的
藉由這些特性,可以用來移除 Array 內重複的元素

ActionScript 2.0 getUniqueArray:

var myArray:Array = ["a", "b", "c", "a"];

function getUniqueArray(ary:Array):Array{
 var obj:Object = {};
 for (var i:Number = 0; i < ary.length; ++i) {
  obj[ary[i]] = ary[i];
 }
 var newAry:Array = [];
 for (var s:String in obj) {
  newAry.push(obj[s]);
 }
 return newAry;
}

trace(getUniqueArray(myArray));

ActionScript 3.0 getUniqueArray:

var myArray:Array = ["a", "b", "c", "a"];

function getUniqueArray(ary:Array):Array{
 var dict:Object = new Dictionary();
 for (var i:Number = 0; i < ary.length; ++i) {
  dict[ary[i]] = null;
 }
 var newAry:Array = [];
 for (var s:String in dict) {
  newAry.push(s);
 }
 return newAry;
}

trace(getUniqueArray(myArray));

需要注意的是 AS2 的用法,比較適用於 Primitive Object
假如陣列元素是 Complex Object,可能需要自己建立 toString() 決定物件資料相等性
才能適用此 function

至於 AS3 的版本,由於有 Dictionary Class
所以也可以用於 Complex Object Array

相關連結:
AS技巧 - 快速移除重複陣列元素改版
Remove all duplicates from an array

Read more...

Flash CS3 Export Class in Frame Bug   [+/-]

Ticore's Blog

Flash CS3 可以允許設定 AS Class 輸出影格
理論上,可以降低影格 1 的大小,讓 Preloader 發揮效用
不過實際上卻有一些 Bug 存在

開一空白 Flash 文件,按下 Ctrl + Shift + F12
在 ActionScript Setting 中設定 "Export classes in frame 2"

建立一個 MovieClip 設定 Class Name
勾選 "Export for ActinScript"
取消勾選 "Export in first frame"

回到主場景,影格拉到 3 格
將建立好的 MovieClip 放在影格 3
設定 Instance Name

按下 Ctrl + Enter 測試影片
就會得到錯誤訊息:

TypeError: Error #1034: 強制轉型失敗:
無法將 flash.display::MovieClip@33e3971 轉換成 Obj。

表示 Class 根本沒有輸出~~
改善的做法是不要設定 Instance Name

這樣實在很不方便

Read more...

Flash CS3 jsfl 也支援 E4X, RegExp   [+/-]

Ticore's Blog

E4X、RegExp 是 ActionScript 3.0 重要的新特色
沒想到 Flash CS3 JavaScript API 也支援
以下是簡單的測試程式

Flash CS3 jsfl:

var xml =   
<xml xmlns:ns="http://www.ticore.com">  
 <node1 attr1="Attribute 1" attr2="Attribute 2"/>
 <node2/>
 <ns:node3/>
</xml>;  
fl.trace(xml.node1.@attr1); // Attribute 1
fl.trace(xml.node1.name()); // node1

try {
 fl.trace(xml.*.(name() == "node1"));
} catch (e) {
 fl.trace(e); // ReferenceError: name is not defined
}

fl.trace(xml[new QName("http://www.ticore.com", "node3")].toXMLString());
// <ns:node3 xmlns:ns="http://www.ticore.com"/>


var reg = /^[A-z]+$/;
fl.trace(reg.test("vdsv")); // ture
fl.trace(reg.test("cs12c")); // false
fl.trace("vns 12 smk43a md".replace(/[0-9]+/g, "="));

不過 Flash CS3 jsfl 的 E4X 在使用篩選運算子上似乎有點小問題
既然文件上沒有寫,姑且不算是 Bug 好了

相關連結:
JSFL updated to JavaScript 1.6, gains E4X

AS3 - Inline 宣告 XMLList 物件方式
AS3 E4X 互補方案 XPath
AS3 E4X - QName 相關操作
AS3 利用 QName 快速存取 Namespace Member
AS3 E4X - XML 節點包覆
AS3 E4X 資料取出與計算
AS3 E4X - XML 節點交換
AS3 E4X - 插入 XML 節點
AS3 E4X - 刪除 XML 節點
AS3 E4X Tip - 你拿到的是 XML or XMLList?
AS3 E4X 技巧 - 替 XML 添加 prototype fnuction
AS3 E4X - XML Attribute 相關操作
用 @* 指定 Attributes 造成 Flash Player 9 Crash
AS3 E4X - XML、XMLList 物件內子節點參考指定與複製
AS3 E4X - XML 物件比較
AS3 E4X - 相關類別與物件建立
AS2、AS3 基礎型別物件一致性
原來 Firefox 1.5 就已經開始支援 E4X

Read more...

Flash Shared Library 測試影片影格跳躍 Bug   [+/-]

Ticore's Blog

假如有用到 gotoAndStop 作影格跳躍,且目標影格上有用到外部 Shared Lib. Asset
用 Flash IDE 測試影片,便會發生影格跳躍失敗的情況

假設 Flash 文件有兩個影格:

[Frame 1]
 ActionScript:
  gotoAndStop(2);
[Frame 2]
 在 Stage 上使用 Shared Lib. Asset

外部 Shared Lib. 也準備好之後
主影片用 Ctrl + Enter 測試
就會發現畫面白白的,影格跳躍失敗

這 Bug 發生於 Flash 7、8、9 IDE 環境
Flash 6 可能也是一樣,只是沒測試過

Read more...

2007年7月12日星期四

Flex ArrayCollection as Array 使用方式   [+/-]

Ticore's Blog

Flex Framewrok 下有一個集合類別 ArrayCollection
是 Array 的外覆類別,文件上只有暴露 API 部分
其實它是用 AS3 新功能 Proxy 實作的
所以可以直接把 ArrayCollection 當作是 Array 來操作

ArrayCollection as Array 使用範例:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
 layout="absolute" creationComplete="init();">
 <mx:Script>
  <![CDATA[
   
   import mx.collections.*;
   
   public var testData:ArrayCollection = new ArrayCollection(
    [
     {A1:"A1", A2:"A2", children:new ArrayCollection(
      [
       {B1:"B1", B2:"B2", children:new ArrayCollection(
        [
         {C1:"C1", C2:"C2"}, {D1:"D1", D2:"D2"}
        ])
       },
       {E1:"E1", E2:"E2"}
      ])
     }
    ]);
    
   public function init():*{
    trace(testData[0].children[0].B1);
    trace(testData[0].children[1].E1);
    trace(testData[0].children[0].children[0].C1);
    trace(testData[0].children[0].children[1].D1);
   }
   
  ]]>
 </mx:Script>
</mx:Application>
Read more...

2007年7月11日星期三

Flash 技巧 - 利用 Shared Library 掛勾外部 Lib Asset   [+/-]

Ticore's Blog

Flash 6 開始支援 Shared Library 功能
到現在已經很久了,用的人似乎很少
主要可能是設置有點麻煩,欠缺彈性
ActionScript 3.0 則是 ApplicationDomain 相關方式來取代

假如非得要把 Library Assets 分割為多個外部 swf 檔案
且必須要使用 ActionScript 在主影片動態 attachMvoie 外部 Assets
那麼 Shared Library 就是不二選擇了

不過 Assets 數量一多,會非常麻煩
以下介紹一個小技巧,可以省去不少工作

其實在主影片內,只要掛勾一個外部 Shared Library Asset
待 Shared Lib. swf 完全讀入後,所有外部 Shared Lib. 內的 Assets 都可以直接使用了
根本不需要一個一個設置

Read more...

2007年7月10日星期二

AS3 E4X 互補方案 XPath   [+/-]

Ticore's Blog

ActionScript 3.0 E4X 功能已經非常好用
尤其是篩選運算子 XML.(expr)
不過有些小地方稍嫌不足
Query 語法不能完全從 String 動態解析
Axis 軸的功能比較弱
以下介紹一個 AS3 XPath OpenSource

AS3 XPath 似乎還沒有完整支援 XPath
而且不是原生支援
執行效能應該是不高
不過可以當作 AS3 E4X 互補方案

AS3 XPath 的一些用法:

import memorphic.xpath.*;
import memorphic.xpath.model.*;

var xml:XML =
<path attr1="Attribute 1" attr2="Attribute 2">
 <to>
  <node index="1" price="10">1</node>
  <node index="2" price="20">2</node>
  <node index="3" price="30">3</node>
 </to>
</path>;

trace(new XPathQuery("path/to/node[1]").exec(xml).toXMLString());
trace(new XPathQuery("path/to/node[text()>2]/text()").exec(xml).toXMLString());
trace(new XPathQuery("path/to/child::node()").exec(xml).toXMLString());
trace(new XPathQuery("path/to/node[position()=3]").exec(xml).toXMLString());
trace(new XPathQuery("path/@attr2").exec(xml));
trace(new XPathQuery("path/to/node[@index=1][name()='node']").exec(xml).toXMLString());
trace(new XPathQuery("path/to/node[1]|path/to/node[2]").exec(xml).toXMLString());
trace(new XPathQuery("path//node").exec(xml).toXMLString());
trace(new XPathQuery("path/descendant::node").exec(xml).toXMLString());

var xq:XPathQuery = new XPathQuery("path/to/node[trace(@index + $prop)]");
xq.context.variables.prop = getTimer();
xq.context.functions.trace = function (context:XPathContext, ... args):void{
 //trace(arguments);
 trace(args);
};
xq.exec(xml);

AS3 XPath Namespace 用法:

import memorphic.xpath.*;
import memorphic.xpath.model.*;

var xml:XML =
<path xmlns:ns1="http://www.ticore.com/ns1" xmlns:ns2="http://www.ticore.com/ns2">
 <to>
  <ns1:node>1</ns1:node>
  <ns2:node>2</ns2:node>
 </to>
</path>;

var xq1:XPathQuery = new XPathQuery("path/to/ns1:node");
xq1.context.namespaces.ns1 = "http://www.ticore.com/ns1";
trace(xq1.exec(xml).toXMLString());

相關連結:
AS3 - Inline 宣告 XMLList 物件方式
Flash CS3 jsfl 也支援 E4X, RegExp
AS3 E4X - QName 相關操作
AS3 利用 QName 快速存取 Namespace Member
AS3 E4X - XML 節點包覆
AS3 E4X 資料取出與計算
AS3 E4X - XML 節點交換
AS3 E4X - 插入 XML 節點
AS3 E4X - 刪除 XML 節點
AS3 E4X Tip - 你拿到的是 XML or XMLList?
AS3 E4X 技巧 - 替 XML 添加 prototype fnuction
AS3 E4X - XML Attribute 相關操作
用 @* 指定 Attributes 造成 Flash Player 9 Crash
AS3 E4X - XML、XMLList 物件內子節點參考指定與複製
AS3 E4X - XML 物件比較
AS3 E4X - 相關類別與物件建立
AS2、AS3 基礎型別物件一致性
原來 Firefox 1.5 就已經開始支援 E4X

Read more...

2007年7月9日星期一

AS2 RegExp Class   [+/-]

Ticore's Blog

ActionScript 直到 3.0 才支援 RegExp
假如想要在 AS 1.0、2.0 使用 RegExp
可以參考
RegExp class for Flash 5 / Flash MX
as2lib Framework

不過 As2lib 的 RegExp 實在非常難用,而且累贅
稍微測試過,僅僅只是編譯 as2lib RegExp 必要 Class,就會產生 23 kb 左右的大小
Pavils Jurjans RegExp Class 只有支援到 AS 1.0 寫法
於是花了點時間改寫為 AS 2.0 格式

使用範例:

trace(new RegExp("[0-9]+A[0-9]+").test("67A28"));
trace(new RegExp("[0-9]+A[0-9]+").test("67AB28"));
trace(new RegExp("[0-9]+A[0-9]+").exec("67A28"));

RegExp Class:

dynamic class RegExp {

 public var const:String = "RegExp";
 public var source:String = "";
 public var global:Boolean = false;
 public var ignoreCase:Boolean = false;
 public var multiline:Boolean = false;

 public function RegExp() {
  if (arguments[0] == null) {
   return;
  }
  this.compile(arguments[0],arguments[1],arguments[2]);
 }
 public function compile() {
  this.source = arguments[0];
  var flags = (arguments[1] + '').toLowerCase();
  this.global = false;
  this.ignoreCase = false;
  this.multiline = false;
  for (var i = 0; i < length(flags); i++) {
   if (substring(flags, i + 1, 1) == "g") {
    this.global = true;
   }
   if (substring(flags, i + 1, 1) == "i") {
    this.ignoreCase = true;
   }
   if (substring(flags, i + 1, 1) == "m") {
    this.multiline = true;
   }
  }
  if (arguments[2] == null) {
   var root = true;
   RegExp._xr = 1;//Paren counter
   var i = 0;
  } else {
   var root = false;
   this._xr = RegExp._xr++;
   var i = arguments[2];
  }
  this.lastIndex = 0;

/*
Compile the regular expression
The array of character definition objects will be created:
  q[n].t    -->  type of match required: 0  = exact
                                         1  = in char set
 2  = not in char set
 3  = paren
 4  = ref to paren
 7  = new "OR" section
 9  = beginning of line
 10 = end of line
  q[n].s    -->  character or character set
  q[n].a    -->  character has to repeat at least a times
  q[n].b    -->  character has to repeat at most b times
*/

  var re = this.source;
  var ex;
  var l = length(re);
  var q = [];
  var qc = 0;
  var s;
  var range = false;
  var ca;
  var cb;
  var atEnd = false;

  for (i = i; i < l; ++i) {
   var thischar = substring(re, i + 1, 1);
   if (thischar == "\\") {
    i++;
    char = false;
    thischar = substring(re, i + 1, 1);
   } else {
    char = true;
   }
   var nextchar = substring(re, i + 2, 1);
   q[qc] = new Object();
   q[qc].t = 0;
   q[qc].a = 0;
   q[qc].b = 999;
   q[qc].c = -10;

   if (char) {
    // Handle special characters
    if (thischar == "(") {
     //Opening paren
     ex = new RegExp(re, (this.ignoreCase ? "gi" : "g"), i + 1);
     i = RegExp._xi;
     q[qc].t = 3;
     thischar = ex;
     nextchar = substring(re, i + 2, 1);

    } else if (!root && thischar == ")") {
     //Closing paren
     break;

    } else if (thischar == "^") {
     //Must be located at the beginning of string/line
     if (qc == 0 || q[qc - 1].t == 7) {
      q[qc].t = 9;
      q[qc].a = 1;
      q[qc].b = 1;
      qc++;
     }
     continue;

    } else if (thischar == "$") {
     //Must be located at the end of string/line
     if (root) {
      atEnd = true;
     }
     continue;

    } else if (thischar == "[") {
     //This is a character set
     i++;
     if (nextchar == "^") {
      q[qc].t = 2;
      i++;
     } else {
      q[qc].t = 1;
     }
     thischar = "";
     range = false;
     while (i < l && (s = substring(re, 1 + i++, 1)) != "]") {
      if (range) {
       //Previous char was "-", so create a range
       if (s == "\\") {
       }
       cb = s == "\\" ? (s == "b" ? chr(8) : substring(re, 1 + i++, 1)) : s;
       ca = ord(substring(thischar, length(thischar), 1)) + 1;
       while (cb >= (s = chr(ca++))) {
        thischar += s;
       }
       range = false;
      } else {
       if (s == "-" && length(thischar) > 0) {
        //Character range is being defined
        range = true;
       } else {
        if (s == "\\") {
         //Predefined char set may follow
         s = substring(re, 1 + i++, 1);
         if (s == "d") {
          thischar += "0123456789";
         } else if (s == "D") {
          thischar += invStr("0123456789");
         } else if (s == "s") {
          thischar += " \f\n\r\t\v";
         } else if (s == "S") {
          thischar += invStr(" \f\n\r\t\v");
         } else if (s == "w") {
          thischar += "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
         } else if (s == "W") {
          thischar += invStr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_");
         } else if (s == "b") {
          thischar += chr(8);
         }
        } else {
         thischar += s;
        }
       }
      }
     }
     i--;
     var nextchar = substring(re, i + 2, 1);

    } else if (thischar == "|") {
     //OR section
     if (atEnd) {
      q[qc].t = 10;
      q[qc].a = 1;
      q[qc].b = 1;
      qc++;
      q[qc] = new Object();
      atEnd = false;
     }
     q[qc].t = 7;
     q[qc].a = 1;
     q[qc].b = 1;
     qc++;
     continue;

    } else if (thischar == ".") {
     q[qc].t = 2;
     thischar = "\n";

    } else if (thischar == "*" || thischar == "?" || thischar == "+") {
     continue;
    }
   } else {
    if (thischar >= "1" && thischar <= "9") {
     q[qc].t = 4;
    } else if (thischar == "b") {
     q[qc].t = 1;
     thischar = "--wb--";
    } else if (thischar == "B") {
     q[qc].t = 2;
     thischar = "--wb--";
    } else if (thischar == "d") {
     q[qc].t = 1;
     thischar = "0123456789";
    } else if (thischar == "D") {
     q[qc].t = 2;
     thischar = "0123456789";
    } else if (thischar == "s") {
     q[qc].t = 1;
     thischar = " \f\n\r\t\v";
    } else if (thischar == "S") {
     q[qc].t = 2;
     thischar = " \f\n\r\t\v";
    } else if (thischar == "w") {
     q[qc].t = 1;
     thischar = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
    } else if (thischar == "W") {
     q[qc].t = 2;
     thischar = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
    }
   }

   //Counting metacharacters
   if (nextchar == "*") {
    q[qc].s = thischar;
    qc++;
    i++;
   } else if (nextchar == "?") {
    q[qc].s = thischar;
    q[qc].b = 1;
    qc++;
    i++;
   } else if (nextchar == "+") {
    q[qc].s = thischar;
    q[qc].a = 1;
    qc++;
    i++;
   } else if (nextchar == "{") {
    var comma = false;
    var rangeA = 0;
    range = "";
    i++;
    while (i + 1 < l && (s = substring(re, 2 + i++, 1)) != "}") {
     if (!comma && s == ",") {
      comma = true;
      rangeA = Number(range);
      rangeA = Math.floor(isNan(rangeA) ? 0 : rangeA);
      if (rangeA < 0) {
       rangeA = 0;
      }
      range = "";
     } else {
      range += s;
     }
    }
    rangeB = Number(range);
    rangeB = Math.floor(isNan(rangeB) ? 0 : rangeB);
    if (rangeB < 1) {
     rangeB = 999;
    }
    if (rangeB < rangeA) {
     rangeB = rangeA;
    }
    q[qc].s = thischar;
    q[qc].b = rangeB;
    q[qc].a = comma ? rangeA : rangeB;
    qc++;
   } else {
    q[qc].s = thischar;
    q[qc].a = 1;
    q[qc].b = 1;
    qc++;
   }
  }
  if (root && atEnd) {
   q[qc] = new Object();
   q[qc].t = 10;
   q[qc].a = 1;
   q[qc].b = 1;
   qc++;
  }
  if (!root) {
   RegExp._xi = i;
   this.source = substring(re, arguments[2] + 1, i - arguments[2]);
  }

  if (RegExp.d) {
   for (var i = 0; i < qc; i++) {
    trace("xr" + this._xr + ' ' + q[i].t + " : " + q[i].a + " : " + q[i].b + " : " + q[i].s);
   }
  }

  this._xq = q;
  this._xqc = qc;

  RegExp._xp = 0;
 }


 public function test() {

  if (RegExp._xp++ == 0) {
   RegExp._xxa = [];//Temp array for storing paren matches
   RegExp._xxlp = 0;//Last paren
  }
  //  q[n].c  -->  count of matches   
  //  q[n].i  -->  index within the string

  var str = arguments[0] + '';
  var re;

  var q = this._xq;
  var qc = this._xqc;
  var qb;
  var c;
  var cl;
  var ct;
  var s;

  var l = length(str);
  var ix = this.global ? this.lastIndex : 0;
  var ix_ = ix;

  var str_ = str;
  if (this.ignoreCase) {
   str = str.toLowerCase();
  }

  var r = new Object();
  r.i = -1;

  var i = -1;

  while (i < qc - 1) {
   i++;
   if (RegExp.d) {
    trace("New section started at i=" + i);
   }
   ix = ix_;
   qb = i;
   q[qb].c = -10;
   var atEnd = false;
   while (i > qb || ix < l + 1) {
    if (q[i].t == 7) {
     //New "OR" section coming
     break;
    } else if (q[i].t == 9) {
     i++;
     if (i == qb + 1) {
      atStart = true;
      qb = i;
     }
     q[qb].c = -10;
     continue;
    } else {
     if (r.i >= 0 && ix >= r.i) {
      //There is already better match, so quit searching
      break;
     }
     if (q[i].c == -10) {
      if (RegExp.d) {
       trace("Lookup #" + i + " at index " + ix + " for \'" + q[i].s + "\' type " + q[i].t);
      }
      //Count the # of matches   
      var m = 0;
      q[i].i = ix;
      if (q[i].t == 0) {
       //Exact match
       c = this.ignoreCase ? q[i].s.toLowerCase() : q[i].s;
       while (m < q[i].b && ix < l) {
        if (substring(str, 1 + ix, 1) == c) {
         m++;
         ix++;
        } else {
         break;
        }
       }
      } else if (q[i].t == 1) {
       //In char set
       if (q[i].s == "--wb--") {
        q[i].a = 1;
        if (ix > 0 && ix < l) {
         ct = substring(str, ix, 1);
         if (ct == " " || ct == "\n") {
          m = 1;
         }
         if (m == 0) {
          ct = substring(str, 1 + ix, 1);
          if (ct == " " || ct == "\n") {
           m = 1;
          }
         }
        } else {
         m = 1;
        }
       } else {
        c = this.ignoreCase ? q[i].s.toLowerCase() : q[i].s;
        cl = length(c);
        while (m < q[i].b && ix < l) {
         ct = substring(str, 1 + ix, 1);
         cs = 0;
         while (cs <= cl && substring(c, 1 + cs++, 1) != ct) {
         }

         if (cs <= cl) {
          m++;
          ix++;
         } else {
          break;
         }
        }
       }
      } else if (q[i].t == 2) {
       //Not in char set
       c = this.ignoreCase ? q[i].s.toLowerCase() : q[i].s;
       cl = length(c);
       if (q[i].s == "--wb--") {
        q[i].a = 1;
        if (ix > 0 && ix < l) {
         ct = substring(str, ix, 1);
         s = substring(str, 1 + ix, 1);
         if (ct != " " && ct != "\n" && s != " " && s != "\n") {
          m = 1;
         }
        } else {
         m = 0;
        }
       } else {
        while (m < q[i].b && ix < l) {
         ct = substring(str, 1 + ix, 1);
         cs = 0;
         while (cs <= cl && substring(c, 1 + cs++, 1) != ct) {
         }

         if (cs <= cl) {
          break;
         } else {
          m++;
          ix++;
         }
        }
       }
      } else if (q[i].t == 10) {
       //End of string/line must be next
       s = substring(str, 1 + ix, 1);
       m = (this.multiline && (s == "\n" || s == "\r")) || ix == l ? 1 : 0;
      } else if (q[i].t == 3) {
       //Regular expression in parens
       re = q[i].s;
       q[i].ix = [];
       q[i].ix[m] = ix;//Save index if need to retreat
       re.lastIndex = ix;
       while (m < q[i].b && re.test(str_)) {
        cl = length(RegExp._xxlm);
        if (cl > 0) {
         ix += cl;
         m++;
         q[i].ix[m] = ix;
        } else {
         m = q[i].a;
         q[i].ix[m - 1] = ix;
         break;
        }
       }
       if (m == 0) {
        RegExp._xxlm = "";
       }
       if (re._xr > RegExp._xxlp) {
        RegExp._xxlp = re._xr;
       }
       RegExp._xxa[re._xr] = RegExp._xxlm;
      } else if (q[i].t == 4) {
       //Back reference to paren
       if (RegExp._xp >= (c = Number(q[i].s))) {
        c = RegExp._xxa[c];
        c = this.ignoreCase ? c.toLowerCase() : c;
        cl = length(c);
        q[i].ix = [];
        q[i].ix[m] = ix;
        if (cl > 0) {
         while (m < q[i].b && ix < l) {
          if (substring(str, 1 + ix, cl) == c) {
           m++;
           ix += cl;
           q[i].ix[m] = ix;
          } else {
           break;
          }
         }
        } else {
         m = 0;
         q[i].a = 0;
        }
       } else {
        //Paren is not ready, treat number as charcode
        c = chr(c);
        q[i].ix = [];
        q[i].ix[m] = ix;
        while (m < q[i].b && ix < l) {
         if (substring(str, 1 + ix, 1) == c) {
          m++;
          ix++;
          q[i].ix[m] = ix;
         } else {
          break;
         }
        }
       }
      }
      q[i].c = m;
      if (RegExp.d) {
       trace("   " + m + " matches found");
      }
     }
     if (q[i].c < q[i].a) {
      if (RegExp.d) {
       trace("   not enough matches");
      }
      //Not enough matches   
      if (i > qb) {
       //Retreat back and decrease # of assumed matches
       i--;
       q[i].c--;
       if (q[i].c >= 0) {
        ix = (q[i].t == 3 || q[i].t == 4) ? q[i].ix[q[i].c] : (q[i].i + q[i].c);
       }
       if (RegExp.d) {
        trace("Retreat to #" + i + " c=" + q[i].c + " index=" + ix);
       }
      } else {
       if (RegExp._xp > 1) {
        //If this is a paren, failing to find first match is fatal
        break;
       }
       if (atStart) {
        //Match must be at the start of string/line
        if (this.multiline) {
         //Jump to the beginning of the next line
         while (ix <= l) {
          s = substring(str, 1 + ix++, 1);
          if (s == "\n" || s == "\r") {
           break;
          }
         }
         q[i].c = -10;
        } else {
         //No match
         break;
        }
       } else {
        //Start a new search from next position
        ix++;
        q[i].c = -10;
       }
      }
     } else {
      if (RegExp.d) {
       trace("   enough matches!");
      }
      //# of matches ok, proceed to next   
      i++;
      if (i == qc || q[i].t == 7) {
       if (RegExp.d) {
        trace("Saving better result: r.i = q[" + qb + "].i = " + q[qb].i);
       }
       r.i = q[qb].i;
       r.li = ix;
       break;
      } else {
       q[i].c = -10;
      }
     }
    }
   }
   while (i < qc && q[i].t != 7) {
    i++;
   }//Jump to the next "OR" section
  }
  if (r.i < 0) {
   this.lastIndex = 0;
   if (RegExp._xp-- == 1) {
    RegExp._xxa = [];
    RegExp._xxlp = 0;
   }
   return false;
  } else {
   ix = r.li;
   this._xi = r.i;
   RegExp._xxlm = substring(str_, r.i + 1, ix - r.i);
   RegExp._xxlc = substring(str_, 1, r.i);
   RegExp._xxrc = substring(str_, ix + 1, l - ix);
   if (ix == r.i) {
    ix++;
   }
   this.lastIndex = ix;
   if (RegExp._xp-- == 1) {
    RegExp.lastMatch = RegExp._xxlm;
    RegExp.leftContext = RegExp._xxlc;
    RegExp.rightContext = RegExp._xxrc;
    RegExp._xa = RegExp._xxa;
    RegExp.lastParen = RegExp._xxa[RegExp._xxlp];
    for (i = 1; i < 10; i++) {
     RegExp["$" + i] = RegExp._xa[i];
    }
   }
   return true;
  }
 }

 public function exec() {

  var str = arguments[0] + '';
  if (str == '') {
   return false;
  }

  var t = this.test(str);

  if (t) {
   var ra = new Array();
   ra.index = this._xi;
   ra.input = str;
   ra[0] = RegExp.lastMatch;
   var l = RegExp._xa.length;
   for (var i = 1; i < l; i++) {
    ra[i] = RegExp._xa[i];
   }
  } else {
   var ra = null;
  }

  return ra;
 }
 
 public function invStr(s:String):String {
  //var s = this;
  var l = length(s);
  var j;
  var c;
  var r = "";
  for (var i = 1; i < 255; i++) {
   c = chr(i);
   j = 0;
   while (j <= l && substring(s, 1 + j++, 1) != c) {
   }

   if (j > l) {
    r += c;
   }
  }
  return r;
 }
}

License
Please refer to RegExp class for Flash 5 / Flash MX

Read more...

2007年7月6日星期五

Flash CS3 繁體中文完整線上 HTML 文件下載   [+/-]

Ticore's Blog

Flash CS3 LiveDocs 繁體中文版下載位置:
http://rapidshare.com/files/41298410/Flash_9_LiveDocs_tw.rar.html
http://rapidshare.com/files/76893913/Flash_9_LiveDocs_tw.rar

下載過程中,也發現到 Adobe LiveDocs 有連結錯誤的情況
都自行修正了
假如還有發現漏掉的部分,可以留言告訴我~

相關連結:
Flash CS4 繁體中文完整線上 HTML 文件下載

Read more...

AS3 E4X - QName 相關操作   [+/-]

Ticore's Blog

利用 QName 取得 XML Namespace Node:

var xml:XML =
<xml>
 <ns1:node xmlns:ns1="http://www.ticore.com/ns1"/>
 <ns2:node xmlns:ns2="http://www.ticore.com/ns2"/>
 <ns3:node xmlns:ns3="http://www.ticore.com/ns3"/>
 <ns4:node xmlns:ns4="http://www.ticore.com/ns4"/>
</xml>;
trace(xml[new QName("http://www.ticore.com/ns1", "node")].toXMLString());
trace(xml.elements(new QName("http://www.ticore.com/ns2", "node")).toXMLString());
trace(xml.descendants(new QName("http://www.ticore.com/ns3", "node")).toXMLString());
trace(xml.child(new QName("http://www.ticore.com/ns4", "node")).toXMLString());

利用 QName 取得 XML Attribute:

var xml:XML =
<xml
 xmlns:ns1="http://www.ticore.com/ns1"
 xmlns:ns2="http://www.ticore.com/ns2"
 xmlns:ns3="http://www.ticore.com/ns3"
 ns1:attr1="NS1:Attr 1"
 ns2:attr2="NS1:Attr 2"
 ns3:attr3="NS1:Attr 3"
 >
</xml>;
trace(xml.@[new QName("http://www.ticore.com/ns1", "attr1")]);
trace(xml.attribute(new QName("http://www.ticore.com/ns2", "attr2")));
trace(xml[new QName("http://www.ticore.com/ns3", "@attr3")]);

利用 QName 插入 XML 子節點:

var xml:XML =
<ns1:xml xmlns:ns1="http://www.ticore.com/ns1">
 <node/>
</ns1:xml>;
xml[new QName("http://www.ticore.com/ns1", "node")] = "";
xml[new QName("http://www.ticore.com/ns2", "node")] = "";
trace(xml.toXMLString());

利用 QName 插入 Attribute:
假如 XML 沒有設定 Namespace,首次插入的 Attribute Namespace 會變成 default
之後插入的 Attribute Namespace 會自動編號 aaa、aab、......

var xml:XML =
<xml>
 <node/>
</xml>;
xml.@[new QName("http://www.ticore.com/ns1", "attr1")] = "Attribute 1";
xml[new QName("http://www.ticore.com/ns2", "@attr2")] = "Attribute 2";
xml[new QName("http://www.ticore.com/ns3", "@attr3")] = "Attribute 3";
xml[new QName("http://www.ticore.com/ns4", "@attr4")] = "Attribute 4";
trace(xml.toXMLString());

相關連結:
AS3 E4X - Namespace Bug
AS3 - Inline 宣告 XMLList 物件方式
Flash CS3 jsfl 也支援 E4X, RegExp
AS3 E4X 互補方案 XPath
AS3 利用 QName 快速存取 Namespace Member
AS3 E4X - XML 節點包覆
AS3 E4X 資料取出與計算
AS3 E4X - XML 節點交換
AS3 E4X - 插入 XML 節點
AS3 E4X - 刪除 XML 節點
AS3 E4X Tip - 你拿到的是 XML or XMLList?
AS3 E4X 技巧 - 替 XML 添加 prototype fnuction
AS3 E4X - XML Attribute 相關操作
用 @* 指定 Attributes 造成 Flash Player 9 Crash
AS3 E4X - XML、XMLList 物件內子節點參考指定與複製
AS3 E4X - XML 物件比較
AS3 E4X - 相關類別與物件建立
AS2、AS3 基礎型別物件一致性
原來 Firefox 1.5 就已經開始支援 E4X

Read more...

2007年7月5日星期四

AS3 利用 QName 快速存取 Namespace Member   [+/-]

Ticore's Blog

ActionScript 3.0 新增 Class Namespace Member 功能
官方文件上也有示範一般性存取方式
需要事先宣告 Namespace
使用起來有點小麻煩

AS3 E4X 那邊也有所謂的 Namespace
可以 QName Class 可以用來快速存取 XML 物件的 Namespace Element
假如可以把 E4X QName 拿來存取 Class Namespace Member 應該不錯
測試之後,果然可以用
在官方文件上卻沒有寫
以下便是各種存取 Class Namespace Member 示範程式

Obj Class:

package {
 public class Obj {
  
  public namespace ns1 = "http://www.ticore.com/ns1";
  public namespace ns2 = "http://www.ticore.com/ns2";
  public namespace ns3 = "http://www.ticore.com/ns3";
  public namespace ns4 = "http://www.ticore.com/ns4";
  public namespace ns5 = "http://www.ticore.com/ns5";
  
  ns1 var p:String = "p1";
  ns2 var p:String = "p2";
  ns3 var p:String = "p3";
  ns4 var p:String = "p4";
  ns5 var p:String = "p5";
  
 }
}

Main Class:

package {
 import flash.display.*;
 import flash.utils.*;
 public class main extends MovieClip {
  
  public function main () {
   
   var o:Object = new Obj();
   
   // Method 1
   namespace ns1 = "http://www.ticore.com/ns1";
   trace(o.ns1::p);
   
   // Method 2
   var ns2:Namespace = new Namespace("http://www.ticore.com/ns2");
   trace(o.ns2::p);
   
   // Method 3
   var ns3:Namespace = new Namespace("http://www.ticore.com/ns3");
   var q3:QName = new QName(ns3, "p");
   trace(o[q3]);
   
   // Method 4
   var q4:QName = new QName("http://www.ticore.com/ns4", "p");
   trace(o[q4]);
   
   // Method 5
   trace(o[new QName("http://www.ticore.com/ns5", "p")]);
   
  }
 }
}

相關連結:
AS3 - Inline 宣告 XMLList 物件方式
Flash CS3 jsfl 也支援 E4X, RegExp
AS3 E4X 互補方案 XPath
AS3 E4X - QName 相關操作
AS3 E4X - XML 節點包覆
AS3 E4X 資料取出與計算
AS3 E4X - XML 節點交換
AS3 E4X - 插入 XML 節點
AS3 E4X - 刪除 XML 節點
AS3 E4X Tip - 你拿到的是 XML or XMLList?
AS3 E4X 技巧 - 替 XML 添加 prototype fnuction
AS3 E4X - XML Attribute 相關操作
用 @* 指定 Attributes 造成 Flash Player 9 Crash
AS3 E4X - XML、XMLList 物件內子節點參考指定與複製
AS3 E4X - XML 物件比較
AS3 E4X - 相關類別與物件建立
AS2、AS3 基礎型別物件一致性
原來 Firefox 1.5 就已經開始支援 E4X

Read more...

2007年7月3日星期二

AS3 利用 with, Proxy 選擇性替換 Scope Variables   [+/-]

Ticore's Blog

這次改以 ActionScript 3.0 實作 Scope Shield

ScopeShield Class:

package {
 import flash.utils.*;
 public class ScopeShield extends Proxy {
  
  private var shiledRule:Object = {};
  
  public function addVarShield (varName:String, value:* = null):void{
   shiledRule[varName] = value;
  }
  public function removeVarShield (varName:String):void{
   delete shiledRule[varName];
  }
  
  flash_proxy override function hasProperty(varName:*):Boolean{
   //trace("hasProperty : " + varName, shiledRule[varName] == true);
   return shiledRule.hasOwnProperty(varName);
  }
  
  flash_proxy override function callProperty(varName:*, ...rest):* {
   //trace("callProperty : " + varName);
   return shiledRule[varName].apply(null, rest);
  }
  flash_proxy override function getProperty(varName:*):* {
   //trace("getProperty : " + varName);
   return shiledRule[varName];
  }
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

main Class:

package {
 import flash.display.*;
 import flash.events.*;
 import flash.utils.*;
 import flash.system.System;

 public class main extends MovieClip {
  
  private var t:Number = 1000;
  private var shield:ScopeShield;
  
  public function main():*{
   init();
   
   trace("getT() : " + getT());
   // fun shield(1,2,3);
   // getT() : t shield
   
   shield.removeVarShield("t");
   // 移除遮蔽 t 變數
   shield.removeVarShield("fun");
   // 移除遮蔽 fun 變數
   
   trace("getT() : " + getT());
   // fun(1,2,3);
   // getT() : 1000
  }
  
  public function init():*{
   shield = new ScopeShield();
   shield.addVarShield("t", "t shield");
   // 加入遮蔽 t 變數
   shield.addVarShield("fun",
     function(... rest){trace("fun shield(" + rest + ");")});
   // 加入遮蔽 fun 變數
  }
  
  public function fun(... rest):*{
   trace("fun(" + rest + ");");
  }
  
  public function getT():*{
   with(shield) {
    try {
     fun(1, 2, 3);
    } catch (e:Error) {
     trace(e);
    } finally {
     return t;
    }
   }
  }
  
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

相關連結:
AS2 利用 with, Object.__resolve 選擇性替換 Scope Variables
ActionScript "with" Block Scope 遮蔽效應

Read more...

2007年7月2日星期一

AS2 利用 with, Object.__resolve 選擇性替換 Scope Variables   [+/-]

Ticore's Blog

上次介紹過 ActionScript "with" Block Scope 遮蔽效應
理論上,使用 with、Object.__resolve 是可以做到選擇性遮蔽取代 Scope Variables
以下便是 ActionScript 2.0 實作:

ScopeShield Class:

class ScopeShield {
 
 private var shiledObj:Object;
 private var shiledRule:Object = {};
 
 public function ScopeShield(obj:Object) {
  shiledObj = obj;
 }
 public function addVarShield (varName:String, value:Object):Void{
  shiledRule[varName] = value;
 }
 public function removeVarShield (varName:String):Void{
  delete shiledRule[varName];
 }
 public function __resolve (varName:String) {
  if (shiledRule.hasOwnProperty(varName)) {
   return shiledRule[varName];
  } else {
   return shiledObj[varName];
  }
 }
 
}
// Ticore's Blog - http://ticore.blogspot.com/

main Class:

class main {
 
 private var shield:ScopeShield;
 
 public var name:String = "Ticore";
 
 public function main() {
  init();
  
  trace(getName());
  shield.removeVarShield("name");
  // 移除遮蔽 name 變數
  shield.removeVarShield("test");
  // 移除遮蔽 test 變數
  trace(getName());
  
 }
 public function init() {
  shield = new ScopeShield(this);
  shield.addVarShield("name", "name shield");
  // 設定遮蔽 name 變數
  shield.addVarShield("test",
   function(){trace("test shield(" + arguments + ");");});
  // 設定遮蔽 test 變數
 }
 
 public function test() {
  trace("test(" + arguments + ");");
 }
 public function getName() {
  with (shield) {
   test(1, 2, 3);
   return name;
  }
 }
 
}
// Ticore's Blog - http://ticore.blogspot.com/

ScopeShield Class:

package {
 import flash.utils.*;
 public class ScopeShield extends Proxy {
  
  private var shiledRule:Object = {};
  
  public function addVarShield (varName:String, value:* = null):void{
   shiledRule[varName] = value;
  }
  public function removeVarShield (varName:String):void{
   delete shiledRule[varName];
  }
  
  flash_proxy override function hasProperty(varName:*):Boolean{
   //trace("hasProperty : " + varName, shiledRule[varName] == true);
   return shiledRule.hasOwnProperty(varName);
  }
  
  flash_proxy override function callProperty(varName:*, ...rest):* {
   //trace("callProperty : " + varName);
   return shiledRule[varName].apply(null, rest);
  }
  flash_proxy override function getProperty(varName:*):* {
   //trace("getProperty : " + varName);
   return shiledRule[varName];
  }
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

main Class:

package {
 import flash.display.*;
 import flash.events.*;
 import flash.utils.*;
 import flash.system.System;

 public class main extends MovieClip {
  
  private var t:Number = 1000;
  private var shield:ScopeShield;
  
  public function main():*{
   init();
   
   trace("getT() : " + getT());
   // fun shield(1,2,3);
   // getT() : t shield
   
   shield.removeVarShield("t");
   // 移除遮蔽 t 變數
   shield.removeVarShield("fun");
   // 移除遮蔽 fun 變數
   
   trace("getT() : " + getT());
   // fun(1,2,3);
   // getT() : 1000
  }
  
  public function init():*{
   shield = new ScopeShield();
   shield.addVarShield("t", "t shield");
   // 加入遮蔽 t 變數
   shield.addVarShield("fun",
     function(... rest){trace("fun shield(" + rest + ");")});
   // 加入遮蔽 fun 變數
  }
  
  public function fun(... rest):*{
   trace("fun(" + rest + ");");
  }
  
  public function getT():*{
   with(shield) {
    try {
     fun(1, 2, 3);
    } catch (e:Error) {
     trace(e);
    } finally {
     return t;
    }
   }
  }
  
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

相關連結:
AS3 利用 with, Proxy 選擇性替換 Scope Variables
ActionScript "with" Block Scope 遮蔽效應

Read more...

2007年7月1日星期日

Flash CS3 完整線上 HTML 文件下載   [+/-]

Ticore's Blog

Flash 9 Live Docs 是 Flasher 必備的線上文件
可是線上瀏覽速度實在有點慢
尤其是第一次進入時,它會載入大量 JavaScript
Flash CS3 內建的 Help 瀏覽起來有點彆腳,不比瀏覽器好用

於是我把整個 HTML 線上文件都抓下來了
檔案有點大,壓縮前約 90 mb,壓縮後約 25 mb
離線版下載位置:
http://rapidshare.com/files/40367779/Flash_9_LiveDocs.rar.html
http://rapidshare.com/files/43818764/Flash_9_LiveDocs.rar.html

Read more...