2007年12月31日 星期一

Firefox IFrame Print Preview Bug   [+/-]

Ticore's Blog

昨天在測試 Print CSS 時
偶然發現 Firefox 幾乎每次預覽列印之後
使用滑鼠或是鍵盤選擇文字反白功能失效
乍看之下,好像無法選擇文字似的
必須要重新整理網頁才恢復正常

後來反覆測試,才發現只要是網頁內有用到 IFrame
Firefox 就會出現預覽列印 Bug

Firefox IFrame 預覽列印 Bug 範例程式:

<html>
<head>
<meta content='text/html; charset=UTF-8' http-equiv='Content-Type'/>
<title>Firefox IFrame Print Preview Bug</title>
</head>
<body>
<iframe src="" id="myFrame" height="30px" width="100px" frameborder="1" ></iframe>
<br/>
↑ iframe
<p>Firefox IFrame Print Preview Bug</p>
<ol>
<li>Preview print in Firefox.</li>
<li>Cancel print, try to select text in this page.</li>
</ol>
</body>
</html>

Firefox 又沒有 onbeforeprint 等事件可以用
沒想到什麼好辦法,只能像駝鳥一樣把 IFrame 藏起來
前提當然是 IFrame 內容不需要印出來的情況下

Firefox 預覽列印自動隱藏 IFrame:

<html>
<head>
<meta content='text/html; charset=UTF-8' http-equiv='Content-Type'/>
<title>Firefox IFrame Print Preview Bug</title>
<script type="text/javascript">
<!--
function onBlur(event) {
 document.getElementById("myFrame").style.display = "none";
}

function onFocus(event) {
 document.getElementById("myFrame").style.display = "block";
}

window.addEventListener("blur", onBlur, true);
window.addEventListener("focus", onFocus, true);
//-->
</script>
</head>
<body>
<iframe src="" id="myFrame" height="30px" width="100px" frameborder="1" ></iframe>
<br/>
↑ iframe
<p>Firefox IFrame Print Preview Bug</p>
<ol>
<li>Preview print in Firefox.</li>
<li>Cancel print, try to select text in this page.</li>
</ol>
</body>
</html>

以上的 Bug 至少會在 Firefox 2.0.0.11 Windows zh_TW 版本出現

Read more...

2007年12月30日 星期日

Blog 加入列印用 CSS   [+/-]

Ticore's Blog

花了點時間,撰寫列印用的 CSS 樣式表
讓 Blog 文章列印起來比較美觀一些
以下是列印出來的效果縮圖

Read more...

2007年12月28日 星期五

Flex Embed SWF 與 Embed Symbol 的差異   [+/-]

Ticore's Blog

有人提出 Flex 嵌入的 SWF 無法被 BitmapData.draw 的問題
所以來測試看看
初步測試之後發現,只要在初始化之後稍等一下
就可以正常使用了

這是很典型初始化時間差的問題
於是進一步加入編譯參數 -keep-generated-actionscript=true 測試
觀察 Flex 產生的中間 ActionScript 程式碼

Flex Embed 範例 Main.mxml:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
 <mx:Script>
  <![CDATA[
  
   [Embed(source="../assets/assets.swf")]
   public var swf:Class;
  
   [Embed(source="../assets/assets.swf", symbol="MC")]
   public var mc:Class;
   
  ]]>
 </mx:Script>
</mx:Application>

將上述的範例加入 -keep-generated-actionscript=true 參數編譯之後
可以在產生的 ActionScript 檔案中找到三個與 Embed 動作相關的 AS Class
Main_mc.as、Main_swf.as、Main_swf_dataClass.as

Main_mc.as:

package {
 import mx.core.SpriteAsset;
 
 [ExcludeClass]
 [Embed(_resolvedSource="D:/Workspaces/WorkspaceFlex30/Flex3Test06/assets/assets.swf",
  _column="5", symbol="MC", source="../assets/assets.swf", _line="108", _pathsep="true",
  _file="D:/Workspaces/WorkspaceFlex30/Flex3Test06/src/generated/Main-generated.as")]

 public class Main_mc extends mx.core.SpriteAsset {
     public function Main_mc() { 
      super();
     }
 }
}

Main_swf.as:

package {
 import mx.core.MovieClipLoaderAsset;
 import flash.utils.ByteArray;
 
 public class Main_swf extends MovieClipLoaderAsset {
  public function Main_swf() {
   super();
   initialWidth=6000/20;
   initialHeight=4000/20;
  }
  private static var bytes:ByteArray = null;
 
  override public function get movieClipData():ByteArray {
   if (bytes == null) {
    bytes = ByteArray( new dataClass() );
   }
   return bytes;
  }
  [Embed(_resolvedSource='D:/Workspaces/WorkspaceFlex30/Flex3Test06/assets/assets.swf',
   mimeType='application/octet-stream')]
  public var dataClass:Class;
 }
}

Main_swf_dataClass.as:

package {
 import mx.core.ByteArrayAsset;
 
 [ExcludeClass]
 [Embed(_resolvedSource="D:/Workspaces/WorkspaceFlex30/Flex3Test06/assets/assets.swf",
  _column="3", exportSymbol="Main_swf_dataClass", _line="25", _file="Main_swf.as",
  mimeType="application/octet-stream")]
 
 public class Main_swf_dataClass extends mx.core.ByteArrayAsset {
     public function Main_swf_dataClass() { 
      super(); 
     }
 }
}

由產生的程式碼來看,直接 Embed Symbol 並無特別之處
可是 Embed SWF 檔案,就不太一樣了
Flex 編譯器會自動將整個 SWF 檔案以 Binary 方式嵌入
執行期使用的時候,最終也是透過 Loader.loadBytes 方式還原
這樣的話,一定會有時間差
無法在剛 new 完之後立刻取用

除了上述的問題以外
透過 Loader.loadBytes 產生的實體
還有一些安全性的限制

此外,嵌入整個 SWF 也會增加無謂的檔案容量
所以最好還是不要將整個 SWF 嵌入比較好

