Flex Air HTMLLoader blank pop up window when flash content is loaded - apache-flex

I have a flex Air program that loads external content with the HTMLLoader. Now for some reason whenever I load a page that has any flash content a blank system window pops up outside of my program. It's completely blank, all white with min, max and close buttons. If I close it any flash content I loaded stops working. For the life of my I can't figure out what's happening and there's no messages in the console and no title for the window.
Does anyone have any ideas? I appreciate any help you can give. Here's the code I'm using:
private var webPage:HTMLLoader;
private function registerEvents():void
{
this.addEventListener(gameLoadEvent.GAME_LOAD, gameLoad);
//webPage = new HTMLLoader();
}
//function called back from Game Command to load correct game
private function gameLoad(event:Event):void
{
var gameEvent:gameLoadEvent = event as gameLoadEvent;
loadgame(gameEvent.url, gameEvent.variables);
}
private function loadgame(url:String, variableString:String):void
{
DesktopModelLocator.getInstance().scaleX = 1;
DesktopModelLocator.getInstance().scaleY = 1;
//var url:String = "http://pro-us.sbt-corp.com/aspx/member/LaunchGame.aspx";
var request:URLRequest = new URLRequest(url);
//var variables:URLVariables = new URLVariables("gameNum=17&as=as1&t=demo&package=a&btnQuit=0");
if(variableString != null && variableString != ""){
var variables:URLVariables = new URLVariables(variableString);
variables.exampleSessionId = new Date().getTime();
variables.exampleUserLabel = "guest";
request.data = variables;
}
webPage = HTMLLoader.createRootWindow(true, null, true, null);
webPage.height = systemManager.stage.nativeWindow.height - 66;
webPage.width = systemManager.stage.nativeWindow.width;
webPage.load(request);
webPage.navigateInSystemBrowser = false;
flexBrowser.addChild(webPage);
}
]]>
</mx:Script>
<mx:HTML id="flexBrowser" width="1366" height="658" backgroundAlpha="0.45" creationComplete="registerEvents();" x="0" y="0">
</mx:HTML>

you're not using any of the capabilities of your html component. As is, it may as well be a canvas since all you're doing is addChild to flexBrowser, a DisplayObjectContainer. Though I wouldn't do it this way, you can pretty simply set the flexBrowser.htmlLoader.load(request); and get rid of all that webPage stuff.

Is your application using a transparent window? air won't display flash content in the HTMLLoader in that case, see http://bugs.adobe.com/jira/browse/SDK-15033
One workaround is to use http://code.google.com/p/adobe-air-util/source/browse/trunk/src/net/tw/util/air/HTMLOverlay.as.
I had to do some changes to get it to work well with our app. I sent an email to the project owner to contribute the changes, if you are still on it I can send you the patch. The most important change, is that the html overlay window does go behind other apps when switching i.e. alt-tab or opening another app.
Update: I committed the changes to the overlay above, check it out as it should work for you as well. I know it seems like an awful workaround, but there doesn't seem to be anything better until adobe fixes the issue. If you do see something better, make sure to post the update :)

This problem has been fixed in AIR 1.5.2:
Before AIR 1.5.2, SWF content embedded in and HTML container in a transparent window could not be displayed. With AIR 1.5.2, SWF content can be displayed with certain wmode settings.

Related

Flex 4.6 Need to know how to animate a .swf in actionscript

