Open Webpage in Adobe Flex Desktop Application - actionscript-3

We are developing a small desktop application by using Adobe Flex. In this application, we will have a screen with input box in which user will enter URL of any website and then enter.
After providing URL, the desktop application will open that webpage into the same screen just below the URL input box. Also we want to give an option to capture screenshot of that opened webpage manually(i.e on button click).
When the webpage is open in desktop app, then our screen should be work like browser i.e we can go to any internal page by clicking webpage instead of providing another URL into input box.
We have searched lot of things regarding the same, but nothing got. Can anyone explain us, how can we implement this type of functionality into our desktop application? or Is it possible to make this application using Adobe Flex?
Your solution will be appreciated. Thanks in advance.

You can do that using the HTML control.
Take this example :
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
width="920" height="580">
<fx:Script>
<![CDATA[
protected function btn_history_back_clickHandler(event:MouseEvent):void
{
// history back
html_browser.historyBack();
}
protected function btn_history_forward_clickHandler(event:MouseEvent):void
{
// history forward
html_browser.historyForward()
}
protected function btn_go_clickHandler(event:MouseEvent):void
{
var url:String = txt_url.text;
if(url != '')
{
if(url.substr(0, 4) == 'http')
{
// open the typed url
html_browser.location = url;
}
}
}
protected function html_browser_locationChangeHandler(event:Event):void
{
// update our url text input
txt_url.text = html_browser.location;
}
]]>
</fx:Script>
<mx:HTML id="html_browser" x="6" y="39" width="905" height="511"
locationChange="html_browser_locationChangeHandler(event)"/>
<s:Button id="btn_forward" x="38" y="10" width="28" label=">" click="btn_history_forward_clickHandler(event)"/>
<s:Button id="btn_go" x="858" y="10" width="50" label="GO" click="btn_go_clickHandler(event)"
enabled="true"/>
<s:TextInput id="txt_url" x="74" y="10" width="775"/>
<s:Button id="btn_back" x="10" y="10" width="28" label="<" click="btn_history_back_clickHandler(event)"/>
</s:WindowedApplication>
Which will give you something like this ( it's the same window just I pressed the back button to show the different pages ) :
Of course this is just a very simple example to show you how to start, you can improve and adapt it to your specific needs.
Hope that can help.

Related

ItemRenderer Objects Changing Properties

Apologies for the vague title. I could not think of a better way to word it in so few words.
Basically, I am creating a custom ItemRenderer (IR). The IR has a label on the left side and an icon on the right side. The icon on the right side is dynamic (can be either an add or remove icon or nothing at all). This works beautifully and gives me the control I need over it.
Now, the problem is that when I scroll the list in my mobile application, the icons change.
How it should look:
How it looks after scrolling using a finger (or mouse in emulator) by dragging on Test3:
As you can see, the icons change but the labels do not. I have dragEnabled, dropEnabled, and dragMoveEnabled all set to false on my Spark List component. The only time the icon selection runs is on creationComplete, so there is no way it is choosing a different icon at some point. I can also verify that the data itself is what it should be after this change occurs.
Here is the MXML that creates the item:
<s:HGroup width="100%" verticalAlign="middle" left="{this.sideSpacing}" right="{this.sideSpacing}" top="{this.sideSpacing}" bottom="{this.sideSpacing}">
<s:Label id="text" width="100%"/>
<s:Image id="actionIcon" buttonMode="true" click="actionIconClick( event );">
<s:filters>
<s:DropShadowFilter alpha=".45" angle="90" distance="3" blurX="3" blurY="3" quality="3"/>
</s:filters>
</s:Image>
</s:HGroup>
<s:Rect width="100%" height="1" bottom="0" alpha=".1">
<s:fill>
<s:SolidColor color="#000000"/>
</s:fill>
</s:Rect>
And the possibly over-elaborate AS3 for selecting which icon should be displayed:
private function creationComplete( e:Event ):void {
if ( this.data.actionIcon != null ) {
this.actionIconType = this.data.actionIcon;
if ( this.data.actionIcon == ACTION_ICON_ADD ) {
this.actionIcon.source = this.addBitmapSource;
}
else if ( this.data.actionIcon == ACTION_ICON_REMOVE ) {
this.actionIcon.source = this.removeBitmapSource;
}
else {
this.actionIcon.source = null;
this.actionIcon.visible = false;
this.actionIcon.includeInLayout = false;
}
}
else {
this.actionIcon.source = null;
this.actionIcon.visible = false;
this.actionIcon.includeInLayout = false;
}
}
What could be causing this issue?
Basically, you need to update your renderer's label and icon when the dataChange event is fired. CreationComplete is only fired once. The list isn't really scrolled, just that the data in the itemRenderers change; causing it to look like things are scrolling. I call this renderer recycling.
Here is a component I created for a mobile app that does what you want. It displays a label and an icon (AKA the Decorator). When scrolling the label and icon are both updated. You can use a very similar approach.
<?xml version="1.0" encoding="utf-8"?>
<s:IconItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
dataChange="onDataChange(event)" alpha=".7" width="100%" cacheAsBitmap="true">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import com.dotcomit.magondaMaze.managers.BoardDataManager;
import com.dotcomit.magondaMaze.managers.StatManager;
import mx.events.FlexEvent;
[Embed(source="assets/images/chooseLevel/completed78x78.png")]
private var completedImage:Class;
public var statManager :StatManager = StatManager.instance;
protected function onDataChange(event:FlexEvent):void
{
var itemAsXML :XML = data as XML;
var results :String = itemAsXML.#id + '. ' + itemAsXML.#title;
label = results;
if( statManager.isBoardComplete(itemAsXML.#id)){
this.decorator = completedImage;
} else {
this.decorator = null;
}
}
]]>
</fx:Script>
</s:IconItemRenderer>
I'll also add that the IconItemRenderer component--which my code above extends--is designed to do exactly what you need. So, you may not have to re-write the wheel so to speak.