最後補充一點,嵌入整個 SWF 會保留 ActionScript
而嵌入 Symbol 的 ActionScript 不會保留

Read more...

ActionScript 3 Sampler 相關文件公佈   [+/-]

Ticore's Blog

隨著 Flex 3 beta 3 釋出的 Adobe® Flex™ 3 Language Reference
加入了 flash.sampler package
這裡面都是一些用來觀察 AVM 記憶體物件使用情況的公用函式與類別
不過只能用在 Flash Player debugger update 3 版本上

Package flash.sampler

Functions
clearSamples()
getGetterInvocationCount()
getInvocationCount()
getMemberNames()
getSampleCount()
getSamples()
getSetterInvocationCount()
getSize()
isGetterSetter()
pauseSampling()
startSampling()
stopSampling()
Classes
DeleteObjectSample
NewObjectSample
Sample
StackFrame

2008/05/01
正式文件位置已經改到 flash.sampler package

相關連結:
AS3 - 利用 flash.sampler.getSize 觀察物件大小

Read more...

2007年12月27日 星期四

Flex 2, 3b3 FocusColor Bug   [+/-]

Ticore's Blog

今天嘗試設定 Flex 組件的 Focus 外框顏色時,遇到了困難
無論怎樣設定,focusColor 這屬性好像完全沒有作用似的
只有 themeColor 屬性可以改變 Focus 外框顏色
可是 themeColor 影響的範圍太廣,根本不能用

以下是 focusColor 無效的設定範例:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application
 xmlns:mx="http://www.adobe.com/2006/mxml"
 layout="horizontal" verticalAlign="middle">
 <mx:Style>
  
  global {
   focusColor: #FFFFFF;
  }
  
  Button {
   focusColor: #FFFFFF;
  }
  
 </mx:Style>
 <mx:Button id="btn1" label="Button 01" />
 <mx:Button id="btn2" label="Button 02" />
</mx:Application>

實際測試就會發現,無論是在 Flex 2 or 3b3
focusColor 都沒有效果

還是得要下去看 Flex Source Code 除錯
Flex 內的 Focus Skin 預設是使用 HaloFocusRect Class
而其中 updateDisplayList 方法是主要負責繪圖的
由原始碼可以看出,HaloFocusRect 是先取用 focusColor
假如 focusColor 不存在,才會使用 themeColor
這裡是很正常的行為


