We are migrating our Flex-3.2 application to Flex 4.1, mainly to take advantage of the new text flow/engine features. In a first step we decided to go with compiling for MX-only and in Flex-3-compatibility mode.
Thanks to some helpful resources (
http://www.adobe.com/devnet/flex/articles/flexbuilder3_to_flashbuilder4.html
Any Flex 4 migration experience?
http://www.adobe.com/devnet/flex/articles/flex3and4_differences_02.html
) I am able to compile our application.
But I find myself surprised about the amount of runtime differences ranging from the problem that I cannot cast ResultEvent.currentTarget to HTTPService ( which apparently was introduced in 3.5 ) to many layout problems to differences in event dispatching ( e.g. one of our legacy components listens to the add event which it just doesn't seem to get anymore ).
It seems there is very little documentation on this. I'd like to find a list with detailed changes so that we don't have to rely on QA to stumble across hopefully all issues.
This documents lists some, but doesn't seem exhaustive.
Does someone have a better list of documented changes?
Thanks
Stefan
PS. List of concrete examples I have found so far:
1) In Flex 4 the add event is not fired:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx" layout="absolute" minWidth="955" minHeight="600">
<fx:Script>
<![CDATA[
private function notFired():void
{
trace("ADDED");
}
private function fired():void
{
trace("COMPLETE");
}
]]>
</fx:Script>
<mx:TextArea add="notFired();" creationComplete="fired();"/>
</mx:Application>
Now do the same in Flex 3 and you'll see both events fire.
Apparently, this is a bug. Might be possible to work around this but certainly decreases my level or trust substantially.
2) Dialogs/popups show all content mirrored.
A bug as well. Easy to work around, but how could something that obvious slip?
3) Problems with injected "Ôª" chars.
See post here.
Let's see some of your doubts...
1) add never was a reliable event since flash player 9 release. It's a common bug. Try to create a movieclip out of displaylist and add a child in it that have the Event.ADDED listener. In some situations (don't know exactly what situation) it doesn't work (Adobe Fail). But, instead the "add" flex event, use the "added" or "addedToStage" once you want to detect if it's already in your applications display list.
2) Fail. Check the layout manager source-code of the framework.
3) I've never seen this. (Even in compatibility mode). Can you show an example? Did you check if the application encoding is the same you're using on your strings? Maybe the string table could be doing some confusion due to the characters encodings (or maybe your editor). Try other editors and verify the code file contents on a linux shell with SED. With a find and a sed you can fix it easily.
Related
I have been using Flex / Flash Builder for a number of years. The latest release of Flash Builder (4.7) seems to come with quite a few problems, the biggest of those being:
Does not detect component IDs in MXML. For example, you cannot Find Usages of the ID of a component. Keeping the cursor on the ID of a component does not even mark occurrences of the ID. Instead, it marks occurrences of the actual id words in the MXML.
Extremely slow.
I am seriously evaluating moving over to IntelliJ IDEA 12, especially after reading many experienced Flex devs raving about it and recommending it.
I tried it. It took me a while to get to terms with the new terminologies of the IDE (made easy by this doc and very helpful support personnel at JetBrains).
I was able to setup my (large) projects in IDEA with Adobe Flex 4.6 SDK and got it to compile fine. But I noticed many "errors" highlighted in my AS files which are all actually false alarms.
The ActionScript editor doesn't seem to recognise the objects defined in MXML. Apparently, this is a known bug in IDEA (tracked here). And this bug has existed for more than 2 years!
Quoting the JetBrains support personnel:
I must admit that highlighting of ActionScript files which do not contain classes, but instead included in mxml as <fx:Script source="some_file.as"/> is probably the only weak part of IntelliJ IDEA code highlighting. False error highlighting will go away if you embed AS code inside CDATA of <fx:Script/> instead of referencing as external *.as file. Though I understand that this is not always desired.
I'm afraid the fix won't go into 12 release because the release is very soon and the fix is too risky. Priority of the issue depends on votes and user feedback. So far we have only 2 votes (http://youtrack.jetbrains.com/issue/IDEA-52598) and as the fix is pretty complex we still haven't implemented it thinking that this is a rare use case. I hope to fix it in one of 12.x update releases.
My project is a huge one, with huge MXML files and even more huge AS code for each MXML. So, for organisation purposes, I need to logically split them into smaller files. So, merging the AS code with the MXML is not practical. The false error highlighting just drastically reduces the readability of the code. Also, it does not allow Control / Command-clicking component IDs in AS code to quickly navigate to the definition of the component in MXML (which, incidentally, is now broken in FB 4.7 as well, but worked well in FB 4.6).
This bug in IDEA is unfortunately a deal-breaker for me. But I am wondering how other Flex devs are able to overcome / work around this seemingly critical bug.
It seems unbelievable to me that just 2 people have been affected by this bug, especially with so many Flex devs recommending IDEA. Maybe I am doing something wrong?
All you Flex developers, I would appreciate your thoughts.
UPDATE
This is in response to RIAStar's excellent and detailed answer. But it doesn't quite help me completely. Let me explain why and how I use <fx:Script source>. I am using Flex 4.x, with almost only Spark components.
Suppose a brand new Flex project. The main application is an MXML file.
In this MXML file, suppose I have a signup form.
On editing the form (in each field), suppose I have to run validations and enable the Submit button only if the form is completely valid. This would mean I need to assign change event handlers to the form items. The event handlers is AS code.
Suppose there is a username field which needs an on-type uniqueness check, by calling the server asynchronously. The server communication code is also AS code.
And then of course, there is the Submit button handler, which is also AS code.
I usually put all the AS code in separate .as files and include it in the MXML using <fx:Script source>. This AS code is usually quite heavy, with a lot of functional and behavioural logic. Many times, based on user action, even the components in the MXML and layout of the elements is modified through this AS code.
If I understand you guys right, none of this event handler code should be in these MXML script files. So, where should it be? How do you guys do it? I am not sure how the Spark Skinning architecture has anything to do with this.
Since I can't think of a gentle way of putting this, I'll just be blunt: I'm afraid the reason only two people think this is a critical bug, is that most seasoned Flex developers will agree that using <fx:Script source="some_file.as"/> is bad practice.
You effectively create two files that represent one class. From a readablity POV, which you seem concerned about, that's not a good move. One of these files (the .as file) is just a bunch of functions that cannot exist in their own right: they are tightly coupled to another file/class, but just looking at the .as file there is no way of knowing which class it is coupled to. Of course you can use some kind of naming convention to work around this, but in the end ActionScript/Flex is supposed te be used as a statically typed language, not a scripting language relying on mixins and naming conventions (don't get me wrong: I'm not saying scripting languages are bad practice; it's just not how ActionScript was conceived).
So what are your alternatives?
I suppose the main reason behind this construct is that you wish to separate MXML from ActionScript code, or in more abstract terms: separate the view from the logic. Fortunately this can be achieved in a few other, cleaner ways. Which solutions are available to you depends whether we're talking Flex 3 (or earlier) or Flex 4.
I realise that you may not have time to refactor your code to one of the proposed solutions, but I didn't want to leave you with just a "that's not good practice" answer.
Flex 3 (mx)
Code behind: A lot of developers used the so-called "code behind" pattern to separate their logic from their view. You can find plenty of information on the topic by Googling "flex code behind". I don't need to repeat all that in here. I'm not much of a fan of the concept because it relies heavily on inheritance and the two resulting classes are still pretty tightly coupled, but at least we're talking two classes. If you design your architecture well, you may even be able to reuse some of your base classes.
Compose model en controller: I used to create a separate "presentation model" class and a "controller" class for each MXML view and then use it something like this:
<!--MyView.mxml-->
<mx:VBox>
<m:MyModel id="model"/>
<c:MyController model="{model}" view="{this}"/>
...
</mx:VBox>
MVC purists won't like this, but it worked pretty well for me in thencontext of Flex applications.
Later when Direct Injection supporting frameworks (like Parsley) made their appearance, I could use injection to wire all those classes instead of hard-wiring them like in this example.
MVC frameworks: My knowledge of this topic is sparse (because in my opinion Flex is a very decent MVC framework that requires no third-party additions, but that's another disussion), but in short: they can help you separate logic from view in a clean way.
Flex 4 (Spark)
With Flex 4, the Spark skinning architecture was introduced, which allows for very nicely separated view and logic. You create a so-called 'host component' class in plain ActionScript, which contains all of the behavioural code, and a 'skin' class in MXML which defines the visual representation of the component. This makes designing reusable components very easy.
As per your request, here's a simplified example of how you might use Spark skinning to create your signup form.
Let's start with the skin class since it's easy to understand. It's just a form with some input fields. The HostComponent metadata tells the skin it's supposed to work together with the SignUp host component.
<!--SignUpSkin.mxml: the visual representation-->
<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark">
<fx:Metadata>
[HostComponent("net.riastar.view.SignUp")]
</fx:Metadata>
<s:Form>
<s:FormHeading label="Sign up"/>
<s:FormItem label="User name">
<s:TextInput id="userInput"/>
</s:FormItem>
<s:FormItem label="Password">
<s:TextInput id="passwordInput" displayAsPassword="true"/>
</s:FormItem>
<s:Button id="submitButton" label="Submit"
enabled="{hostComponent.canSave}"/>
</s:Form>
</s:Skin>
And now the host component in pure ActionScript. It has to extend SkinnableComponent to be able to use our skin (there's also SkinnableContainerwhich I've just recently explained in this question: Flex mxml custom component - how to add uicomponents?, but we won't be needing that here).
public class SignUp extends SkinnableComponent {
[SkinPart(required="true")]
public var userInput:SkinnableTextBase;
[SkinPart(required="true")]
public var passwordInput:SkinnableTextBase;
[SkinPart(required="true")]
public var submitButton:IEventDispatcher;
[Bindable]
public var canSave:Boolean;
override protected function partAdded(partName:String, instance:Object):void {
super.partAdded(partName, instance);
switch (instance) {
case userInput:
userInput.addEventListener(TextOperationEvent.CHANGE,
handleUserInputChange);
break;
case passwordInput:
passwordInput.addEventListener(TextOperationEvent.CHANGE,
handlePasswordInputChange);
break;
case submitButton:
submitButton.addEventListener(MouseEvent.CLICK,
handleSubmitButtonClick);
}
}
private function handleUserInputChange(event:TextOperationEvent):void {
validateUsername(userInput.text);
}
...
}
What's important here?
The variables marked as SkinPart will automatically be assigned the components with the same id that exist in the Skin you just created. For instance <s:TextInput id="userInput"/> will be injected into public var userInput:SkinnableTextBase;. Note that the type is different: SkinnableTextBase is the base class of TextInput; this allows us to create another skin with e.g. a TextArea instead of a TextInput and it'll work without touching the host component.
partAdded() is called whenever a SkinPart is added to the display list, so that's where we hook up our event listeners. In this example we're validating the username whenever its value changes.
When the validation is done, you can simply set the canSave property to true or false. The binding in the skin on this property will automatically update the Button's enabled property.
And to use both of these classes together:
<v:SignUp skinClass="net.riastar.skin.SignUpSkin"/>
I actually have become quite fond of using RobotLegs.
In my MXML views I try to keep all logic outside of the MXML and simply dispatch events out to the mediator. From there I can put code in the mediator to the heavier AS needed.
Would anyone be able to point out some good tutorials on creating applications in flex that are don't have UI's?
Actually, it looks like all I really need to know is how to call a function upon initialization of the flash object. I tried the creationComplete attribute, but it doesn't work in browser.
Well, I'm not sure what made it work finally, but I ended up copying and pasting this code from some website (sorry, i don't remember the site):
<?xml version="1.0" encoding="utf-8"?>
<!-- wrapper/CheckExternalInterface.mxml -->
<s:Application
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark"
creationComplete="initApp()">
</s:Application>
And that ended up working! thanks anyway.
If you're intent is to connect JavaScript to a Java Server, why not use XMLHTTPRequest? IT is the basis of every AJAX style RIA application. The data format you pass back and forth can either be JSON or XML. It doesn't have to be binary.
Second, you don't need Flex for this. The Sockets APIs in ActionScript and are part of the Flash Player. You can use them without any dependencies to the Flex Framework.
Hello all!
I'm working on a prototype that would require me being able to read and track the mouse movement over a playing youtube video. The basic code to replicate my problem boils down to this simple test case:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute"
initialize="{go();}">
<mx:VBox>
<mx:Label id="test" text=""/>
<mx:SWFLoader source="http://www.youtube.com/apiplayer?version=3" />
</mx:VBox>
<mx:Script>
<![CDATA[
function go(){
Security.allowDomain("*");
Security.allowInsecureDomain("*");
addEventListener(MouseEvent.MOUSE_MOVE,
function(e:MouseEvent){trace(test.text=e.stageX+"")});
}
]]>
</mx:Script>
</mx:Application>
Expected behavior is:
Youtube player loads
The label on the top right tracks the X coordinate of the mouse
The number should update even when moving the mouse over the Youtube player
So far the program behaves as expected when running from the IDE (tested on both FlashDevelop and FlashBuilder) and even when running the file manually from the output folder. But, alas, when I try to run it from anywhere else than the debug folder (be it another location on my computer or up on a webserver), the Youtube player seems to eat the events.
I don't get sandbox security warnings when debugging (thanks to allowDomain("*")) but I'm running out of ideas on why the program fails once you take the file out of the debug folder.
I would immensely appreciate any clues. Please note that as far as solutions go, I'm willing to try a different tech than flash if you have a proof of that working somewhere else.
Ok so I'm answering my own answer (I know...) only to let it recorded somewhere if someone needs it.
As much as I tried, there was no success with tweaking the security sandbox settings. I even tried all possible combinations, and no dice.
What I did do, out of desperation, was actually adding mouse listeners to the Loader.content property once loading is finished. And it worked well enough.
It's the only place I've found where a loading application can safely access the loadee's mouse events without obstructing its inner mouse logic.
Hope it helps someone else get unstuck in the future!
I'd like to be able to add a character to a TextInput programmatically (say when you press a button) even when using IMEs (I'm using a Japanese IME right now). Normally this would be super easy, i.e.
protected function button_clickHandler(event:MouseEvent):void
{
ti.text = "k";
}
where ti is a TextInput component. However, things get a little tricky when using an IME. The code above, for instance, adds a k in ti even if you're using the Hiragana IME.
I looked at the IME documentation and tried something like this
protected function button_clickHandler(event:MouseEvent):void
{
IME.setCompositionString("k");
}
at first I thought this was doing the trick, but it seems like it always defaults to what looks like Half-Width Katakana (although I'm not 100% sure), even if the Hiragana conversionMode is currently selected, or if I set it right before setting the composition string. Unfortunately the IME library doesn't seem to be open source so I have no idea if this is a bug or not.
Was wondering if anyone had any advice - I realize this is super specific so the odds are low, but thought I'd try.
thank you!
post-edit: here is some code to try out what I'm talking about. Note: you'll need Japanese IME setup on your machine. I'm using this on a Windows 7 box with Japanese IME setup, and running it on standalone Flash. It's hard to see the difference between typing a k in Hiragana and in Katakana, but if you look closely you should notice a difference (and if you type an 'a' right after you should see different results popping up).
<?xml version="1.0"?>
<!-- dpcontrols/adg/SimpleADG.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark">
<fx:Script>
<![CDATA[
protected function button_clickHandler(event:MouseEvent):void
{
ti.setFocus();
try
{
IME.enabled = true;
IME.conversionMode = IMEConversionMode.JAPANESE_HIRAGANA;
IME.setCompositionString("k");
}
catch (error:Error)
{
trace("Unable to set conversion mode.\n" + error.message);
}
}
]]>
</fx:Script>
<s:VGroup>
<s:TextInput id="ti"/>
<s:Button label="go" click="button_clickHandler(event)"/>
</s:VGroup>
</s:Application>
First, look at this link: http://livedocs.adobe.com/flex/3/html/help.html?content=18_Client_System_Environment_6.html
Make sure you have IME enabled and the proper settings. Second, what version of flex are you using? Do you have a font that's loaded into the application that can handle the language?
filed a bug - we'll see what Adobe says.
What I'm trying to do: allow a user to be able to select a color palette for a custom component by selecting from a drop down menu with a variety of icons.
I have the drop down menu part down, but I'm trying to understand how to best handle the various styles in my code. Ideally I would have liked to be able to load styles at run time, but I don't see a major advantage with this so I'm now thinking about compiling in all styles. Still, I can't seem to find a decent way to structure the code. Hacking it seems pretty easy / fast, but there's got a better way than having a big fat array of values which can be indexed via some index associated with each icon - yuck!
Would love to hear your thoughts or see any pointers to obvious ways to handle this.
thank you!
fred
I'd define a set of style names in CSS, then you can use a collection of style names to provide values for your style selector control, like so:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Style>
.style1{color:red;}
.style2{color:green;}
.style3{color:blue;}
</mx:Style>
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
public static const styleNames:ArrayCollection =
new ArrayCollection(['style1', 'style2', 'style3']);
]]>
</mx:Script>
<mx:ComboBox
id="styleCombo"
styleName="{styleCombo.value}"
dataProvider="{styleNames}"
/>
</mx:Application>
The optimal way to achieve this is to compile several CSS+Swf(assets) files and then loading them at runtime according to what the user selected.
This is by far the best practice out there, I used it for large applications and small applications and it stands tall above every other solution I could think of.
good luck