Constraining number of children in a ViewStack issue

I have the following code to create a ViewStack which is used as a dataprovider for a TabBar:
<s:TabBar id="objectTab" dataProvider="{vs_objects}"/>
<mx:ViewStack id="vs_objects" width="100%" />
I want to constrain the number of children the ViewStack to avvoid the tabs going out of the screen when the user opens many tabs without closing any. I attempt to do this by removing the oldest element in the ViewStack when the user opens a new tab and the size of the ViewStack is above 9.
private function openTab(object:Object): void {
//Create a new NavigatorContent(form) and add it to the ViewStack
........
vs_objects.addChild(form);
if(vs_objects.numChildren > 9) {
vs_objects.removeChildAt(0);
}
//vs_objects.selectedChild = form;
vs_objects.selectedIndex = (vs_Tiltaksbanken.numChildren -1);
}
The image below illustrates my problem, where the dark grey color illustrates the selected Tab. There should only be one selected tab, which works perfectly fine with both the child selection approaches above, when i don't remove a child before selecting a new. When i remove a child and then open a new Tab, the new Tab does not get selected properly, it only gets "painted" in the selected color. In This case Tab 40 is still shown when i open Tab 41 (exceeding 9 tabs). The result of this issue is that Tab 41 is not rendered completely.
Does anyone know how i can fix this problem, or have a different approach for constraining the number of Tab's/ViewStack-children?
UPDATE:
The problem was my AS3 code inside the childrens NavigatorContent's that caused the application to behave this way. The solution was using the callLater method:
The solution to my problem was using the callLater method as shown below with Adnan Doric's code example:
protected function openTab():void
{
var form:Container = new Container();
form.name = "Tab " + counter++;
vs_objects.addChild(form);
vs_objects.selectedChild = form;
callLater(removeTab);
}
private function removeTab(): void {
if (vs_objects.numElements > 10)
vs_objects.removeElementAt(0);
}
Try this, even though I'm not sure it is the correct solution, maybe it's better to implement some kind of scrolling.
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
<fx:Script>
<![CDATA[
import mx.core.Container;
private var counter:int = 1;
protected function openTab():void
{
var form:Container = new Container();
form.name = "Tab " + counter++;
vs_objects.addChild(form);
if (vs_objects.numElements > 10)
vs_objects.removeElementAt(0);
vs_objects.selectedChild = form;
}
]]>
</fx:Script>
<s:TabBar id="objectTab" top="32" labelField="name" dataProvider="{vs_objects}"/>
<mx:ViewStack id="vs_objects" width="100%" />
<s:Button label="addTab" click="openTab()" />
</s:Application>
Hope that helps :)

Flex Element wrongly keeps properties from previous parent - how do I reset it?

I want to put an element into another component (in this case a print template), print it, and then return it to its place. The problem is that when I return it, it has the properties of the print template! Here is a simplified example. When you click print, the label is removed and then returned but when returned it is affected by the padding of the print template! Why? How can I somehow refresh it to its proper properties? I tried all the invalidate... methods and parentChanged() but nothing worked.
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" width="400" height="200">
<fx:Script>
<![CDATA[
import spark.components.VGroup;
protected function button1_clickHandler(event:MouseEvent):void {
var printTemplate:VGroup = new VGroup();
printTemplate.paddingTop = 50;
printTemplate.paddingLeft = 30;
printTemplate.addElement(label);
addElement(printTemplate);
validateNow();
// print
removeElement(printTemplate);
addElement(label);
}
]]>
</fx:Script>
<s:Button label="Print" right="0" click="button1_clickHandler(event)"/>
<s:Label id="label" text="This is the label text, it should appear at the top-left."/>
</s:Application>
I would recommend you to have a separate print view-component which has a separate label which you only need to pass the right data.
OK I hacked up a solution. Put this in before adding the label back to its proper place:
var vg:VGroup = new VGroup();
vg.addElement(label);
addElement(vg);
validateNow();
removeElement(vg);
Then it gets the padding from "vg", which has no padding set. Yay. Another little hack to circumnavigate a Flex bug.