I've converted a PowerPoint into Flash so each slide is a .swf. I've used a number of different converters and the problem here is the same.
What I'd like to do is trigger the .swf's animation (contents of slide appearing) programatically. I can click on the .swf with a mouse and the animation advances. I can automate this when the .swf's embedded in a web page simply by doing:
document.getElementById('myMovie').play();
Each time I execute that code, the swf advances to the next animation. However, I can't find a way to do this in flex. I've used then MovieClipSWFLoader and tried:
private function animate():void {
var simulatedClick1:MouseEvent = new MouseEvent(MouseEvent.CLICK);
var simulatedClick2:MouseEvent = new MouseEvent(MouseEvent.MOUSE_DOWN);
var simulatedClick3:MouseEvent = new MouseEvent(MouseEvent.MOUSE_UP);
frameNo++;
myMovie.gotoAndStop(frameNo);
myMovie.nextFrame();
myMovie.nextScene();
myMovie.play();
myMovie.dispatchEvent(simulatedClick1); // with clicks 1, 2, and 3
}
<s:MovieClipSWFLoader id="myMovie" source=""/>
<s:Button id="btnAnimate" click="animate()"/>
I've also tried loading as an Image component and using the simulated click too... no good. Can anyone tell me how I can do this?
The problem was that the .swf was created with Flash 8 and wasn't compatible with my version of Flex. I found a great solution in ForcibleLoader at https://gist.github.com/nsdevaraj/409902. It converts old .swf's to new ones and then the code worked as it should.
private var libMC:MovieClip = new MovieClip();
ur = new URLRequest(guide_url);
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, swfComplete);
var fLoader:ForcibleLoader = new ForcibleLoader(loader);
fLoader.load(ur);
swfMovie.addChild(loader);
private function swfComplete(event:Event):void{
libMC = event.currentTarget.content as MovieClip;
}
private function animate():void {
libMC.nextFrame();
<mx:UIComponent id="swfMovie"/>

Text Highlighting issue with TextSnapshot object - Flex AS3

I am working with a digital book application. I make use of swf loader to load swf pages created from pdf. I use TextSnapsot to draw inline text highlight on the pages. The highlight is thoroughly retained on the respective pages throughout the session and later it can be updated/deleted without any problem. Everything was working great till I made the following changes in the swf loading approach to enable page caching:
I am now loading swf loader object into application memory and while doing jumping from one page to other page I am just copying the content of the next page to the current swf loader which is on the display to the user. There are two sets of swf loaders - one for displaying the page and other to cache the next/previous page(s). On the caching side, I load the swf into application memory and after getting it loaded I pick all the contents of the loaded swf page (the children of it's movie clip) into an array collection. While changing the page I copy the cached content into the swf loader's movie clip which is displaying the page.
Now when I highlight on the page on display and navigate back/forth from the page and comeback again to the page where I did the highlighting: It shows the highlight I did. But as soon as I try to draw another highlight on that page, the previous highlight is instantly disappears from the page.
I suspect that the Textsnapshot object which draws highlight while navigating (to the target display page) is different from the one which redraws/update the highlight on the same page next time. Although the Textsnapshot object id for both the objects is same.
Here are some code snippet:
For copying the content from the swf loader object cached in application memory:
private function copyPageContent():void
{
var contentCollection:ArrayCollection = new ArrayCollection();
_pageContentVO = new PageContentVO();
_pageContentVO.contentHeight = MovieClip(_swfPageLoader.content).height;
_pageContentVO.contentWidth = MovieClip(_swfPageLoader.content).width;
var count:int = MovieClip(_swfPageLoader.content).numChildren;
for(var i:int=0;i<count;i++)
{
var dispObject:DisplayObject = MovieClip(_swfPageLoader.content).removeChildAt(0);
contentCollection.addItem(dispObject);
}
_pageContentVO.pageContentCollection = contentCollection;
_swfPageLoader = null;
}
For copying the content to the swf loader which is displaying the page:
private function copyContent(pageContentVo:PageContentVO):void
{
for(var i:int = 0;i<pageContentVo.pageContentCollection.length;i++)
{
var dispObject:DisplayObject = pageContentVo.pageContentCollection.getItemAt(i) as DisplayObject;
MovieClip(this.content).addChild(dispObject);
}
this.content.height = this.height;
this.content.width = this.width;
}
after this I dispatch swf loader's complete manually and in the handler of that event I take the text snap shot object.(highlightManager.as)
Code I use to draw highlight manually(using mouse drag on the page).
public function setHighlight():void
{
removeAll();
if(_textSnapShot!=null && _textSnapShot.getText(0,_textSnapShot.charCount)!="")
{
if(_isCoveredTextSelectedAtAnyInstance)
{
_textSnapShot.setSelected(_beginIndex,_endIndex+1,false); //this is the global variable to the class
}
else
{
_textSnapShot.setSelectColor(0xfff100);
_textSnapShot.setSelected(_beginIndex,_endIndex+1,true);
}
if(saveHighlight)
{
countHighlightedSegments();
}
}
}
Code I use to redraw previously drawn highlight when I return to the page:
public function showHighlights(textSnapShot:TextSnapshot,currentPageNum:int):void
{
if(currentPageNum >= 0)
{
textSnapShot.setSelected(0,textSnapShot.charCount,false);
var pageVO:PageVO = _model.eBookVO.eBookPagesVO.getItemAt(currentPageNum) as PageVO;
var objColl:ArrayCollection = new ArrayCollection();
objColl.source = pageVO.highLightSelection;
for(var i:int=0;i<objColl.length;i++)
{
var highlightVO:HighlightVO = new HighlightVO();
highlightVO.beginIndex = objColl.getItemAt(i).beginIndex;
highlightVO.endIndex = objColl.getItemAt(i).endIndex;
setHighlightedSegment(textSnapShot,highlightVO.beginIndex,highlightVO.endIndex);
}
}
}
private function setHighlightedSegment(textSnapShot:TextSnapshot,beginIndex:int,endIndex:int):void
{
textSnapShot.setSelectColor(0xfff100);
textSnapShot.setSelected(beginIndex,endIndex,true);
}
Looking forward to your support to resolve this issue.
Regards,
JS
What you're doing is not 'caching', it's preloading previous/next pages. Also, what you're doing is really bad practice. I'm not even sure why you're casting these things into MovieClips unless the SWFs are that; if they're Flex SWFs, they'll be UIComponents. I would recommend you rethink your approach. I wouldn't even bother copying the children or anything over. Once the browser loads a SWF, it is now part of the browser cache, meaning the next time it's requested, it won't actually download it.
If you want to 'cache' your SWFs for a quicker next/previous page flipping, I would recommend you use something like SWFLoader to just load the other SWFs without actually adding it to the display, then removing it from memory. That will cache the SWFs for you in the browser. Then when the user click previous/next, just change the url of the main swfloader of the currently displayed page and it will load it up really quickly. No downloading since it's already cached, it will just need to instantiate.

Add Child immediately in Flex 3

I'm having a problem similar to FLEX: dialog not display immediately . Code follows:
private function saveBitmap(event:ContextMenuEvent):void
{
loadingScreen.visible = true;
loadingScreen.appLoadingText.text = "Preparing bitmap...";
addChild(loadingScreen);
validateNow();
var bmpd:BitmapData = new BitmapData(canv.width, canv.height);
bmpd.draw(canv);
var fr:FileReference = new FileReference();
fr.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA, removeLoadingScreen);
fr.addEventListener(Event.CANCEL, removeLoadingScreen);
var png:PNGEncoder = new PNGEncoder();
var iba:ByteArray = png.encode(bmpd);
fr.save(iba, "export.png");
}
Basically, bmpd.draw and/or png.encode are dog slow, so I'd like to have a nice "please hold while we prepare your png" dialog to appear. I can't use callLater() because of the FileReference.
And just for good measure, the loading screen appears at the same time the save dialog appears from the call to fr.save().
Any ideas?
Cheers!
You're adding the child in this function. Are you doing any other work to the loadingScreen, such as sizing it? Or positioning it? Most commonly this is done in updateDisplayList(). What container are you using?
Are you sure the Z-order of your two children is correct? You can swap children with the swapChildren method

Images won't dynamically refresh

I am writing a Flex application to receive xml from an httpservice. That works because I can populate a datagrid with the information. The xml sends image pathnames. A combobox sends a new HttpService call onChange. This repopulates the datagrid and puts new images in the folder that flex is accessing.
I want to dynamically change the image without changing the pathname of the image.
<mx:Canvas id="borderCanvas"><mx:Canvas id="dropCanvas">
<mx:Tile id="adTile"><mx:Image></mx:Image>
</mx:Tile></mx:Canvas></mx:Canvas>
This is my component.
I assign my Image sources using this code:
var i:Number = 0;
while ( i <= dg_conads.rowCount){
var img:Image = new Image();
img.source = null;
img.source = imageSource+i+".jpg";
adTile.addChild(img);
i++; }
My biggest problem is that the images are not refreshing. I get the same image even though I've prevented caching from the HTML wrapper and the ASP.Net website. The image automatically loads in the folder and refreshes in the folder but I can't get the image to refresh in the application.
I've tried removeAllChildren(); delete(adTile.getChildAt(0)); and neither worked.
I would try using:
img.load(imageSource + i + ".jpg");
If that doesn't work, try appending a random number on the end ie:
img.source = imageSource + i + ".jpg?" + Math.random();
Have you tried to add id="img" into the mx:Image tag directly and remove adTile.addChild(img);
in the script?

Flex 3: Is it possible to use a remote image as the icon for a LinkButton?

We are creating a LinkButton programmatically and would like to set it's icon to an image retrieved from the remote server rather than something embedded within the SWF. The .icon property expects a Class but I can't figure out how to create one equivalent to an #Embed but from a dynamically generated URLRequest or URL String.
var myImage:Image = new Image();
myImage.source = "http://www.domain.com/img/1234.png";
myImage.width = 16;
myImage.height = 16;
myImage.scaleContent = true;
var myButton:LinkButton = new LinkButton();
myButton.label = "Some text"
// This is what I'm trying to figure out.
myButton.setStyle("icon", ???)
I'm probably missing something obvious - I've tried passing in the URL and myImage separately but both throw errors. Stepping into the setStyle() method shows that the code is expecting a Class - so what do I pass in place of the ???
I can't embed the image itself because it's dynamic - the URL is different each time the software runs.
Thanks for any assistance!
Why not just set the buttonMode of a mx:Image to true then add a click event?
<mx:Image source="{imageSource}" buttonMode="true" click="action()" />
I'm not sure its possible without using an embedded images with a linkButton
This might be worth a read
Edit... in AS3:
var img:Image = new Image();
img.source = "...";
img.buttonMode = true;
img.addEventListenever(MouseEvent.CLICK, funcName);
I think that instead of trying to set the style, you need to change the child object that holds the icon. You can access it by something like:
Var:Bitmap icon = myButton.getChildByName("upIcon") as Bitmap
It should be easy to replace the bitmapData in there with the one from a Loader.
If memory serves, you'll want to use button.setStyle('icon', img), where img is an image loaded via Loader class.
for laalto,
this may be too late of an answer but somebody might find it useful or as a starting point to a solution to your problem. Have you tried referencing your image icon as a class? I don't know if this will work for an image which is in a dynamic URL but this worked for me:
[Embed("assets/LinkButton.png")]
private const linkButtonIcon:Class;
Then in your code:
myButton.setStyle("icon", linkButtonIcon);
See this example here:
http://blog.flexexamples.com/2008/09/03/setting-the-icon-on-a-linkbutton-control-in-flex/
<mx:Button id="example" label="Example" icon="{IconUtility.getClass(example, 'http://www.exampledomain.com/image.jpg')}" />
http://blog.benstucki.net/?p=42

Resources