What undocumented alchemy is necessary to get parentApplication to work - apache-flex

I load an SWF with SWFLoader. Within the loaded .SWF, this.parentApplication is returning NULL. Been searching the internet for eight hours.
code listing as requested:
<?xml version="1.0"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
initialize= "Init();"
visible="false"
>
<mx:Script>
<![CDATA[
import flextrace.Dumper;
private var txt_event:TextEvent = new TextEvent(TextEvent.LINK,false,false,"next.xml");
private var timer:Timer = new Timer(10000);
private function Init():void {
timer.addEventListener(TimerEvent.TIMER,timer_handlr);
timer.start();
}
private function timer_handlr(event:Event) {
Dumper.info("timer_handlr");
if (this.parentApplication == null)
Dumper.info("null");
parentApplication.dispatchEvent(new TextEvent(TextEvent.LINK,false,false,"next.xml"));
}
]]>
</mx:Script>
</mx:Application>

I just was looking through Flex docs and saw an answer on your question, if I understood you correctly:
The parentApplication property of an Application object is never itself; it is either the Application object into which it was loaded, or it is null (for the Application object).
Since, your calling it from the application, it should be null.
Just a quick link for you about accessing nested applications (I haven't tested the solution yet tho, but still, may give you some ideas): Nesting Flex applications - weird issues..
Hope, this would help :)

RYAN GUILL: I tried your suggestion - didn't work. I replaced the dispatchEvent call in the code from the OP with the following: this.dispatchEvent(new TextEvent(TextEvent.LINK,true,false,"next.xml")); Were you saying that this should have triggered the Parent application's event handler for TextEvent.LINK? It didn't work.

Try FlexGlobals.topLevelApplication?
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/core/FlexGlobals.html?filter_flex=4.1&filter_flashplayer=10.1&filter_air=2

Related

Calling JavaScript function from Flex 4 web application

