Flex-iframe: problems in FF - apache-flex

I'm using http://code.google.com/p/flex-iframe/ for showing wikicontent in a flex app.
<?xml version="1.0"?>
<mx:TitleWindow
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:components="components.*"
title="Hjälp"
showCloseButton="true"
close="close();"
styleName="Popup"
paddingBottom="0"
paddingLeft="0"
paddingRight="0"
paddingTop="0"
width="700"
height="500">
<mx:Script>
<![CDATA[
import mx.core.Application;
import mx.managers.PopUpManager;
import offerta.Config;
import offerta.monkeywrench.Icons;
import offerta.utils.printf;
import flash.utils.setTimeout;
import flash.display.DisplayObject;
private static var _popup:HelpPopup = null;
[Bindable]
public var callback:Function;
[Bindable]
public var key:String;
private function close(cancel:Boolean = true):void
{
PopUpManager.removePopUp(this);
if(callback!=null) callback();
}
public static function create():HelpPopup
{
HelpPopup._popup =
HelpPopup(PopUpManager.createPopUp(DisplayObject(Application.application),
HelpPopup, true));
HelpPopup._popup.visible = false;
return HelpPopup._popup;
}
public function show():void
{
PopUpManager.centerPopUp(HelpPopup._popup);
this.visible = true;
setTimeout(function():void {
refresh();
},500);
}
public function refresh():void
{
if(!!key)
{
frameMain.label = key;
frameMain.source = printf(Config.DOCUMENTATION_URL,key);
}
}
]]>
</mx:Script>
<mx:VBox width="100%" height="100%" paddingBottom="0" paddingLeft="0"
paddingRight="0" paddingTop="0">
<mx:ApplicationControlBar width="100%">
<mx:HBox width="100%" id="pnlToolbar" horizontalGap="0">
<mx:LinkButton
icon="{Icons.refresh}"
click="refresh();"/>
<mx:LinkButton
icon="{Icons.previous}"
click="frameMain.historyBack()"/>
<mx:LinkButton
icon="{Icons.next}"
click="frameMain.historyForward()"/>
</mx:HBox>
</mx:ApplicationControlBar>
<components:IFrame id="frameMain"
loadIndicatorClass="components.IFrameLoadingIndicator"
width="100%"
height="100%"/>
</mx:VBox>
<mx:ControlBar>
<mx:Spacer width="100%"/>
<mx:Button
width="80"
height="30"
label="Stäng"
click="close();"/>
</mx:ControlBar>
</mx:TitleWindow>
When displaying the window: In Ie. it works perfectly, but in FF the
content flashes quickly and then the iframe becomes blank?

I answered you on the bug you opened on the project site ;)

I had missed to add wmode=opaque and it works in FF. Only problem is that flex loadingindicator isn't showing.

Related

How is an mx:Canvas measured when inside a renderer in Flex 3?

