Archive for the ‘ActionScript’ Category

“Error #1088: The markup in the document following the root element must be well-formed.”

December 5, 2009

I was using PHP and curl as proxy to get some xml files from Basecamp for my Flex UI to consume and was successful (something like “return $response   = curl_exec($session);“. But after I refactored my little php functions into an object/class and included it in another delegation file, it suddenly stopped working. In Flex, I got the following error for the HTTPService fault event:

faultCode:Client.CouldNotDecode
faultString:’Error #1088: The markup in the document following the root element must be well-formed.’
faultDetail:’null’

In Firefox 3.5, the output XML file looked ok. But both Safari and IE gave error messages: There was an “*” in front of the <?xml ..?> header in Safari source code view; while IE gave the following error:

Invalid at the top level of the document. Error processing resource

After comparing the files before refactoring and the one after, I noticed that the refactored one was encoded in UTF-8 while the old one was in ANSI. After I converted my class file into ANSI, XML output became normal in all three browsers.

BTW, I used Notepad++. Not sure if that was an issue.

Anyhow, lessons learned: Make sure the source files are encoded in ANSI.

Any comments and thoughts are welcome!

Block statements in control flow constructs

December 2, 2009

There is no need to block (using braces to wrap) single line statements in a control flow (as-if, do-while, for/while); and you can mix blocks and non block statements together like this:

if(num > 0)
trace(num+” is positive;\n”);
else if(num <0)
{
trace(num+” is negative.”);
trace(num+” don’t be negative;\n”);
}
else if(num == 0)
trace(num+” is neutral;\n”);

This applies to all the control statements although the example here is just of if/else .

With this being said, The Elements of C# Style recommends Always us block statements in control flow constructs. Reason one is that it makes it easy to add additional statements in it; reason two is it’s easier to read than those without blocks.

Accessing UI views, properties and methods in main app in Flex

July 6, 2009

This applies to both AIR and Flex project, in Flex SDK 3.3:

// Application.application refers to the top level application.
// But be aware that it's typed to Object as opposed to Application.
// According to Flex team, it's for the purpose of fast compilation and
// being able to access properties/methods in the <Script> of their
// <Application> without having to cast it to their application's real type.
// So this means you can get:
// var stuff:SomeStuff = Application.application.getStuff();
// but you would have to access the real application each time by saying
// Application.application. Or you can do it this way:

var app:MySubclassedApplication = mx.core.Application.application as
                                  MySubclassedApplication;

// UI components with id names are automatically declared as public
var contactList: ContactList = app.contactList;

// as long as you've declared them as public in your <Script>.:)
var dou:Dug = app.dug;
var stuff:SomeStuff = app.getStuff();

Documentation. Note when you are using SWFLoader to load a module into the main application, you can reference your main application as parentApplication.

Tracking mouse movement in Flash Player

June 8, 2009

In a recent prototyping project, I attempted to simulate “shake” gestures in a desktop AIR application, i.e., using mouse cursor to simulate a hand grabbing some object on the screen…

Anyhow. I found out that Flash Player can send out the mouseMove event must faster than it can update the screen. In the case you want to keep track of the simulated gestural motion, you would want to track the mouse cursor position on the stage, instead of the display object the mouse cursor is dragging. This is because when you drag the object to the point Flash Player cannot keep up with, the redaw will then not necessarily reflect the real positional changes of it in between the frames.

Take a look here. Right click to for the code. Also note that when directly register Application.application as the currentTarget we seem to get smoother tracking than if we registered the display object, like so:

mButton.addEventListener(MouseEvent.MOUSE_MOVE, mButton_handleMouseMove);/** you got more stripped out points than if you do this:

addEventListener(MouseEvent.MOUSE_MOVE, mButton_handleMouseMove);// this is btter.*/

MVC revisit: Take two

June 7, 2009

I find that MVC is much easier to understand both at the conceptual level and at the implementation level if you think about it from the perspective of how you communicate with the Model.

  1. Control is the input to Model. Basically, the Control is responsible to take input from the user or the system and stransfer it to the changes in the Model; The View is merely there to render the changes from the Model; so it can be considered as the output from the Model. You should keep the business logic as much as possible inside the Model and leave Control/View simple and dandy.For Flex 3 (Halo) components, the way of input is realized by implimenting the “change” listener of the controls, like this:

    <mx:TextInput id="mTxt" change="mVO.txtValue = mTxt.htmlText;"/>

    In Flex 3, when you bind a model to a control, it is one-way communication, meaning the control will reflect the change whenever there is one in the model; but the control would not be able to change the model. That’s why we need to wire through the change listener to make this happen.

    The output is hooked up by setter methods in the Model. Whenever you detect some changes that are historical, you would notify your listeners.

    [Bindable]
    public function set myValue(v:int):void
    {
    _
    myValue = v;
    notifyListeners();
    }

    In ActionScript 3, we normally implement “notifyListeners” by way of dispatchEvent. Your client listens to the event and updates the View by querying the changes from the Model. You may want to have different types of events so that your listeners can respond differently. For example, you normally would invalidate properties of your component and regenerate all the renderers when the data provider has changed, besides doing other updates; and you don’t want to do this kind of heavy-lifting each time when changes occur on the “less important” members of the Model.

  2. Asynchronous data. Sometimes you may compose something like an HTTPService component into your Model so that it can request external data.The data that are requested by the Control at a lot of times are not immediately available, and normally you would not notify your listeners until they are ready (For example, parsed into an XMLList object that can be consumed by component’s dataProvider).
  3. Static members are available before non-static members of the objects. You can use static members to set some initial values of your member variables.
  4. When you smell spaghetti code in your Model, try to partition/refactor your Model into smaller Value Objects. Value objects are a good way to structure your data/make flat Model hierarchical.
  5. For larger projects, you may want to duplicate Model (or value objects) so that multiple client can access the same data. For example, in your main window of your AIR application, you initialize your model like so:

    public var chatModel:ChatModel = new ChatModel();In another console window, you want to access the same model, like so:

    private var chatModel:ChatModel = Application.application.chatModel;

Change Adobe AIR window size dynamically

May 28, 2009

This changes your AIR app (main app’s window) to 100 px by 100 px.

Application.application.width = 100;
Application.application.height = 100;

“Unexpected end of token stream when parsing XML”

April 29, 2009

When I tried to load an external xml file using an XML tag, I got something like this from Flex Builder:

“Problem parsing external XML. Unexpected end of token stream. The last token was: 360.”

The file was built in Nodepad++ and was displayed fine in Firefox as well as in Eclipse/FB. When I got the error message, I then tried to load it in IE, which also gave me an error. What I did to fix it was going back to Nodepad++ and  “Format>Encode in UTF-8“, which basically changed the encode from ANSI (the default one for Notepad++) to Unicode. I got several “special” unicode characters such as 360° in my orignial XML file.

Code snippet: clamp value into a range

April 24, 2009

var myVal:Number = Math.max(USER_MIN,  Math.min(USER_MAX, calculateMyDesiredValue());

Inspired by Ely Greenfield. (Note: “Inspired” is an elegent way of saying “copy”.)

Keyboard Keys and Key Code Values in ActionScript 3

April 21, 2009

Postfix operators: x++

March 30, 2009

Although postfix operators are unary operators, they are classified separately from the rest of the unary operators because of their higher precedence and special behavior. When a postfix operator is used as part of a larger expression, the expression’s value is returned before the postfix operator is processed. In other unary operators, such as prefix increments/decrements, the increment or decrement operation is completed before the value of the overall expression is returned.

#include <iostream>
using namespace std;

int main()
{
int max = 3;
int total = 7;

int count = 0;
cout<<”unary test for postfix:”<<endl;
for(int i = 0; i< total; i++)
{
count = count >= max? 0 : count++;
cout<<”#”<<i<<”: “<<”count is “<<count<<endl;
}
cout<<endl;

count = 0;
cout<<”unary test for prefix:”<<endl;
for(int i = 0; i< total; i++)
{
count = count >= max? 0 : ++count;
cout<<”#”<<i<<”: “<<”count is “<<count<<endl;
}
cout<<endl;

cout<<”for loop test:”<<endl;
count = 0;
for(int i = 0; i< total; i++)
{
if(count >= max)
{
count = 0;
}else
{
//both are the same.
//count++;
++count;
}
cout<<”#”<<i<<”: “<<”count is “<<count<<endl;
}
cout<<endl;
}
/**result
unary test for postfix:
#0: count is 0
#1: count is 0
#2: count is 0
#3: count is 0
#4: count is 0
#5: count is 0
#6: count is 0

unary test for prefix:
#0: count is 1
#1: count is 2
#2: count is 3
#3: count is 0
#4: count is 1
#5: count is 2
#6: count is 3

for loop test:
#0: count is 1
#1: count is 2
#2: count is 3
#3: count is 0
#4: count is 1
#5: count is 2
#6: count is 3
*/