I need to call javascript function from Flash 4 based web application. When I run it in Debug mode it runs perfectly but when I make release build or run same application on other machine it does not call JavaScript function.
For testing I am just calling sample Alert function of JavaScript. Can someone help me what I am missing ?
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical" initialize="application1_initializeHandler(event)"
verticalAlign="middle"
backgroundColor="white">
<mx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.events.FlexEvent;
public function btnLogin_click():void
{
var s:String;
if (ExternalInterface.available)
{
ExternalInterface.call("alert", "Hello World!");
}
else
{
Alert.show("External interface not available");
}
trace(s);
}
protected function application1_initializeHandler(event:FlexEvent):void
{
flash.system.Security.allowDomain("always");
}
]]>
</mx:Script>
<mx:Form>
<mx:FormItem>
<mx:Button id="btnLogin" label="Login" click="btnLogin_click()" />
</mx:FormItem>
</mx:Form>
</mx:Application>
Well, firstly, make sure JavaScript on your testing machine is turned on and then also make sure you are adding your JavaScript file/code after adding swfobject.js file.
I had similar problem but it worked out when I moved swfobject.js at the top of all js includes.
Have you tried a test like (Flex):
ExternalInterface.call("alertFn");
And JS:
function alertFn() {
alert("hello world");
}
?
I've never tried an ExternalInterface call to a native JS function like "alert"...
After digging out the error code 2060 through
Alert.show(e.message)
I figured out that for some reason ExternalInterface.call doesn't work on a file:// and needs http(s)://
So, anybody who is facing this problem, get your yourself a webserver(Apache) or a GAE for testing these kinds of things and save yourself from the "Extreme time wastage":
I was having endless hours of problems using file:// with the Flex
AJAX Bridge.
The AJAX code would fail silently during the SWF initialization
callbacks to the AJAX code. I would then have null values for all of
the SWF root elements.
As soon as I installed a web server and started using http:// localhost
everything worked perfectly.
Extreme time wastage :(
test.mxml
..........
protected function bt1_clickHandler(event:MouseEvent):void
{
// TODO Auto-generated method stub
ExternalInterface.call("callUnity");
}
.js
....
function callflex(){
alert("got it");
}

Why is my object reference null when trying to reference an mx:Canvas from ActionScript?

this is a follow up question from this one, I don't want to keep going in the comments and preventing people from getting hard-earned reputation... :)
In my Cairngorm command class, to get it to compile I needed to tell it what myCanvas was, so I used this line:
var myCanvas : MyCanvas = new MyCanvas;
I'm guessing that's wrong, though, because although it compiles, if I try to do something like this:
if (myCanvas.subObject.value == 0) { ... }
it'll throw this error:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at com.foo.bar.command::MyCommand/execute()
as if the subObject doesn't exist. It looks like I might be getting a new instance of MyCanvas, not the instance I want from the main.mxml with an id of myCanvas. Am I right? How do I fix this?
Edit (10:59pm GMT+1): Okay, so it looks like I've been way too vague here. Here's my main.mxml:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:control="com.foo.bar.control.*"
xmlns:business="com.foo.bar.business.*"
xmlns:view="com.foo.bar.view.*"
applicationComplete="com.foo.bar.util.StartupUtil.init()"
horizontalScrollPolicy="off"
verticalScrollPolicy="off"
borderThickness="0"
paddingBottom="0"
paddingLeft="0"
paddingTop="0"
paddingRight="0"
>
<mx:Script>
<![CDATA[
import com.foo.bar.model.PlayerModelLocator;
[Bindable]
private var model : PlayerModelLocator = PlayerModelLocator.getInstance();
]]>
</mx:Script>
<!-- ========================================================================== -->
<!-- the ServiceLocator where we specify the remote services -->
<business:Services id="services" />
<!-- the FrontController, containing Commands specific to this application -->
<control:PlayerController id="controller" />
<!-- ========================================================================== -->
<mx:Style source="assets/main.css" />
<view:MyCanvas id="myCanvas" />
</mx:Application>
And here's my com/foo/bar/command/MyCommand.as:
package com.foo.bar.command {
/* add to controller
addCommand( MyEvent.EVENT_CHANGE_VOLUME, ChangeVolumeCommand );
*/
import flash.net.SharedObject;
import com.adobe.cairngorm.control.CairngormEvent;
import com.adobe.cairngorm.commands.ICommand;
import com.foo.bar.model.PlayerModelLocator;
import com.foo.bar.event.MyEvent;
import com.foo.bar.view.*;
public class ChangeVolumeCommand implements ICommand {
public function execute(event:CairngormEvent):void {
var model : PlayerModelLocator = PlayerModelLocator.getInstance();
var myEvent : MyEvent = MyEvent(event);
var myCanvas : MyCanvas = new MyCanvas();
var so:SharedObject = SharedObject.getLocal("fixie.video");
if (myCanvas.subObject.value == 0) {
trace("subobject value is 0");
}
}
}
}
Basically, I want to get a handle on the object with ID myCanvas in main.mxml using the myCanvas object in MyCommand.as
Could be a couple of things. First, you need parentheses on your class name after the "new" statement: new MyCanvas(); Second, you may be trying to access your sub component before the component lifecycle is ready for you to do so. (It's hard to tell from the code you posted since there isn't enough context.)
What is the scope of your myCanvas variable? Is it inside a method somewhere? You will need to make it public or give it getter/setter to be able to access it.
You may also be trying to reference it before it has been added to its parent, using the addChild() method.
There really isn't enough code in your examples to determine the problem, but these things should give you somewhere to start looking.
1 way is to add eventListener when your myCanvas will be ready after CreationComplete and to do all your stuff
and the second is:
define your subObject as in myCanvas class so you'll be able to access it on Init Stage of your component.
regards
Eugene
p.s. all of the time everybody want to get answer without well formed sample of their problem, its terrible!!

Access WindowedApplication from package class

I'm developing an AIR application, where i need to access
WindowedApplication's function from the package class.
This is the Main application (Partial code)
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute" creationComplete="initApplication()">
<mx:Script>
<![CDATA[
import mx.events.CloseEvent;
import messages.MessageWindow
public function undock():void {
stage.nativeWindow.visible = true;
stage.nativeWindow.orderToFront();
//Clearing the bitmaps array also clears the applcation icon from the systray
NativeApplication.nativeApplication .icon.bitmaps = [];
}
]]>
</mx:Script>
</mx:WindowedApplication>
Package: (Partial code)
package messages
{
public class MessageWindow extends NativeWindow
{
public function MessageWindow():void
{
stage.addEventListener(MouseEvent.MOUSE_DOWN,onClick);
}
private function onClick(event:MouseEvent):void
{
****** Need to call the undock method from here. *****
}
}
}
Is it possible to call this way or suggest any other solution
Thanks in advance
Senling.
Even if I don't recommend this for the sake of your code design, you can access your method like this:
Application.application.undock()
(if your undock() method is public in the WindowedApplication )
Cant see why it shouldnt work. Go ahead and give it a try, and if any errors come up, post it here.
What you can maybe try is to add parentApplication in front of stage in the MessageWindow method, like this..
parentApplication.stage.addEventListener(MouseEvent.MOUSE_DOWN,onClick);
and then call the undock() method from the onClick() method

Flex: image switching place in tilelist

I'm running into an odd issue with itemRenderers inside a TileList.
Here is a working example without an itemRenderer: 152.org/flex/
Here is the broken version with an itemRenderer: 152.org/brokenExample/
(I don't have the rep to make both of these a link)
Both examples have "View Source" enabled.
To see the problem use the broken example, select an album and scroll down one row. Scroll back up and the images will be switched. If you try this on the working example it's fine.
This seems to be a widely known bug, but I can't find a solution for it.
UPDATE
I started playing with this example again and found out something else. Turns out you don't have to override the data setter. You can create a new method in the itemRenderer that is set whenever the tile wants to refresh. So the trick is to not rely on the initialize or creationComplete methods.
This is what I have for the itemRenderer in the Application.
<itemRenderers:ImageTile img="{data}"/>
This is the code I have in the itemRenderer.
public function set img(value:String) : void {
trace("setting source: " + value);
this.source = value;
this.name = value.toString().split("/").pop().split(".").shift();
}
I updated my example to reflex this change.
I don't have your app handy, so I can't test end-to-end, but I've looked at your source. You probably need to override the data setter in your itemRenderer:
<?xml version="1.0" encoding="utf-8"?>
<mx:Image xmlns:mx="http://www.adobe.com/2006/mxml" initialize="init()">
<mx:Script>
<![CDATA[
override public function set data(value:Object):void
{
super.data = value;
this.source = data;
this.name = data.toString().split("/").pop().split(".").shift();
}
private function init() : void {
// Removed from your source and transplanted above
}
]]>
</mx:Script>
</mx:Image>
Flex will attempt to re-use item renderers in lists (which means the lifecycle events you might be expecting -- initialize, creationComplete, etc. -- won't always fire), so if you want to be sure your renderer gets updated when the data item changes (as it will when scroll events happen), the best practice is to override the renderer's data property. That'll most likely fix the problem.
Maybe try to invalidate on creationComplete?
From what I recall with DataGrids (which work somewhat similarly to a tilelist), when an item comes into focus its recreated.
<mx:itemRenderer>
<mx:Image id="myImage" creationComplete="myImage.invalidate()" />
</mx:itemRenderer>
Haven't tried this code but I think this is where you want to start looking. I took a look at your itemRenderer component. Try creationComplete instead of initialize to call your function

How can I target a Flex 3 datagrid in MXML from Actionscript?

I have a datagrid defined in an mxml file (flex 3):
I am using an external class to connect to a sqlite database and generate some results (this is working and I can trace the results).
How can I target the datagrid generated in the mxml from the external class? I have tried:
Application.application.resultsGrid.dataProvider = results.data;
And get 'Error: Access of undefined property Application.' from the amxmlc compiler.
I've also tried:
[Bindable]
public var resultsGrid:DataGrid;
In the class properties.
Looks like I needed to include import mx.core.*; and it now works.
I don't really understand your answer. Am I not binding the dataprovider property by doing:
Application.application.resultsGrid.dataProvider = result.data; ?
I'm from a PHP background and familiar with OOP in that environment so the idioms in Flex are quite strange to me.
as brd664 says, what you are actually doing in
Application.application.resultsGrid.dataProvider = result.data;
is actually an assignment. It's just like assigning a value to variable as in
var a : uint = 1;
Binding gives you a little more structure and allows you to populate multiple components based on a single property update. There's a ton of other benefits from binding and probably too much to cover in this post.
Here is a quick and simple example of how binding works. Note that there is one property that is bindable... when you click the button it sets that property to the value of whatever is in the textInput. This update then causes the bindings to fire and updates anything that has been bound to that property. It's one of flex's biggest features (it's also used extensively in silverlight and wpf and probably a load of other technologies that i'm not aware of). Anyway... have a play with it and see if you can get your component to update from a binding.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="horizontal">
<mx:Script>
<![CDATA[
private var _myData : String
[Bindable]
public function get myData() : String
{
return _myData;
}
public function set myData(value : String) : void
{
_myData = value;
}
private function clickHandler(event : MouseEvent) : void
{
myData = myTextInput.text;
}
]]>
</mx:Script>
<mx:VBox>
<mx:HBox>
<mx:Label text="{myData}" />
<mx:Label text="{myData}" />
<mx:Label text="{myData}" />
</mx:HBox>
<mx:TextInput id="myTextInput" text="TYPE HERE" />
<mx:Button label="CLICK TO BIND" click="clickHandler(event)" />
</mx:VBox>
</mx:Application>
Update: The phrasing of your question confused me :(
If you need to populate the datagrid with from you db, you really should be looking at binding the dataProvider property.

Resources