override protected function updateDisplayList(w:Number, h:Number):void
 {  
  super.updateDisplayList(w, h);

  var focusBlendMode:String = getStyle("focusBlendMode");
  var focusAlpha:Number = getStyle("focusAlpha");
  var focusColor:Number = getStyle("focusColor");
  var cornerRadius:Number = getStyle("cornerRadius");
  var focusThickness:Number = getStyle("focusThickness");
  var focusRoundedCorners:String = getStyle("focusRoundedCorners");
  var themeColor:Number = getStyle("themeColor");
  
  var rectColor:Number = focusColor;
  if (isNaN(rectColor))
   rectColor = themeColor;
   
  var g:Graphics = graphics;
  g.clear();
  
  blendMode = focusBlendMode;
......

於是再往下追蹤,發現 UIComponent 會重設 focusSkin 的 focusColor

    /**
     *  Adjust the focus rectangle.
     *
     *  @param The component whose focus rectangle to modify. 
     *  If omitted, the default value is this UIComponent object.
     */
    protected function adjustFocusRect(obj:DisplayObject = null):void
    {
        if (!obj)
            obj = this;
        
        // Something inside the lisder has a width and height of NaN
        if (isNaN(obj.width) || isNaN(obj.height))
            return;

        var fm:IFocusManager = focusManager;
        if (!fm)
            return; // we've been unparented so ignore

        var focusObj:IFlexDisplayObject = IFlexDisplayObject(getFocusObject());
        if (focusObj)
        {
            var rectCol:Number;
            if (errorString && errorString != "")
                rectCol = getStyle("errorColor");
            else
                rectCol = getStyle("themeColor");

            var thickness:Number = getStyle("focusThickness");

            if (focusObj is IStyleClient)
            {
                IStyleClient(focusObj).setStyle("focusColor", rectCol);
            }
......

從原始碼看來,絲毫沒有檢查 focusColor 就直接用 themeColor 硬幹下去了
真是無言......

解決方式,自行繼承組件,覆寫 adjustFocusRect 方法:

package {
 import flash.display.*;
 
 import mx.controls.Button;
 import mx.core.*;
 import mx.styles.*;

 public class MyButton extends Button {
  
  public function MyButton() {
   super();
  }
  
  override protected function adjustFocusRect(obj:DisplayObject = null):void{
   super.adjustFocusRect(obj);
   var focusObj:IFlexDisplayObject = IFlexDisplayObject(mx_internal::getFocusObject());
   if (focusObj is IStyleClient) {
    var focusColor:Number = this.getStyle("focusColor");
    if (!isNaN(focusColor)) {
     IStyleClient(focusObj).setStyle("focusColor", focusColor);
    }
   }
  }
  
 }
}

可是假如用到大量組件,這樣一個一個覆寫也不是辦法
所以另一個方式就是覆寫 HaloFocusRect,硬在 updateDisplayList 之前把顏色覆蓋下去

MyHaloFocusRect.as

package {
 import mx.skins.halo.HaloFocusRect;
 
 public class MyHaloFocusRect extends HaloFocusRect {
  public function MyHaloFocusRect() {
   super();
  }
  override protected function updateDisplayList(w:Number, h:Number):void{
   this.setStyle("focusColor", 0xFFFFFF);
   super.updateDisplayList(w, h);
  }
 }
}

Main.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:Application
 xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:comp="*"
 layout="horizontal" verticalAlign="middle">
 <mx:Style>
  global {
   focusSkin: ClassReference("MyHaloFocusRect");
  }
 </mx:Style>
 <mx:Button id="btn1" label="Button 01" />
 <mx:Button id="btn2" label="Button 02" />
</mx:Application>
Read more...

2007年12月23日 星期日

Blogger "_WidgetManager undefined" 問題   [+/-]

Ticore's Blog

最近在使用 Google Blogger 的時候
偶爾會遇到 JavaScript 錯誤訊息

"_WidgetManager" is not defined
_WidgetManager 未被定義

開 Firebug 才發現,原來是以下的 JavaScript 根本找不到
http://www.blogger.com/widgets/1513184922-widgets.js

絕大多數瀏覽情況下 Blogger 都會使用以下網址作為 Widget Manager 程式來源
http://www.blogger.com/widgets/3950888898-widgets.js

可是就是有少數情況 Blogger 使用這個怪異網址
http://www.blogger.com/widgets/1513184922-widgets.js
這個網址根本沒有資料~~
結果就造成 JavaScript 錯誤

想要重現這個 Bug 可能要花點時間大量測試
我發現一直逐月瀏覽文章似乎比較容易出現
想要測試的話,請換別人的 Blog
因為我已經加上修補程式

改善方式,自行加入以下 JavaScript 偵測:

<script type='text/javascript'>
if (typeof(_WidgetManager) == "undefined") {
 var headID = document.getElementsByTagName("head")[0];
 var scriptNode = document.createElement('script');
 scriptNode.type = 'text/javascript';
 scriptNode.src = 'http://www.blogger.com/widgets/3950888898-widgets.js';
 headID.appendChild(scriptNode);
}
</script>
Read more...

2007年12月21日 星期五

Flash Player ActiveX 9.0.115.0 Upgrade Bug   [+/-]

Ticore's Blog

又遇到 Flash Player ActiveX 與 IE 的 Bug 了
這次 Bug 與剛推出的 Flash Player ActiveX 9.0.115.0 升級有關

基本上,Flash Player 9 ActiveX 離線安裝程式有分兩種版本
一種是 Flash CS3 安裝目錄下的 Players 資料夾
無論是 Release 或是 Debug 版本,檔案大小約為 4.xx MB

另一種安裝程式則是在 Flex Builder 安裝目錄下的 Players 資料夾
或者是到 Adobe 網站下載 Flash Player ActiveX 9
這兩個來源的安裝程式大概只有 RD 會用到,檔案大小只有 1.xx MB

只要用戶電腦從舊版的 Flash Player ActiveX 8、9 (4.xx MB)
直接安裝升級到 1.59 MB 的 Flash Player ActiveX 9.0.115.0
遇到使用版本偵測功能的 Flash 網站
幾乎都無法正常看到 Flash 內容
像是 SWFObjectSWFFixUFO - Unobtrusive Flash Objects

OS:
Windows XP Pro SP1、SP2 CHT
Windows Vista

Flash Player ActiveX 9.0.115.0 Upgrade Bug 重現步驟:

  1. 先下載 Flash Player Uninstaller, 加上 /clean 參數執行之
    確保完整移除 Flash Player 相關程式與註冊碼

  2. 下載並安裝 Flash Player 8 或是 Flash Player 9.0.115.0 之前任一版本 (4.xx MB)

  3. 下載並安裝 Flash Player ActiveX 9.0.115.0 (1.59 MB)

  4. 建立一 HTML 網頁檔案,並且用 IE 執行之:
    <!-- saved from url=(0025)http://ticore.blogspot.com/ -->
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
    <script type="text/javascript">
    try{
     var axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");
    } catch (e) {
     var str = "ShockwaveFlash.ShockwaveFlash.7\n" + e.name + "\n"
      + e.description + "\n" + e.number;
     alert(str);
    }
    
    try{
     var axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");
    } catch (e) {
     var str = "ShockwaveFlash.ShockwaveFlash.6\n" + e.name + "\n"
      + e.description + "\n" + e.number;
     alert(str);
    }
    
    try{
     var axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
    } catch (e) {
     var str = "ShockwaveFlash.ShockwaveFlash\n" + e.name + "\n"
      + e.description + "\n" + e.number;
     alert(str);
    }
    
    if (axo != null) {
     alert(axo.GetVariable("$version"));
    }
    </script>
    </head>
    <body></body>
    </html>
    

    就會出現以下錯誤訊息:

    ShockwaveFlash.ShockwaveFlash.7
    Error
    Automation 伺服器程式無法產生物件
    -2146827859
    

上述錯誤訊息意味著
在 IE 上無法利用 JavaScript 動態產生 Flash Player ActiveX 實體
很多 Flash Player 版本偵測工具,包含
SWFObjectSWFFixUFO - Unobtrusive Flash Objects、Adobe AC_RunActiveContent.js (AC_RunActiveContent 內的版本偵測預設沒用到而已)
都是利用這方式偵測 Flash Player ActiveX 版本
一旦網站使用到版本偵測
碰巧瀏覽者又是從 Flash Player 8、9 直接升級到 9.0.115.0
就會看不到 Flash 內容了

解決方式:

  • 到 Adobe 網站重新安裝一次 Flash Player 9
  • 下載 Flash Player 9 ActiveX 強迫再安裝一次就會正常

不過當然最好的習慣是每次升級之前都先用
Flash Player Uninstaller 加上 /clean 參數執行
完整清除 Flash Player 與相關註冊碼之後再安裝新版本

相關連結:
解決 IE 無法安裝 Flash Player ActiveX Bug

Read more...

2007年12月19日 星期三

Flex 3 DataGrid ToolTip Bug   [+/-]

Ticore's Blog

又遇到 Flex 奇怪的問題
而且還是我公司內的 QA Team 發現的

先建立含有數個 Column 的 DataGrid
並設定 Column DataTip
預先將滑鼠滑到一個 DataGrid 左上角
不包含 Column Header 的 100px 矩形區域內 當 DataGrid 內資料發生變動時
就會出現奇怪的 ToolTip

Flex DataGrid 怪異 ToolTip 示範:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
 layout="vertical" verticalAlign="middle" initialize="onInit();">
 <mx:Script>
  <![CDATA[
   import flash.utils.*;
   import mx.collections.*;
   import mx.core.*;
   
   [Bindable]
   public var dataAry:ArrayCollection = new ArrayCollection();
   
   public function onInit():void{
    dataAry.addItem({field1: "field1", field2: getTimer()});
    setInterval(updateData, 500);
   }
   
   public function updateData():void{
    dataAry.addItem({field1: "field1", field2: getTimer()});
    dataAry.removeItemAt(0);
   }
  ]]>
 </mx:Script>
 <mx:Canvas width="100%" height="100%">
  <mx:DataGrid id="dataGrid" width="100%" height="100%"
   dataProvider="{dataAry}">
   <mx:columnStretch>
    <![CDATA[
     tooTipArea.width = col2.width;
    ]]>
   </mx:columnStretch>
   <mx:columns>
    <mx:DataGridColumn id="col1" dataField="field1" />
    <mx:DataGridColumn id="col2" width="200" dataField="field2" showDataTips="true" />
   </mx:columns>
  </mx:DataGrid>
  <mx:Canvas id="tooTipArea" backgroundColor="0" backgroundAlpha="0.1"
   top="{dataGrid.headerHeight}" width="200" height="100"
   borderColor="0" borderStyle="solid" borderThickness="1"/>
 </mx:Canvas>
</mx:Application>

執行結果:

我刻意在 DataGrid 左上角畫出一塊黑邊半透明的矩形
用意是清楚的標明會出現怪異 ToolTip 的區域
而這個矩形的高度剛好是 100px
寬度則是隨著 field2 欄位寬度而變

這個 Bug 幾乎發生在 Flex 3 所有的版本 beta, 3.1, 3.2, 3.3
在 Flex 2.01 則是正常的

由這個矩形位置來看
推測很有可能是 DataGrid ItemRenderer 物件剛建立好的位置
還來不及放到正確的位置上
就收到了滑鼠的事件
導致出現 ToolTip 之後,ItemRenderer 才被放到正確的位置上
殘留下來的 ToolTip 就顯得很怪異

以下是個人的修正方式:

自行繼承 DataGridItemRenderer 並在建構式先將尺寸設為 0.01
在後續的 invalidateSize 呼叫自然會被調整為正確的尺寸

package {
 import mx.controls.dataGridClasses.*;

 public class MyDataGridItemRenderer extends DataGridItemRenderer {
  public function MyDataGridItemRenderer() {
   super();
   this.setActualSize(0.01, 0.01);
  }
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

套用到 DataGrid 上即可:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
 layout="vertical" verticalAlign="middle" initialize="onInit();">
 <mx:Script>
  <![CDATA[
   import flash.utils.*;
   import mx.collections.*;
   import mx.core.*;
   
   [Bindable]
   public var dataAry:ArrayCollection = new ArrayCollection();
   
   public function onInit():void{
    dataAry.addItem({field1: "field1", field2: getTimer()});
    setInterval(updateData, 500);
   }
   
   public function updateData():void{
    dataAry.addItem({field1: "field1", field2: getTimer()});
    dataAry.removeItemAt(0);
   }
  ]]>
 </mx:Script>
 <mx:Canvas width="100%" height="100%">
  <mx:DataGrid id="dataGrid" width="100%" height="100%"
   itemRenderer="{new ClassFactory(MyDataGridItemRenderer)}"
   dataProvider="{dataAry}">
   <mx:columnStretch>
    <![CDATA[
     tooTipArea.width = col2.width;
    ]]>
   </mx:columnStretch>
   <mx:columns>
    <mx:DataGridColumn id="col1" dataField="field1" />
    <mx:DataGridColumn id="col2" width="200" dataField="field2" showDataTips="true" />
   </mx:columns>
  </mx:DataGrid>
  <mx:Canvas id="tooTipArea" backgroundColor="0" backgroundAlpha="0.1"
   top="{dataGrid.headerHeight}" width="200" height="100"
   borderColor="0" borderStyle="solid" borderThickness="1"/>
 </mx:Canvas>
</mx:Application>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->

或許會覺得很奇怪,為什麼 Flex 2 就不會出現這問題呢?
後來又仔細測試
才發現在 Flex 2 內,DataGridItemRenderer 建立完成到擺放正確位置
時間差非常小,幾乎是一瞬間就完成
而 Flex 3 的 DataGridItemRenderer 建立完成後,還會連續被呼叫好幾次 validateNow();
到最後調整完成,已經隔了幾毫秒
也就是這時間差,讓滑鼠事件有機可乘

Read more...

2007年12月15日 星期六

怪異的 Flex HTTP 請求   [+/-]

Ticore's Blog

之前在開發 Flex 時,發現 Application 會發出怪異的 HTTP 請求
如下圖所示:

程式明明已經將外部圖檔嵌入
Flex 居然將整個 Embed 字串當作圖檔網址
嘗試從外部讀取

http://localhost:8080/flex/@Embed('application_background.gif')

怪異的 Flex HTTP 請求 Demo Code:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
 backgroundImage="@Embed('application_background.gif')"
 preinitialize="onPreInit()">
 <mx:Script>
    <![CDATA[
   private function onPreInit():void{
    var count:Number = 0;
    for (var i:Number = 0 ; i < 10000000 ; ++i) {
     count += i;
    }
    trace(count);
   }
    ]]>
 </mx:Script>
</mx:Application>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->

這情況特別容易發生於 Application preinitialize 事件中需要較大量耗時運算

解決方式,改用 CSS 設定 Application.backgroundImage 就可以了

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
 preinitialize="onPreInit()">
 <mx:Style>
  Application {
   backgroundImage: Embed('application_background.gif');
  }
 </mx:Style>
 <mx:Script>
    <![CDATA[
   private function onPreInit():void{
    var count:Number = 0;
    for (var i:Number = 0 ; i < 10000000 ; ++i) {
     count += i;
    }
    trace(count);
   }
    ]]>
 </mx:Script>
</mx:Application>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->
Read more...

2007年12月13日 星期四

AS 技巧 - 快速遮蔽所有子物件選單   [+/-]

Ticore's Blog

Flash Player 7 開始支援自訂 ContextMenu 功能
每個子物件 MovieClip、Sprite、Button、TextField 等均可以設定
假如在數十個分散不同時間軸之下的子物件使用到 ContextMenu
想要一次覆蓋全部的 ContextMenu,將會變的非常麻煩
原因是 ContextMenu 功能缺少一個由上而下的管理方式

不過我們可以用 hitArea 來作到由上而下遮蔽所有子物件選單
看到這一定會覺得很困惑,為什麼可以用 hitArea 來遮蔽選單呢?
hitArea 原本的功能是設定滑鼠感應區域到其它 Sprite 上
假如 hitArea 所指定的 Sprite 沒有放在 stage 之下或是 invisible
利用這一點,就可以做出不具有滑鼠感應區域的 Sprite
但是原本設定的 ContextMenu 依然有效

至於為什麼不用 mouseEnabled 來作
很簡單,因為設定 mouseEnabled = false; 會一併把 ContextMenu disable

利用以上原理,只要在最上層,建立一個夠大的透明 Sprite
指定好 ContextMenu,將 hitArea 指定到不可視的 Sprite
就可以用來遮蔽所有子物件的 ContextMenu 了

AS3 快速遮蔽所有子物件選單範例程式:

// Ticore's Blog - http://ticore.blogspot.com/
package {
 import flash.display.*;
 import flash.text.*;
 import flash.events.*;
 import flash.utils.*;
 import flash.ui.*;
 
 import fl.controls.Button;
 import fl.controls.CheckBox;
 
 public class Main extends MovieClip {
  
  public var menuShield:Sprite = new Sprite();
  
  public function Main():void{
   initChildren();
   initMenuShield();
  }
  
  public function initChildren():void{
   var btn1:Button = new Button();
   btn1.y = 50;
   btn1.x = 100;
   btn1.label = "Button 1";
   this.addChild(btn1);
   btn1.contextMenu = new ContextMenu();
   btn1.contextMenu.customItems = [new ContextMenuItem("Button 1")];
   
   var btn2:Button = new Button();
   btn2.y = 80;
   btn2.x = 100;
   btn2.label = "Button 2";
   this.addChild(btn2);
   btn2.contextMenu = new ContextMenu();
   btn2.contextMenu.customItems = [new ContextMenuItem("Button 2")];
   
   var chk:CheckBox = new CheckBox();
   chk.y = 120;
   chk.x = 100;
   chk.label = "Hide Menu";
   this.addChild(chk);
   
   chk.addEventListener(Event.CHANGE, onChkChange);
  }
  
  public function initMenuShield():void{
   menuShield.visible = false;
   var g:Graphics = menuShield.graphics;
   
   g.beginFill(0, 0);
   g.drawRect(0, 0, 300, 200);
   g.endFill();
   
   menuShield.hitArea = new Sprite();
   menuShield.contextMenu = new ContextMenu();
   menuShield.contextMenu.hideBuiltInItems();
   this.addChild(menuShield);
  }
  
  public function onChkChange(evtObj:Event):void{
   var chk:CheckBox = evtObj.target as CheckBox;
   menuShield.visible = chk.selected;
  }
  
 }
}

實際範例:

hitArea, ContextMenu 相關行為在 ActionScript 2.0 也是一樣的
AS2 MovieClip 預設不會攔截滑鼠事件,卻會保留 ContextMenu
所以作起來更簡單

Read more...

2007年12月11日 星期二

Linux Flash Player getTimer Bug   [+/-]

Ticore's Blog

這次又是 Linux Flash Player 的 Bug
最新版本 9.0.115.0 也會發生
在 Flash Player 執行中,修改 Linux Date 設定
假如 Date 往後修改
Flash Player getTimer() 就會得到錯誤的 ms 數值
假如 Date 往前修改
Flash Player 就會卡在那邊,動彈不得
直到時間改回來,或是重新 refresh

Linux Flash Player getTimer Bug Demo Code:

package {
 import flash.display.*;
 import flash.text.*;
 import flash.events.*;
 import flash.utils.*;
 
 public class Main extends MovieClip {
  
  var txt:TextField = new TextField();
  var timer:Timer = new Timer(1000);
  
  public function Main ():void{
   
   txt.x = 25;
   txt.y = 25;
   txt.width = 250;
   txt.height = 150;
   txt.border = true;
   this.addChild(txt);
   
   timer.addEventListener(TimerEvent.TIMER, onTimer);
   timer.start();
  }
  
  public function onTimer (evtObj:TimerEvent):void{
   txt.appendText(getTimer() + "\n");
   txt.scrollV = txt.maxScrollV;
  }
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

Flash 版 Bug 線上測試網址
Javascript 版 Bug 線上測試網址

不光是 Flash Player
連 Firefox、Qt Demo Browser、Adobe AIR Linux 版也會這樣
感覺上實在像是 Linux 本身的 Bug

測試環境 Ubuntu 8.10

該 Bug 至少會在以下版本 Linux Flash Player 發生
Flash Player 9.0.31.0
Flash Player 9.0.48.0
Flash Player 9.0.115.0
Flash Player 10.0.22.87

Read more...

2007年12月10日 星期一

AS3 技巧 - 減緩鍵盤連打事件的速度   [+/-]

Ticore's Blog

在 Flash Player 內,使用者按下某一鍵盤按鍵不放
每隔 30~40 ms 就會連續送出鍵盤事件

以 Flex List 為例

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
 layout="horizontal" verticalAlign="middle" preinitialize="onPreinit();">
 <mx:Script>
  <![CDATA[
   
   [Bindable]
   public var dataAry:Array = [];
   
   public function onPreinit():void{
    for (var i:Number = 0 ; i < 100 ; ++i) {
     dataAry.push(i);
    }
   }
   
  ]]>
 </mx:Script>
 <mx:List width="100" height="100%" dataProvider="{dataAry}"/>
</mx:Application>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->

只要使用者在 List 上按下 Keyboard Down
按住不放持續一秒鐘,List 會被向下捲動 25~33 次左右

有時候,並不需要這麼頻繁的鍵盤事件
就可以利用 ActionScript 3.0 的事件功能加以攔截

以下面的程式為例,在 Applcation Capture Phase 攔截 KeyDown 事件
並紀錄最後一次 KeyDown 時間
假如下一個 KeyDown 時間太接近
便將該事件停止傳播
連續鍵盤事件大約會被減慢一半左右

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
 layout="horizontal" verticalAlign="middle" preinitialize="onPreinit();">
 <mx:Script>
  <![CDATA[
   
   public var minKeyDownInterval:Number = 100;
   public var prevKeyDownTime:Number = 0;
   
   
   [Bindable]
   public var dataAry:Array = [];
   
   public function onPreinit():void{
    this.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown, true);
    for (var i:Number = 0 ; i < 100 ; ++i) {
     dataAry.push(i);
    }
   }
   
   public function onKeyDown(evtObj:KeyboardEvent):void {
    var currKeyDownTime:Number = getTimer();
    if (currKeyDownTime - prevKeyDownTime > minKeyDownInterval) {
     prevKeyDownTime = currKeyDownTime;
     return;
    } else {
     evtObj.stopImmediatePropagation();
    }
   }
   
  ]]>
 </mx:Script>
 <mx:List width="100" height="100%" dataProvider="{dataAry}"/>
</mx:Application>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->
Read more...

2007年12月8日 星期六

Flash Player TextField Render Bug   [+/-]

Ticore's Blog

繼之前的 Flex TextField Render Bug
反覆測試與簡化之後
終於釐清 Bug 發生條件,與 Flex 沒有直接關係
而是 Flash Player Render TextField 的 Bug

先建立以下的 DisplayObjectContainer 結構

sprite1:DisplayObjectContainer (with Filters)
 └sprite2:DisplayObjectContainer (blendMode="layer")

此時在 sprite2 加入一個 TextField
間隔至少 100 ms 之後,將 sprite1 的 filter 移除
就會造成 TextField 顯示異常

AS3 TextField Render Bug Demo Code:

package {
 import flash.display.*;
 import flash.filters.*;
 import flash.text.*;
 import flash.utils.*;

 public dynamic class Main extends MovieClip {
  
  public var sp1:Sprite = new Sprite();
  public var sp2:Sprite = new Sprite();
  public var txt:TextField = new TextField();
  
  public function Main():void {
   sp1.x = 100;
   sp1.y = 80;
   
   this.addChild(sp1);
   sp1.addChild(sp2);
   sp1.filters = [new BlurFilter()];
   sp2.blendMode = BlendMode.LAYER;
   
   txt.text = "TextField";
   txt.multiline = true;
   txt.type = TextFieldType.INPUT;
   txt.border = true;
   txt.height = 22;
   
   sp2.addChild(txt);
   setTimeout(removeFilters, 600);
  }
  
  public function removeFilters():void{
   sp1.filters = [];
  }
  
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

AS2 TextField Render Bug Demo Code:

import flash.filters.*;

var root:MovieClip = this;
var mc1:MovieClip = root.createEmptyMovieClip("mc1", 0);
var mc2:MovieClip = mc1.createEmptyMovieClip("mc2", 0);

mc1.filters = [new BlurFilter()];
mc2.blendMode = "layer";
var txt:TextField = mc2.createTextField("txt", 0, 100, 80, 100, 22);
txt.text = "TextField";
txt.border = true;

setTimeout(function():Void{mc1.filters = [];}, 600);

以下是幾種不同的 Bug 狀況

Flash Player 9.0.47.0

Flash Player 9.0.115.0

這個 Bug 會在以下版本的 Windows Flash Player 發生
Flash Player 8.0.22.0
Flash Player 8.0.33.0
Flash Player 8.0.34.0
Flash Player 8.0.35.0
Flash Player 9.0.15.0
Flash Player 9.0.16.0
Flash Player 9.0.28.0
Flash Player 9.0.45.0
Flash Player 9.0.47.0
Flash Player 9.0.64.0
Flash Player 9.0.115.0
Flash Player 9.0.124.0

只是在最新版本 9.0.115.0, 9.0.124.0 上表現比較輕微而已

相關連結:
ActionScript BitmapData.draw TextField Bug

Read more...

2007年12月7日 星期五

Flex TextField Render Bug   [+/-]

Ticore's Blog

最近開發 Flex 專案的時候,又遇到奇怪的 Bug
當 Container 指定 BlendMode 為 "layer" 模式時
呼叫 Modal Alert,會導致 Container 內的 TextField 顯示不正常

Flex TextField Render Bug Demo Code:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="horizontal">
 <mx:Style>
  Alert {
   modalTransparencyDuration: 500;
  }
 </mx:Style>
 <mx:Script>
  <![CDATA[
   
   import flash.display.BlendMode;
   import mx.controls.Alert;
   
   public function onButtonClick(evtObj:Event):void{
    var alert:Alert = Alert.show("Alert Message", "Alert", Alert.OK);
   }
   
  ]]>
 </mx:Script>
 <mx:HBox id="box" blendMode="{BlendMode.LAYER}">
  <mx:Button id="btn" label="Alert" click="onButtonClick(event);" />
 </mx:HBox>
</mx:Application>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->

預期正常顯示畫面:

實際顯示畫面:

暫時性解決方式,加上 cacheAsBitmap=true 就好了

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="horizontal">
 <mx:Style>
  Alert {
   modalTransparencyDuration: 500;
  }
 </mx:Style>
 <mx:Script>
  <![CDATA[
   
   import flash.display.BlendMode;
   import mx.controls.Alert;
   
   public function onButtonClick(evtObj:Event):void{
    var alert:Alert = Alert.show("Alert Message", "Alert", Alert.OK);
   }
   
  ]]>
 </mx:Script>
 <mx:HBox id="box" cacheAsBitmap="true" blendMode="{BlendMode.LAYER}">
  <mx:Button id="btn" label="Alert" click="onButtonClick(event);" />
 </mx:HBox>
</mx:Application>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->

這 Bug 在 Flex 2, 3b2 都會發生,看起來很可能與 Flash Player 有關
實際測試之下,連最新版本 Flash Player 9.0.115.0 也都顯示錯誤

相關連結:
Flex Label, TextField 半透明小技巧
Flash Player TextField Render Bug

PS. 只會發生在 Windows XP、Linux 上,在 Windows VISTA 上則是正常的

Read more...

2007年12月6日 星期四

AS3 覆寫 Namespace Function 方式   [+/-]

Ticore's Blog

最近在覆寫 Super Class Namespace Function 遇到了問題
狀況如下:

假設有一個 Package Namespace: ns_ticore

package {
 public namespace ns_ticore = "http://ticore.blogspot.com";
}

另外有一個 SuperClass 用 ns_ticore 宣告 Namespace Function

package {
 use namespace ns_ticore;
 public class SuperClass {
  ns_ticore function fun():void{
  }
 }
}

在這樣情況下,宣告 SubClass 繼承 SuperClass 覆寫 Namespace Function

package {
 public class SubClass extends SuperClass {
  override ns_ticore function fun():void{
   
  }
 }
}

編譯以上程式就會報錯

1004: Namespace was not found or is not a compile-time constant.

此時有兩種方式可以解決
第一種,只要在 SubClass 前加上 use namespace ns_ticore;

package {
 use namespace ns_ticore;
 public class SubClass extends SuperClass {
  override ns_ticore function fun():void{
   
  }
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

假如在 SubClass 無法直接引用到 ns_ticore 時
可以在 SubClass 自行另外宣告 Namespace
只要 URI 一樣就好

package {
 public class SubClass extends SuperClass {
  namespace ns_ticore2 = "http://ticore.blogspot.com";
  use namespace ns_ticore2;
  override ns_ticore2 function fun():void{
   
  }
 }
}
Read more...

2007年12月5日 星期三

Flex Alert 使用美觀小技巧   [+/-]

Ticore's Blog

一般在使用 Flex Alert 時候
偶爾會遇到 Alert 內的 Button 邊線會糊糊的
有經驗的 Flash 開發者就會知道這是由於線段沒有位於整數座標上
經過 Flash Player 抗鋸齒效果所造成

第一種 Alert 模糊情況

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
 layout="horizontal" verticalAlign="middle">
 <mx:Script>
  <![CDATA[
   import mx.controls.Alert;
   
   public function onButtonClickHandler(evtObj:Event):void{
    var alert:Alert = Alert.show("Alert Message.", "Alert");
   }
  ]]>
 </mx:Script>
 <mx:Button label="Alert" click="onButtonClickHandler(event);"/>
</mx:Application>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->

請注意 Button 左右的邊線

只要在呼叫前加上 Alert.buttonWidth = 70; 就可以改善

第二種 Alert 模糊情況

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
 layout="horizontal" verticalAlign="middle">
 <mx:Script>
  <![CDATA[
   import mx.controls.Alert;
   
   public function onButtonClickHandler(evtObj:Event):void{
    Alert.buttonWidth = 70;
    var alert:Alert = Alert.show("Alert Message..................", "Alert", 6);
   }
  ]]>
 </mx:Script>
 <mx:Button label="Alert" click="onButtonClickHandler(event);"/>
</mx:Application>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->

即使將按鈕寬度設為偶數也還是會發生

第二種情況的改善方式
除了 Alert.buttonWidth 要設為偶數之外
Alert 視窗的寬度也要是偶數

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
 layout="horizontal" verticalAlign="middle">
 <mx:Script>
  <![CDATA[
   import mx.controls.Alert;
   
   public function onButtonClickHandler(evtObj:Event):void{
    Alert.buttonWidth = 70;
    var alert:Alert = Alert.show("Alert Message..................", "Alert", 6);
    alert.width += alert.width & 1;
   }
  ]]>
 </mx:Script>
 <mx:Button label="Alert" click="onButtonClickHandler(event);"/>
</mx:Application>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->
Read more...

2007年12月4日 星期二

Flash Player 9.0.115.0 出了   [+/-]

Ticore's Blog

Adobe Flash Player 9.0.115.0 終於正式 release 了
這次更新同時包含 windows, mac, linux 版本...

主要功能是加上 H.264 支援
Introducing Flash Player 9 Update 3
有興趣的朋友可以到這裡下載所有版本
Adobe Flash Player Support Center
之後有空再來慢慢測試新功能與舊 Bug...

相關連結:
Flash 9 AS3 移除 Render Event Bug
一行 AS3 程式讓 Flash Player 9 死機 Part 3

Read more...

Flex TileList HitArea 怪異現象   [+/-]

Ticore's Blog

Flex 2、3b2 的 TileList 組件使用上有一個很怪異的問題
其實這問題很早就遇到過了,只是一直沒有特別去注意它
當 TileList 內最後一排的 Item 只剩下一個時
該 Item 的感應區域判別會出現問題

如下圖所示,最後一整排的範圍全部變成最後一個 Item 感應區域

這實在非常詭異,一度以為是 TileList 的 Bug
於是逐步搜索 Flex TileList Super Class 原始碼
最後終於在 ListBase Class 中找到相關 Code

看程式的寫法,根本像是刻意這樣做的
可是我實在無法認同這樣怪異的 UI 行為
於是利用以下方式,將這行為覆蓋掉

MyTileList Class:

package {
 
 import flash.events.*;
 import flash.display.*;
 import flash.geom.*;
 import mx.core.*;
 import mx.controls.TileList;
 import mx.controls.listClasses.*;

 public class MyTileList extends TileList {
  
  override protected function mouseEventToItemRenderer(
          event:MouseEvent):IListItemRenderer {
   return mouseEventToItemRendererOrEditor(event);
  }
  
  private function mouseEventToItemRendererOrEditor(
          event:MouseEvent):IListItemRenderer {
   var target:DisplayObject = DisplayObject(event.target);
   
   if (target == listContent) {
    var pt:Point = new Point(event.stageX, event.stageY);
    pt = listContent.globalToLocal(pt);
    
    var yy:Number = 0;
    
    var n:int = listItems.length;
    for (var i:int = 0; i < n; i++) {
     if (listItems[i].length) {
      if (pt.y < yy + rowInfo[i].height) {
       var m:int = listItems[i].length;
       /*/
       if (m == 1)
        return listItems[i][0];
       //*/
       var j:int = Math.floor(pt.x / columnWidth);
       return listItems[i][j];
      }
     }
     yy += rowInfo[i].height;
    }
   } else if (target == highlightIndicator) {
    return mx_internal::lastHighlightItemRenderer;
   }
   
   while (target && target != this) {
    if (target is IListItemRenderer && target.parent == listContent) {
     if (target.visible)
      return IListItemRenderer(target);
     break;
    }
   
    if (target is IUIComponent)
     target = IUIComponent(target).owner;
    else 
     target = target.parent;
   }
   
   return null;
  }
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

Main.mxml:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
 layout="horizontal" verticalAlign="middle">
 <mx:Script>
  <![CDATA[
   [Bindable]
   public var dataAry:Array = [1,2,3,4];
  ]]>
 </mx:Script>
 
 <comp:MyTileList xmlns:comp="*"
  dataProvider="{dataAry}" dragEnabled="true"
  width="200" height="150"
  columnWidth="50" rowHeight="50" />
 
</mx:Application>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->
Read more...

2007年12月3日 星期一

新版 Flash Tracer 2.1.2 出了   [+/-]

Ticore's Blog

好用的 Flash 除錯工具 - Flash Tracer 2.1.2 出了喔
雖然該連結文章標題是 Flash Tracer 2.1.0
可是實際上作者已經更新到 2.1.2 版了

新版的功能可以讓使用者自訂規則
利用 regular expression 將 trace 訊息格式化
變成自訂的文字樣式

Read more...

2007年12月2日 星期日

Flex 技巧 - 自訂 Slider Thumb 大小   [+/-]

Ticore's Blog

最近在使用 Flex Slider 時,需要修改 Thumb Skin
發現不管怎樣改 Skin,Thumb 都只有 12 x 12 大小
Flex API 上也沒有提供可以設定的 CSS Style 屬性
以下分享個人修改 Slider Thumb 大小的做法

方式一、待 Slider 建立完成後,取出 Thumb 加以設定

Main.mxml:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
 layout="horizontal" verticalAlign="middle">
 <mx:HSlider>
  <mx:creationComplete>
   <![CDATA[
    import mx.controls.HSlider;
    import mx.core.UIComponent;
    var slider:HSlider = event.target as HSlider;
    var thumb:UIComponent = slider.getThumbAt(0);
    thumb.width = 24;
    thumb.height = 24;
    slider.invalidateDisplayList();
   ]]>
  </mx:creationComplete>
 </mx:HSlider>
</mx:Application>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->

方式二、自訂 SliderThumb Class,覆寫 measure 方法

MySliderThumb Class:

package {
 import mx.controls.sliderClasses.*;
 
 public class MySliderThumb extends SliderThumb {
  override protected function measure():void{
   super.measure();
   measuredWidth = 24;
   measuredHeight = 24;
  }
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

Main.mxml:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
 layout="horizontal" verticalAlign="middle">
 <mx:HSlider sliderThumbClass="{MySliderThumb}" />
</mx:Application>

效果擷圖

方式二似乎比較好一些
應該可以更進一步改成從 CSS 設定會更好

Read more...

2007年12月1日 星期六

Yahoo! Widget 4.5 Flash 功能初步測試   [+/-]

Ticore's Blog

初步測試 Yahoo! Widget 新增的 Flash 功能
是以用戶電腦內安裝 Flash Player ActiveX 運行的
Y! Widget 文件上提供的 Flash API 也都與 Flash Player ActiveX Control API 很像

不過開發者可以利用 useFlashContextMenu 屬性
選擇是否要屏蔽 Flash 的右鍵選單
甚至是換成自訂的

假如有使用 hOffset, vOffset 位移 Flash 物件
useFlashContextMenu 設為 true 時
Flash Player 右鍵選單出現位置會錯亂

Y! Widget Flash 的 wmode 預設是以 transparent 模式運行
無法更改~!
這也意味著會出現中文輸入的 Bug
實際測試下,中文注音輸入都會變成英文亂碼

以下是簡易的 Y! Widget Flash 測試碼

<?xml version="1.0" encoding="UTF-8"?>
<widget minimumVersion="4.5">
 <window name="mainWindow" width="400" height="300"
  style="background-color:#808080">
  <flash name="flashView" width="300" height="200"
   hOffset="50" vOffset="50" useFlashContextMenu="false">
   <src>Flex3Test01.swf</src>
   <contextMenuItems>
    <menuItem title="Beep" onSelect="beep();"/>
    <menuItem title="Another Test"/>
   </contextMenuItems>
  </flash>
 </window>
</widget>

至於 Y! Widget JS 與 Flash 溝通方式
目前還不支援 ExternalInterface
只能以 fscommand, setVariable() 等基本方式溝通

相關連結:
Yahoo! Widgets 4.5 支援 Flash 與 HTML了

Read more...

Yahoo! Widgets 4.5 支援 Flash 與 HTML了   [+/-]

Ticore's Blog

Yahoo! Widgets 4.5 英文版開始支援 Flash 與 HTML 功能了
HTML 引擎與 Adobe AIR 一樣是採用 WebKit
其它部分等有空在來測試了~~

相關連結:
Yahoo! Widget 4.5 Flash 功能初步測試

Read more...