I'm having a sizing issue with a canvases located inside an HBox. It seems "_graphic", "_border" and "_fill" canvases (in com.example.ThingRenderer.mxml) do not get measured at the same time as all the other measurements inside the renderer. However, this problem is only observed on the first pass-through. Refer to the images for a visual... 1st image shows the state of the app after it finished loading. 2nd image represents what the screen looks like after the Populate button is clicked. 3rd image shows what happens when the stepper is incremented. The question is how come the drawing in the 3rd image doesn't get rendered once the data is populated into the table?
RendererTest.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute"
creationComplete="handleCreationComplete(event)"
>
<mx:Script>
<![CDATA[
import com.example.Thing;
import mx.collections.ArrayCollection;
import mx.events.FlexEvent;
import mx.events.NumericStepperEvent;
private const _thingProvider:ArrayCollection = new ArrayCollection();
private var _thing1:Thing;
protected function handleCreationComplete(event:FlexEvent):void {
_thing1 = new Thing("thingy", 0xff0000, 0.3);
_stepper.value = _thing1.ratio;
}
protected function handlePopulateClick(event:MouseEvent):void {
_thingProvider.addItem(_thing1);
}
protected function handleStepperChange(event:NumericStepperEvent):void {
_thing1.ratio = event.value;
}
]]>
</mx:Script>
<mx:VBox>
<mx:Button label="Populate" click="handlePopulateClick(event)" />
<mx:NumericStepper id="_stepper" minimum="0" maximum="1" stepSize="0.01" change="handleStepperChange(event)" />
<mx:AdvancedDataGrid dataProvider="{_thingProvider}" variableRowHeight="true" width="100%" height="100%">
<mx:columns>
<mx:AdvancedDataGridColumn headerText="Name" dataField="name" />
<mx:AdvancedDataGridColumn headerText="Display"
width="150" sortable="false"
itemRenderer="com.example.ThingRenderer"
/>
</mx:columns>
</mx:AdvancedDataGrid>
</mx:VBox>
</mx:Application>
com.exampleThingRenderer.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas
xmlns:mx="http://www.adobe.com/2006/mxml"
width="100%"
horizontalScrollPolicy="off" verticalScrollPolicy="off"
>
<mx:Script>
<![CDATA[
import mx.binding.utils.ChangeWatcher;
private var _thing:Thing;
private var _ratioWatcher:ChangeWatcher;
private var _doClearContent:Boolean;
private var _doDrawBorder:Boolean;
private var _doUpdateFill:Boolean;
override public function set data(value:Object):void {
if(value && value is Thing) {
_thing = Thing(value);
if(_ratioWatcher) {
_ratioWatcher.unwatch();
}
_ratioWatcher = ChangeWatcher.watch(_thing, "ratio", handleRatioChanged);
_doClearContent = false;
_doDrawBorder = true;
_doUpdateFill = true;
_graphic.invalidateSize();
_border.invalidateSize();
}
else {
_doClearContent = true;
_doDrawBorder = false;
_doUpdateFill = false;
}
super.data = value;
}
private function handleRatioChanged(event:Event):void {
_doUpdateFill = true;
invalidateDisplayList();
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
if(_doClearContent) {
_container.visible = false;
_container.includeInLayout = false;
_doClearContent = false;
}
super.updateDisplayList(unscaledWidth, unscaledHeight);
if(_doDrawBorder) {
trace("_thingContainer.width="+_container.width, "_thingGraphic.width="+_graphic.width, "_thingBorder.width="+_border.width);
_border.graphics.clear();
_border.graphics.moveTo(0, 0);
_border.graphics.lineStyle(1, _thing.color);
_border.graphics.lineTo(_border.width, 0);
_border.graphics.lineTo(_border.width, _border.height);
_border.graphics.lineTo(0, _border.height);
_border.graphics.lineTo(0, 0);
_doDrawBorder = false;
}
if(_doUpdateFill) {
_percentage.text = Math.round(_thing.ratio * 100.0) + "%";
_fill.graphics.clear();
_fill.graphics.beginFill(_thing.color);
_fill.graphics.drawRect(0, 0, _fill.width * _thing.ratio, _fill.height);
_doUpdateFill = false;
}
}
]]>
</mx:Script>
<mx:HBox id="_container" width="100%" paddingLeft="5" paddingTop="5" paddingRight="5" paddingBottom="5">
<mx:Label id="_percentage" width="45" />
<mx:Canvas id="_graphic" width="100%" height="15">
<mx:Canvas id="_border" x="0" y="0" width="100%" height="100%" />
<mx:Canvas id="_fill" x="0" y="0" width="100%" height="100%" />
</mx:Canvas>
</mx:HBox>
</mx:Canvas>
com.example.Thing.as
package com.example {
public class Thing {
[Bindable] public var name:String;
[Bindable] public var color:uint;
[Bindable] public var ratio:Number;
public function Thing(name:String, color:uint, ratio:Number) {
this.name = name;
this.color = color;
this.ratio = ratio;
}
}
}
All this happens because you can't use width and height properties in updateDisplayList, they are not updated yet. Make separate component (e.g. ThingProgressBar) and put drawing logick inside it, that will solve everything:
package
{
import mx.core.UIComponent;
public class ThingProgressBar extends UIComponent
{
private var _ratio:Number;
public function get ratio():Number
{
return _ratio;
}
public function set ratio(value:Number):void
{
_ratio = value;
invalidateDisplayList();
}
override protected function updateDisplayList(
unscaledWidth:Number, unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth, unscaledHeight);
graphics.clear();
if (unscaledWidth > 0 && unscaledHeight > 0)
{
graphics.lineStyle(1, 0xFF0000);
graphics.drawRect(0, 0, unscaledWidth, unscaledHeight);
graphics.beginFill(0xFF0000);
graphics.drawRect(0, 0, unscaledWidth * ratio, unscaledHeight);
graphics.endFill();
}
}
}
}
So your renderer might look like this:
<mx:HBox
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
horizontalScrollPolicy="off" verticalScrollPolicy="off" xmlns:local="*"
>
<fx:Script>
<![CDATA[
[Bindable] private var _thing:Thing;
override public function set data(value:Object):void
{
_thing = value as Thing;
super.data = value;
}
]]>
</fx:Script>
<mx:HBox width="100%"
paddingLeft="5" paddingTop="5"
paddingRight="5" paddingBottom="5">
<mx:Label text="{_thing.name}" width="45" />
<local:ThingProgressBar width="100%" height="15"
ratio="{_thing.ratio}"/>
</mx:HBox>
</mx:HBox>
I removed watcher. Binding by watcher is considered a bad practice, use mxml binding or events instead.
I removed two Canvases with separated border and fill - they can be cobined together.
I used UIComponent instead of Canvas. Don't use containers unless you need layout, they are heavy.
I used HBox instead of Canvas in renderer because I like boxes more :) But you can't avoid using second container in renderer if you need custom styles since List overwrites renderer's stylesheet.