AIR HTML Control Issue (it's not opening links that have attribute target = "_blank")

I've developed Adobe AIR application, which opens cpanel of websites in HTML control. I realized that HTML control open links which opens in same window, however it don't opens the links that opens in new window i.e links which has attribute (target="_blank) like this:
<a href"" target="_blank"> Opens in new window </a>
I've searched the web, although I've got one solution here AIR HTML with “_blank” Links but it opens that links in browsers and its too much old (September 2008). So, anyone know another simple way to open link?
I rewrited example you found to change anchor target, now links are opened in same window. But this method has limitations - only static links are fixed, any JS methods trying to open link in new window will fail.
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication
xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
initialize="init()">
<mx:Script>
<![CDATA[
private function init():void
{
html.htmlText =
"<html><body>" +
"<a href='http://adobe.com' target='_blank'>Adobe (blank)</a><br/>" +
"<a href='http://ixbt.com' target='_self'>iXBT (self)</a>" +
"</body></html>";
html.addEventListener(Event.COMPLETE, onHTMLComplete);
}
private function onHTMLComplete(event:Event):void
{
var document:Object = html.domWindow.document;
for each (var anchor:Object in document.getElementsByTagName("a"))
{
if (anchor.hasOwnProperty("target"))
{
if (anchor.target == "_blank")
{
anchor.target = "_self";
}
}
}
}
]]>
</mx:Script>
<mx:HTML id="html" width="100%" height="100%"/>
</mx:WindowedApplication>

Flex: Linebreak problem with spark.components.TextArea inside a MXDataGridItemRenderer

I have a DataGrid that has a MXDataGridItemRenderer applied as an itemEditor to one of the columns. The editor includes a spark.components.TextArea control.
By default, any text item editor of a datagrid closes itself when [enter] key is pressed..
Keeping this in mind; What I want to do is:
Prevent editor from closing on [SHIFT+ENTER] key but accept the linebreak (I can do this, see code below)
Close the editor on [ENTER] key but do not accept the linebreak (could not achieve this)
Here is the current code in the MXDataGridItemRenderer:
<s:MXDataGridItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
focusEnabled="true"
>
<fx:Script>
<![CDATA[
protected function onTxtDataKeyDown(event:KeyboardEvent):void
{
if (event.keyCode == 13)
{
if (event.shiftKey)
{
//Prevent editor from closing on [SHIFT+ENTER] key but accept the linebreak
event.stopImmediatePropagation(); // » works
}
else
{
//Close the editor on [ENTER] key but do not accept the linebreak
event.preventDefault(); // » does not work
}
}
}
]]>
</fx:Script>
<s:TextArea id="txtData" paddingTop="3" lineBreak="explicit"
text="{dataGridListData.label}"
verticalScrollPolicy="auto" horizontalScrollPolicy="off"
keyDown="onTxtDataKeyDown(event)"
/>
I also tried the textInput event but that did not do the trick.
So: How can I prevent the linebreak when the editor is closed on [enter] key?
Any help is appreciated. Thanks.
EDIT: If I change the spark.components.TextArea to mx.controls.TextArea, second part with event.preventDefault() will work as expected but then the first part where SHIFT+ENTER accepts the linebreak will not work.
According to the API reference keyDown is cancellable only in AIR and not in Flash Player. Which one are you developing for? I was not able to cancel either keyDown or textinput in AIR. Could be a bug. Why don't you log a defect with Adobe and see what they say?
Update: I have confirmed that this is indeed a bug in spark.components.TextArea. The thread http://forums.adobe.com/thread/703195 talks about similar issue.A bug has been logged against Flex as well - http://bugs.adobe.com/jira/browse/SDK-25542.
Workaround is to use mx.controls.TextArea.
I'm not good English. Please see code.
<!--snip-->
<fx:Script>
<![CDATA[
protected function textArea_creationCompleteHandler(event:FlexEvent):void{
textArea.addEventListener(TextOperationEvent.CHANGING,onChangingHandler);
}
//This event is faster than KEY_DOWN.
private function onChangingHandler(event:TextOperationEvent):void {
if(event.operation is SplitParagraphOperation){
//SplitParagraphOperation only cancel.
event.preventDefault();
}
}
]]>
</fx:Script>
<s:TextArea id="textArea"
width="100"
creationComplete="textArea_creationCompleteHandler(event)"
height="60"
/>
<!--snip-->