flex mobile TabbedViewNavigatorApplication back button

Why TabbedViewNavigatorApplication don’t have popView() (as in ViewNavigatorApplication I can use popView to go previous view)?
How can I do that in TabbedViewNavigatorApplication?
<fx:Script>
<![CDATA[
protected function BackBtn(event:MouseEvent):void{
navigator.popView(); //error
}
]]>
</fx:Script>
<s:ViewNavigator label="Page1" width="100%" height="100%" firstView="views.DurationView" >
<s:titleContent>
<s:Button label="Back" click="BackBtn(event)"/>
</s:titleContent>
</s:ViewNavigator>
<s:ViewNavigator label="Page2" width="100%" height="100%" firstView="views.FrequencyView"/>
</s:TabbedViewNavigatorApplication>
thanks.
<?xml version="1.0" encoding="utf-8"?>
<s:TabbedViewNavigatorApplication creationComplete="tabbedviewnavigatorapplication1_creationCompleteHandler(event)"
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
import spark.events.IndexChangeEvent;
private var tabHistory : Array;
private var isLoadingFromHistory : Boolean;
protected function BackBtn(event : MouseEvent) : void
{
isLoadingFromHistory = true;
if (tabHistory.length == 0)
{
trace("You can't go back any further");
tabHistory.push(0);
}
tabbedNavigator.selectedIndex = tabHistory.pop();
}
protected function tabbedviewnavigatorapplication1_creationCompleteHandler(event : FlexEvent) : void
{
tabHistory = [];
tabbedNavigator.addEventListener(IndexChangeEvent.CHANGE, tabsChangedHandler);
}
private function tabsChangedHandler(event : IndexChangeEvent) : void
{
if (isLoadingFromHistory)
{
isLoadingFromHistory = false;
return;
}
tabHistory.push(event.oldIndex);
trace(tabHistory);
}
]]>
</fx:Script>
<s:ViewNavigator firstView="views.WhosAtTheDoorHomeView"
height="100%"
label="Page1"
width="100%">
<s:titleContent>
<s:Button click="BackBtn(event)"
label="Back"/>
</s:titleContent>
</s:ViewNavigator>
<s:ViewNavigator firstView="views.WhosAtTheDoorHomeViewCopy"
height="100%"
label="Page2"
width="100%">
<s:titleContent>
<s:Button click="BackBtn(event)"
label="Back"/>
</s:titleContent>
</s:ViewNavigator>
</s:TabbedViewNavigatorApplication>

Displaying images/icons besides y-axis in Flex Bar charts

I am trying to place an image besides the label in y-axis. So I have created a custom label renderer(A HBox containing and ). The source for the image has to be set based on a property present in the data provider. The problem is, I am not able to access the BarSeriesItem in the fnSetSource() method. Any help or pointers is greatly appreciated.
Here's the entire code.
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical"
width="1280" height="750">
<mx:Script><![CDATA[
import mx.collections.ArrayCollection;
import mx.charts.series.items.PlotSeriesItem;
import mx.controls.Label;
import mx.controls.Image;
import mx.containers.HBox;
import mx.charts.series.items.BarSeriesItem;
import mx.charts.series.ColumnSeries;
import mx.charts.series.items.ColumnSeriesItem;
import mx.charts.chartClasses.Series;
import mx.charts.ChartItem;
[Bindable]
public var employeedetails:ArrayCollection = new ArrayCollection([
{rank:"10",emplName:"Peter",prevRank:"7",imgSource:"images/increase.png"},
{rank:"9",emplName:"Mark",prevRank:"3",imgSource:"images/decrease.png"},
{rank:"8",emplName:"Eric",prevRank:"8",imgSource:"images/decrease.png"}
]);
]]>
</mx:Script>
<mx:BarChart id="bar" height="100%"
paddingLeft="15" paddingRight="5"
showDataTips="true" width="847"
dataTipMode="multiple" >
<mx:verticalAxis>
<mx:CategoryAxis id="v1" categoryField="emplName" dataProvider="{employeedetails}"/>
</mx:verticalAxis>
<mx:verticalAxisRenderers>
<mx:AxisRenderer placement="left" axis="{v1}">
<mx:labelRenderer>
<mx:Component>
<mx:HBox width="100%" height="100%" minWidth="120" minHeight="20">
<mx:Image id="axisImage" height="16" width="16" source="fnSetSource()">
<mx:Script><![CDATA[
import mx.charts.chartClasses.Series;
import mx.charts.ChartItem;
import mx.charts.series.items.BarSeriesItem;
[Bindable]
public function fnSetSource(element : ChartItem, series : Series) : String
{
var data : BarSeriesItem = BarSeriesItem(element);
var imgSrc : String = "";
if (data.item.isIncrease)
{
imgSrc = "images/increase.png";
} else if (data.item.isDecrease)
{
imgSrc = "images/decrease.png";
}
else
{
imgSrc = "";
}
return imgSrc;
}
]]></mx:Script>
</mx:Image>
<mx:Label id="axisLabel" fontSize="12" width="100%" height="100%">
<mx:Script><![CDATA[
[Bindable]
override public function set data(value : Object) : void
{
if (value == null)
{
return;
}
var length : int = value.text.toString().length;
if (length > 15)
{
axisLabel.text = value.text.toString().substr(0, 15) + "...";
axisLabel.toolTip = value.text;
}
else
{
axisLabel.text = value.text;
}
}
]]>
</mx:Script>
</mx:Label>
</mx:HBox>
</mx:Component>
</mx:labelRenderer>
</mx:AxisRenderer>
</mx:verticalAxisRenderers>
<mx:series>
<mx:BarSeries id="bs2"
yField="emplName"
xField="rank"
displayName="Rank"
dataProvider="{employeedetails}"
/>
</mx:series>
</mx:BarChart>
</mx:Application>
I had a quick look at the code. The fnSetSource() function will not be called until it is placed inside curly brackets: source="{fnSetSource()}"
This will get the function to be called, but you will get errors because the fnSetSource() call does not have the 2 parameters that fnSetSource function requires. Make the first change I mentioned and you may be able to figure it out from there.
Could you not make an item renderer that is a seperate mxml component?
look like you are not passing any parameters that fnSetSource() needs so it will not work untill you pass those two parameters..
use your function this way
fnSetSource(value:Object,previousValue:Object,axis:IAxis):String

Flex actionscript code for activitylevel

Can any one indicata me a small piece of code for making this progress bar move on mic activitylevel. i.e, When spoken on the microphone the progressbar should indicate it.Also which works on internet explorer
<?xml version="1.0" encoding="utf-8"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute"
width="300"
height="100"
creationComplete="init()">
<mx:Script>
<![CDATA[
import mx.controls.Alert;
import flash.net.NetStream;
private var myMic:Microphone;
private var recordingState:String = "idle";
private function init():void {
myMic = Microphone.getMicrophone();
myMic.setSilenceLevel(0);
myMic.rate = 44;
myMic.gain = 100;
micLevel.visible = true;
Security.showSettings(SecurityPanel.MICROPHONE);
myMic.setLoopBack(true);
if (myMic != null)
{
myMic.setUseEchoSuppression(true);
micLevel.setProgress(myMic.activityLevel, 100);
addEventListener(Event.ENTER_FRAME, showMicLevel);
//micLevel.setProgress(myMic.activityLevel, 100);
}
}
]]>
</mx:Script>
<mx:ProgressBar x="0" y="36" mode="manual" id="micLevel" label="" labelPlacement="bottom" width="100" fontSize="10" fontWeight="normal"/>
</mx:Application>
You need to add a callback function for the event. You have it defined as showMicLevel but you have no implementation of that function.
private function showMicLevel(e: Event):void{
micLevel.setProgress(myMic.activityLevel, 100);
}

Microphone progress bar in action script

Any microphone action script code which indicates a progress bar when there is activity on microphone
here's some code you can use:
it uses the graphics API to draw the indication of volume
<?xml version="1.0" encoding="utf-8"?><mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute"
width="450"
height="450"
creationComplete="creationComplete_Handler()">
<mx:Script>
<![CDATA[
import flash.media.Microphone;
import flash.events.ActivityEvent;
import flash.events.Event;
import flash.events.StatusEvent;
private var _mic:Microphone;
private function creationComplete_Handler():void
{
_mic = Microphone.getMicrophone();
_mic.setLoopBack(true);
_mic.addEventListener(Event.ACTIVATE, mic_ActivateEventHandler);
_mic.addEventListener(StatusEvent.STATUS, mic_StatusEventHandler);
_mic.addEventListener(ActivityEvent.ACTIVITY, mic_ActivityEventHandler);
}
private function mic_ActivateEventHandler(e:Event):void
{
lblStatus.text = "mic active!";
}
private function mic_StatusEventHandler(e:StatusEvent):void
{
trace("ststus event: " + e.toString());
}
private function mic_ActivityEventHandler(e:ActivityEvent):void
{
trace("Activity Event");
addEventListener(Event.ENTER_FRAME, mic_EnterFrame_EventHandler);
}
private function mic_EnterFrame_EventHandler(e:Event):void
{
lblMicLevel.text = "Mic Level :"+_mic.activityLevel.toString();
micLevelCanvas.graphics.clear();
micLevelCanvas.graphics.beginFill(000000, 1);
micLevelCanvas.graphics.drawRect(0, 0, (_mic.activityLevel * 2), 20);
micLevelCanvas.graphics.endFill();
}
]]>
</mx:Script>
<mx:Label x="10" y="10" id="lblStatus"/>
<mx:Canvas x="10" y="36" width="200" height="20" id="micLevelCanvas" />
<mx:Label x="10" y="64" id="lblMicLevel"/></mx:Application>

Resources