I'm facing the same problem. Can some explain me with a example?
My code is:
var dataList:ArrayCollection = new ArrayCollection([{name:"alauddn"}, {name:"ansari"}]);
private function getItemInd(event:MouseEvent):void{
var item:Object = new Object();
item.name = "ansari";
var ias:int = dataList.getItemIndex(item);
Alert.show(ias.toString() + ": " + item.name);
}
But it returns "-1:
getItemIndex is not comparing the value within your arrayCollection. The problem is that the getItemIndex() method matches exact object references, not objects with matching properties.
You should use a solution like this instead :
<?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" creationComplete="creationCompleteHandler(event)">
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.controls.Alert;
import mx.events.FlexEvent;
public var dataList:ArrayCollection = new ArrayCollection([{name:"alauddn"}, {name:"ansari"}]);
public function getItemIndexByProperty(array:ArrayCollection, property:String, value:String):Number
{
for (var i:Number = 0; i < array.length; i++)
{
var obj:Object = Object(array[i])
if (obj[property] == value)
return i;
}
return -1;
dataList.getItemIndex();
}
protected function creationCompleteHandler(event:FlexEvent):void
{
var ias:int = getItemIndexByProperty(dataList, "name", "ansari");
Alert.show(ias.toString() + " : " + dataList.getItemAt(ias).name);
}
]]>
</fx:Script>
</s:WindowedApplication>
getItemIndex only searches the root object. So for example this would work:
var dataList:ArrayCollection = new ArrayCollection(["alauddn", "ansari"]);
private function getItemInd(event:MouseEvent):void{
var name:String = "ansari";
var ias:int = dataList.getItemIndex(name);
Alert.show(ias.toString() + ": " + name);
}
You can use this.
private function getItemInd(event:MouseEvent):void{
for each( var item:Object in dataList){
if(item.name == "ansari")
{
var ias:int = dataList.getItemIndex(item);
Alert.show(ias.toString() + ": " + item.name);
break;
}
}
}
Related
I am using a Spark Combobox and a filter function to filter characters in the firstName and lastName. When user types "a" the drop down list is showing all the filtered items with selecting "aram,babu" in the drop down and also showing text as "aram,babu" in the textinput. If the user presses "r", the text input displays "aram,babu", but the drop down list selection disappears. Hitting Enter or clicking the mouse outside the drop down results in the wrong item (last item, i.e. "armu,babu") being selected.
<?xml version="1.0"?>
<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" xmlns:local="*">
<fx:Script><![CDATA[
import mx.collections.ArrayCollection;
private function labelField(item:Object):String {
if (item && item as SalesPerson && item.lastName && item.firstName) {
return item.firstName + "," + item.lastName;
}
return "";
}
private var arr:ArrayCollection;
private var arr1:ArrayCollection;
private var salesPer:SalesPerson;
private function getData():ArrayCollection
{
arr1 = new ArrayCollection();
var salesPerson:SalesPerson = new SalesPerson();
salesPerson.userName = "ravi kumar";
salesPerson.firstName = "ravi";
salesPerson.lastName = "kumar";
var salesPerson1:SalesPerson = new SalesPerson();
salesPerson1.userName = "kiran kumar";
salesPerson1.firstName = "kiran";
salesPerson1.lastName = "kumar";
var salesPerson2:SalesPerson = new SalesPerson();
salesPerson2.userName = "james bond";
salesPerson2.firstName = "james";
salesPerson2.lastName = "bond";
var salesPerson3:SalesPerson = new SalesPerson();
salesPerson3.userName = "ravi babu";
salesPerson3.firstName = "ravi";
salesPerson3.lastName = "babu";
var salesPerson4:SalesPerson = new SalesPerson();
salesPerson4.userName = "rakesh babu";
salesPerson4.firstName = "rakesh";
salesPerson4.lastName = "babu";
var salesPerson5:SalesPerson = new SalesPerson();
salesPerson5.userName = "ramesh babu";
salesPerson5.firstName = "ramesh";
salesPerson5.lastName = "babu";
var salesPerson6:SalesPerson = new SalesPerson();
salesPerson6.userName = "aram babu";
salesPerson6.firstName = "aram";
salesPerson6.lastName = "babu";
var salesPerson7:SalesPerson = new SalesPerson();
salesPerson7.userName = "armu babu";
salesPerson7.firstName = "armu";
salesPerson7.lastName = "babu";
arr1.addItem(salesPerson);
arr1.addItem(salesPerson1);
arr1.addItem(salesPerson2);
arr1.addItem(salesPerson3);
arr1.addItem(salesPerson4);
arr1.addItem(salesPerson5);
arr1.addItem(salesPerson6);
arr1.addItem(salesPerson7);
return arr1;
}
]]></fx:Script>
<s:VGroup width="100%" height="100%">
<local:FilterCombo labelFunction="labelField" dataProvider="{getData()}"/>
</s:VGroup>
</s:Application>
<?xml version="1.0"?>
<s:ComboBox xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" click="clickHandler(event)">
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.collections.IList;
import spark.events.TextOperationEvent;
private var unfilteredDataProvider:IList;
override public function set dataProvider(value:IList):void {
super.dataProvider = value;
unfilteredDataProvider = value;
}
override protected function textInput_changeHandler(event:TextOperationEvent):void {
super.textInput_changeHandler(event);
if (unfilteredDataProvider is ArrayCollection) {
ArrayCollection(unfilteredDataProvider).filterFunction = filterMatches;
ArrayCollection(unfilteredDataProvider).refresh();
super.dataProvider = new ArrayCollection(unfilteredDataProvider.toArray());
}
}
protected function filterMatches(item:Object):Boolean {
if (item && item.lastName && item.firstName) {
if (String(item.lastName + item.firstName).toLowerCase().indexOf(textInput.text.slice(0, textInput.selectionAnchorPosition).toLowerCase()) > -1) {
// trace("traderDoFilter true")
return true;
}
}
return false;
}
private function clickHandler(event:MouseEvent):void {
}
]]>
</fx:Script>
</s:ComboBox>
Basically Combobox search is working based on labelfield, you can see the Combobox framework code.
Verify the below mentioned function:
ComboBox -> processInputField(Function)
if (itemMatchingFunction != null)//itemMatchingFunction allways null untill we assign our callback function
matchingItems = itemMatchingFunction(this, textInput.text);
else
matchingItems = findMatchingItems(textInput.text);//calling by default
So we need to assign our custom callbackfunction to itemMatchingFunction(public)
I have made some changes in your code try this, it has some bugs
<?xml version="1.0" encoding="utf-8"?>
<s:ComboBox xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" click="clickHandler(event)">
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.collections.IList;
import spark.events.TextOperationEvent;
import spark.utils.LabelUtil;
private var unfilteredDataProvider:IList;
namespace mx_internal;
override public function set dataProvider(value:IList):void {
super.dataProvider = value;
this.itemMatchingFunction = itemMatchingFunction1;
}
override protected function textInput_changeHandler(event:TextOperationEvent):void {
super.textInput_changeHandler(event);
if (dataProvider is ArrayCollection) {
ArrayCollection(dataProvider).filterFunction = filterMatches;
ArrayCollection(dataProvider).refresh();
}
}
protected function filterMatches(item:Object):Boolean {
if (item && item.lastName && item.firstName) {
if (String(item.lastName +","+ item.firstName).toLowerCase().indexOf(textInput.text.slice(0, textInput.selectionAnchorPosition).toLowerCase()) > -1) {
return true;
}
}
return false;
}
/**
* #private
*/
// Returns an array of possible values
private function itemMatchingFunction1(comB:ComboBox,input:String):Vector.<int>
{
// For now, just select the first match
var startIndex:int;
var stopIndex:int;
var retVal:int;
var retVector:Vector.<int> = new Vector.<int>;
retVal = findStringLoop(input, 0, dataProvider.length);
if (retVal != -1)
retVector.push(retVal);
return retVector;
}
/**
* #private
*/
function findStringLoop(str:String, startIndex:int, stopIndex:int):Number
{
// Try to find the item based on the start and stop indices.
for (startIndex; startIndex != stopIndex; startIndex++)
{
var itmStr:String = itemToLabel(dataProvider.getItemAt(startIndex));
itmStr = itmStr.substring(0, str.length);
if (str == itmStr || str.toUpperCase() == itmStr.toUpperCase())
{
return startIndex;
}
}
return -1;
}
/**
* Given a data item, return the correct text a renderer
* should display while taking the <code>labelField</code>
* and <code>labelFunction</code> properties into account.
*
* #param item A data item
*
* #return String representing the text to display for the
* data item in the renderer.
*
* #langversion 3.0
* #playerversion Flash 10
* #playerversion AIR 1.5
* #productversion Flex 4
*/
override public function itemToLabel(item:Object):String
{
if (item && item.lastName && item.firstName)
return item.lastName +","+ item.firstName;
return item[labelField];
}
]]>
</fx:Script>
</s:ComboBox>
In actionscript i have multiple dynamic text fields who are loading values from a php page using print.
...
vartxt1.text = receiveVars.phpVar1;
vartxt2.text = receiveVars.phpVar2;
vartxt3.text = receiveVars.phpVar3;
vartxt4.text = receiveVars.phpVar4;
vartxt5.text = receiveVars.phpVar5;
...
which is going very well.
Question: What i'm trying to do is, if let's say the vartxt2 is empty or has a specific value, the text field to be deleted, and the following text fields to be moved up in the place of the one deleted. The text field are one under other.
Thank you very much
Here the code:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="init()">
<mx:Script>
<![CDATA[
import mx.controls.TextInput;
private var txtArr:Dictionary = new Dictionary();
private var size:int;
public function init():void{
var arr:Array = ["aaaaaaa","bbbbbbbb","ccccccc","ddddddddddd","0","ffffffff","eeeeeee","0","ggggg","hhhhhh"];
var i:int = 0;
for each(var obj:String in arr){
var txt:TextInput = new TextInput();
txt.text = obj;
txt.id = "txt" + i.toString();
txtArr[i] = txt;
addChild(txt);
i++;
}
size = i;
}
public function sort():void{
for(var i:int; i < size - 1; i++){
var str:String = TextInput(txtArr[i]).text;
if(str==null || str.length==0 || str=="0"){
TextInput(txtArr[i]).text = TextInput(txtArr[i + 1]).text;
removeChild(txtArr[i]);
}
}
}
]]>
</mx:Script>
<mx:Button id="btn" label="Click Me" click="sort()"/>
</mx:Application>
I hope will be useful. You can dowload the Flex Project here.
I need to export a pie chart and a datagrid in flex 4.5 to Microsoft Excel format. I was able to export the datagrid using as3xls. But it doesn't allow to export any chart or even add an image to excel file. Can anyone recommend me a way of doing this?
As far as I know there is no way to export a chart to Excel by means of existing libraries.
I would like to suggest you one specific way to do it. We all well know that current Office files are stored as collections of XML structures. The files are packed as a zip-archive. If you have a look at this stuff, you can see that it is possible just to manipulate some lines in this files to get any table, any chart, any picture you'd like to have.
To do it in Flex you need basic XML-structures and some library to be able to zip the result.
I have used Nochump component to have access to zip-functions.
Here you can read about the structure of Excel-files.
Here are some pictures which show you a possible result you can achieve with this method.
Regarding the application, you should know which files have to be patched:
sheet1.xml has information about cells of your sheet
sharedStrings.xml is a dictionary of all strings in the file
chart1.xml is a description of your chart - you should change only
ranges of your data.
To get it working I created an XML-structure with description of the Excel-file-tree. The actual XML-files of this file-tree I put to my projects folder. Then I read all the files to an ArrayCollection and manipulated data of three of them.
After all I packed them to a zip-archive and let user save it to the PC.
Here is the source code:
<?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"
creationComplete="onCreationComplete(event)">
<fx:Declarations>
<fx:XML id="fileTree" xmlns="">
<root id=''>
<folder id='_rels'>
<file id='.rels'/>
</folder>
<folder id='docProps'>
<file id='app.xml'/>
<file id='core.xml'/>
</folder>
<folder id='xl'>
<folder id='_rels'>
<file id='workbook.xml.rels'/>
</folder>
<folder id='charts'>
<file id='chart1.xml'/>
</folder>
<folder id='drawings'>
<folder id='_rels'>
<file id='drawing1.xml.rels'/>
</folder>
<file id='drawing1.xml'/>
</folder>
<folder id='theme'>
<file id='theme1.xml'/>
</folder>
<folder id='worksheets'>
<folder id='_rels'>
<file id='sheet1.xml.rels'/>
</folder>
<file id='sheet1.xml'/>
</folder>
<file id='sharedStrings.xml'/>
<file id='styles.xml'/>
<file id='workbook.xml'/>
</folder>
<file id='[Content_Types].xml'/>
</root>
</fx:XML>
</fx:Declarations>
<fx:Script>
<![CDATA[
import flash.utils.ByteArray;
import mx.collections.ArrayCollection;
import mx.collections.XMLListCollection;
import mx.controls.Alert;
import mx.controls.dataGridClasses.DataGridColumn;
import mx.events.FlexEvent;
import mx.rpc.xml.SimpleXMLDecoder;
import nochump.util.zip.*;
private const CELL_LETTERS:String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private var xmlLoader:URLLoader = new URLLoader();
private var loaderItemId:int = 0;
private var rootPath:String = "com/excelchart/xmlsource/";
private var xlsxFiles:ArrayCollection = new ArrayCollection();
[Bindable]private var dp:ArrayCollection = new ArrayCollection([
{party:"SPD", y2009:23, y2005:34.2 },
{party:"CDU", y2009:27.3, y2005:27.8 },
{party:"FDP", y2009:14.6, y2005:9.8 },
{party:"The Left Party", y2009:11.9, y2005:8.7 },
{party:"A90/The Greens", y2009:10.7, y2005:8.1 },
{party:"CSU", y2009:6.5, y2005:7.4 },
{party:"Others", y2009:6, y2005:3.9 }]);
protected function onCreationComplete(event:FlexEvent):void
{
init();
traverseXMLList(fileTree, 0, "");
processNextNode();
}
private function traverseXMLList(xml:XML, depth:int, parentPath:String):void
{
var path:String = (parentPath == "") ? xml.#id : parentPath + "/" + xml.#id;
var nodeType:String = xml.name().localName;
xlsxFiles.addItem({name:xml.#id.toString(), type:nodeType, path:path});
for each (var item:XML in xml.children())
traverseXMLList(item, depth + 1, path);
}
private function packZip():void
{
var zipEntry:ZipEntry;
var fileName:String;
var fileData:ByteArray = new ByteArray();
var zipOut:ZipOutput = new ZipOutput();
for (var i:int = 0; i < xlsxFiles.length; i++)
{
var obj:Object = xlsxFiles.getItemAt(i);
if (obj.type == "file")
{
fileName = obj.path;
zipEntry = new ZipEntry(fileName);
fileData.clear();
fileData.writeUTFBytes(obj.content);
zipOut.putNextEntry(zipEntry);
zipOut.write(fileData);
zipOut.closeEntry();
}
}
// end the zip
zipOut.finish();
var file:FileReference = new FileReference();
file.save(zipOut.byteArray, "chart.xlsx");
}
private function init():void
{
xmlLoader.addEventListener(Event.COMPLETE, onXmlLoaderComplete);
xmlLoader.addEventListener(IOErrorEvent.IO_ERROR, onXmlLoaderIOError);
}
private function loadXML():void
{
xmlLoader.load(new URLRequest(rootPath + xlsxFiles.getItemAt(loaderItemId).path));
}
private function onXmlLoaderComplete(event:Event):void
{
xlsxFiles.getItemAt(loaderItemId).content = (event.currentTarget as URLLoader).data;
processNextNode();
}
private function processNextNode():void
{
if (xlsxFiles.length > loaderItemId + 1)
{
loaderItemId++;
if (xlsxFiles.getItemAt(loaderItemId).type == "file")
loadXML();
else
processNextNode();
}
else
this.btnMakeZip.enabled = true;
}
private function onXmlLoaderIOError(evt:IOErrorEvent):void
{
Alert.show("error!");
}
protected function onMakeZipClick(event:MouseEvent):void
{
parseDataGrid();
packZip();
}
protected function isString(input:String):Boolean
{
return isNaN(Number(input));
}
protected function parseDataGrid():void
{
function getStringId(str:String):int
{
var result:int = -1;
for (var i:int = 0; i < stringDictionary.length; i++)
if (stringDictionary.getItemAt(i) == str)
{
result = i;
break;
}
if (result == -1)
{
stringDictionary.addItem(str);
result = stringDictionary.length - 1;
}
return result;
}
//find sheet1 xml
var sheet1XML:XML;
var xlsxFilesItemId:int;
for (i = 0; i < xlsxFiles.length; i++)
if (xlsxFiles.getItemAt(i).name == "sheet1.xml")
{
sheet1XML = new XML(xlsxFiles.getItemAt(i).content);
xlsxFilesItemId = i;
break;
}
//define the size of the DG
var dgHeight:int = myGrid.dataProvider.length;
var dgWidth:int = myGrid.columns.length;
//namespaces for elements
var mainNS:Namespace = new Namespace("http://schemas.openxmlformats.org/spreadsheetml/2006/main");
var x14acNS:Namespace = new Namespace("x14ac", "http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac");
default xml namespace = mainNS;
sheet1XML.addNamespace(x14acNS);
sheet1XML.dimension.#ref = "A1:" + CELL_LETTERS.charAt(dgWidth) + (dgHeight + 1).toString();
//delete nodes from sheet1XML.sheetData
var sheetDataRowCollection:XMLListCollection = new XMLListCollection(sheet1XML.sheetData.row);
sheetDataRowCollection.removeAll();
//create a String dictionary
var stringDictionary:ArrayCollection = new ArrayCollection();
var stringId:int = 0;
var cellNode:XML, rowNode:XML, value:String, cellAddress:String;
var i:int, j:int;
//add head information
rowNode = new XML();
rowNode.addNamespace(mainNS);
rowNode.addNamespace(x14acNS);
rowNode = <row r="1" spans="1:3"/>;
rowNode.#x14acNS::dyDescent = "0.25";
for (j = 0; j < dgWidth; j++)
{
value = (((myGrid.columns as ArrayList).getItemAt(j) as GridColumn).headerText).toString();
cellAddress = CELL_LETTERS.charAt(j) + "1";
cellNode = new XML();
cellNode = <c r={cellAddress} t="s"><v>{getStringId(value).toString()}</v></c>;
rowNode = rowNode.appendChild(cellNode);
}
sheetDataRowCollection.addItem(rowNode);
//traverse through DG
for (i = 0; i < dgHeight; i++)
{
rowNode = new XML();
rowNode.addNamespace(mainNS);
rowNode.addNamespace(x14acNS);
rowNode = <row r={i + 2} spans="1:3"/>;
rowNode.#x14acNS::dyDescent = "0.25";
for (j = 0; j < dgWidth; j++)
{
value = (myGrid.dataProvider.getItemAt(i)[((myGrid.columns as ArrayList).getItemAt(j) as GridColumn).dataField]).toString();
cellAddress = CELL_LETTERS.charAt(j) + (i+2).toString();
cellNode = new XML();
if (isString(value))
cellNode = <c r={cellAddress} t="s"><v>{getStringId(value).toString()}</v></c>;
else
cellNode = <c r={cellAddress}><v>{value}</v></c>;
rowNode = rowNode.appendChild(cellNode);
}
sheetDataRowCollection.addItem(rowNode);
}
//save sheet1 to xlsxFiles
xlsxFiles.getItemAt(xlsxFilesItemId).content = sheet1XML;
//sharedStrings
var sharedStringsXML:XML;
for (i = 0; i < xlsxFiles.length; i++)
if (xlsxFiles.getItemAt(i).name == "sharedStrings.xml")
{
sharedStringsXML = new XML(xlsxFiles.getItemAt(i).content);
xlsxFilesItemId = i;
break;
}
//delete nodes from sharedStrings.xml
var sharedStringsCollection:XMLListCollection = new XMLListCollection(sharedStringsXML.si);
sharedStringsCollection.removeAll();
//fill the sharedStrings XML
sharedStringsXML.#count = stringDictionary.length;
sharedStringsXML.#uniqueCount = stringDictionary.length;
//var siNode:XML;
for each (var str:String in stringDictionary)
sharedStringsXML.appendChild(<si><t>{str}</t></si>);
//save sharedStrings to xlsxFiles
xlsxFiles.getItemAt(xlsxFilesItemId).content = sharedStringsXML;
//chart1
var chart1XML:XML;
for (i = 0; i < xlsxFiles.length; i++)
if (xlsxFiles.getItemAt(i).name == "chart1.xml")
{
chart1XML = new XML(xlsxFiles.getItemAt(i).content);
xlsxFilesItemId = i;
break;
}
var catLetter:String = CELL_LETTERS.charAt(cbCategories.selectedIndex);
var catAddress:String = "Tabelle1!$" + catLetter + "$2:$" + catLetter + "$" + (dgHeight + 1).toString();
var valLetter:String = CELL_LETTERS.charAt(cbValues.selectedIndex);
var valAddress:String = "Tabelle1!$" + valLetter + "$2:$" + valLetter + "$" + (dgHeight + 1).toString();
default xml namespace = new Namespace("c", "http://schemas.openxmlformats.org/drawingml/2006/chart");
chart1XML.chart.plotArea.pieChart.ser.cat.strRef.f = catAddress;
chart1XML.chart.plotArea.pieChart.ser.val.numRef.f = valAddress;
xlsxFiles.getItemAt(xlsxFilesItemId).content = chart1XML;
//switch back to the default namespace
default xml namespace = new Namespace("");
}
private function onBtnRefresh():void
{
this.mySeries.nameField = cbCategories.selectedItem.dataField;
this.mySeries.field = cbValues.selectedItem.dataField;
}
]]>
</fx:Script>
<s:HGroup x="100" y="50">
<s:VGroup>
<s:DataGrid id="myGrid" width="360" dataProvider="{dp}">
<s:columns>
<s:ArrayList>
<s:GridColumn dataField="party" headerText="Party"/>
<s:GridColumn dataField="y2005" headerText="2005" width="90"/>
<s:GridColumn dataField="y2009" headerText="2009" width="90"/>
</s:ArrayList>
</s:columns>
</s:DataGrid>
<s:HGroup verticalAlign="bottom">
<s:Label text="Categories:" width="70"/>
<s:ComboBox id="cbCategories" dataProvider="{myGrid.columns}" labelField="headerText" selectedIndex="0"/>
</s:HGroup>
<s:HGroup verticalAlign="bottom">
<s:Label text="Values:" width="70"/>
<s:ComboBox id="cbValues" dataProvider="{myGrid.columns}" labelField="headerText" selectedIndex="1"/>
</s:HGroup>
<s:HGroup>
<s:Button id="btnRefresh" label="Bild Chart" click="onBtnRefresh()"/>
<s:Button id="btnMakeZip" label="Export" enabled="false" click="onMakeZipClick(event)"/>
</s:HGroup>
</s:VGroup>
<mx:PieChart id="myChart" width="281" height="277" dataProvider="{dp}" showDataTips="true">
<mx:series>
<mx:PieSeries id="mySeries" field="y2005" nameField="party" labelPosition="inside" explodeRadius=".12" />
</mx:series>
</mx:PieChart>
<mx:Legend dataProvider="{myChart}"/>
</s:HGroup>
</s:Application>
I hope it can help you.
Thanks for the interesting question!
I have a Flex application and need to generate a menu programatically, it will be quite complex and dynamic. What is the best technique for doing this?
UPDATE : I've tested out the code below using objects for the menu items and children properties as RIAstar suggested. This is working except I don't see the "Input" menu, it seems to be bypassed. What I see is:
I was expecting "Add->Input->Device{0..8}".
Thanks for any ideas, Fred.
<?xml version="1.0" encoding="utf-8"?>
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.controls.Menu;
protected function button1_clickHandler(event:MouseEvent):void
{
var toplevelMenu:Object = new Object();
toplevelMenu.label = "Top Level";
var addMenu:Object = new Object();
addMenu.label = "Add";
toplevelMenu.children = addMenu;
var inputMenu:Object = new Object();
inputMenu.label = "Input";
var inputDevicesMenu:ArrayCollection = new ArrayCollection();
for (var i:int = 0;i < 10;i++) {
if ((i % 2) == 0) {
var inputDeviceMenu:Object = new Object();
inputDeviceMenu.label = "Device " + i;
inputDevicesMenu.addItem(inputDeviceMenu);
}
}
if (inputDevicesMenu.length > 0) {
inputMenu.children = inputDevicesMenu;
}
addMenu.children = [inputMenu];
var menu:Menu = Menu.createMenu(this, toplevelMenu, false);
menu.show(event.stageX, event.stageY);
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:Button x="56" y="28" label="Show Menu" click="button1_clickHandler(event)"/>
As per RIAstar suggestion and you code, i have made some modification in button1_clickHandler function: -
Updated code in function button1_clickHandler: -
protected function button1_clickHandler(event:MouseEvent):void
{
var addMenu:Object = new Object();
addMenu.label = "Add";
var inputMenu:Object = new Object();
inputMenu.label = "Input";
var outputMenu:Object = new Object();
outputMenu.label = "Output";
var inputOutputDevicesMenu:ArrayCollection = new ArrayCollection();
inputOutputDevicesMenu.addItem(outputMenu);
inputOutputDevicesMenu.addItem(inputMenu);
addMenu.children = inputOutputDevicesMenu;
var inputDevicesMenu:ArrayCollection = new ArrayCollection();
for (var i:int = 0;i < 10;i++) {
if ((i % 2) == 0) {
var inputDeviceMenu:Object = new Object();
inputDeviceMenu.label = "Device " + i;
inputDevicesMenu.addItem(inputDeviceMenu);
}
}
if (inputDevicesMenu.length > 0) {
inputMenu.children = inputDevicesMenu;
}
var menu:Menu = Menu.createMenu(this, addMenu, true);
menu.show(event.stageX, event.stageY);
}
Hope this may help to get some idea......
I am trying to create a custom progress bar which has common functionality implemented like twining and setting the total value etc.,
Every thing seems to be working but for some reason, percentComplete is always 0 instead of increasing the value even when I call setProgress()
Update1:
Also, the tweener is not calling the onUpdate function (old code)
Update2:
If I modified the onUpdate function like this, onComplete is called but onUpdateProgress is called only once
onUpdate:this.onUpdateProgress(getTimer()),
Old code (call to function from inside anonymous function)
onUpdate:function():void{this.onUpdateProgress(getTimer());}
This is my custom Progressbar mxml:
<?xml version="1.0" encoding="utf-8"?>
<mx:ProgressBar xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
indeterminate="false" labelPlacement="center" fontWeight="bold" textDecoration="none" fontStyle="normal" textAlign="center"
chromeColor="0xFFFFFF" mode="manual"
>
<fx:Script>
<![CDATA[
import caurina.transitions.Tweener;
import flash.utils.getTimer;
public var cancel:Boolean = false;
public const MESSAGE_TYPE_DELETE:String = "Delete";
public const MESSAGE_TYPE_REMOVE:String = "Remove";
public const MESSAGE_TYPE_COLLECT:String = "Collect";
public const MESSAGE_TYPE_MAINTAIN:String = "Maintain";
public const MESSAGE_TYPE_BUILD:String = "Build";
public const MESSAGE_TYPE_CONSTRUCT:String = "Construct";
private var _orgMessage:String;
private var _newMessage:String;
private var _completeMessage:String;
private var _lastValue:uint;
private var _tweenCompleted:Boolean;
private function onUpdateProgress(value:Number):void{
var txt:String;
if (!cancel){
Update3:
Below is where I am setting the progress
this.setProgress(value,_lastValue);
if (value == _lastValue){
txt = _completeMessage;
_tweenCompleted = true;
}else{
txt = _newMessage;
}
label = txt + ":" + int(this.percentComplete).toString() + "%";
trace(value,_lastValue,this.percentComplete);
}
}
private function onComplete():void{
_tweenCompleted = true;
label = _completeMessage + ": 100%";
trace("completed");
}
public function startProgress(message:String,duration:int = 2):void{
_tweenCompleted = false;
_lastValue = getTimer() + duration * 1000;
_newMessage = ((message.charAt(message.length - 1) == "e")?message.substr(0,message.length - 1):message) + "ing";
_completeMessage = "Completed";
Tweener.addTween(this,
{
time:duration,
onUpdate:function():void{this.onUpdateProgress(getTimer());},
onComplete:this.onComplete(),
transition:"liner"
}
);
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
</mx:ProgressBar>
Main mxml
protected function startProgress(event:MouseEvent):void
{
this.removeAllElements();
pb = null;
pb = new FGProgressBar();
this.addElement(pb);
pb.startProgress("Remove",5);
}
I have trace commands in the onUpdateProgress()
trace(value,_lastValue,this.percentComplete);
value is the current progress value, which I am passing getTimer()
_lastValue is the total value of the progress bar, this is set in the initialzation (getTimer() + duration * 1000)
percentComplete is the progress status which should increase after setProgress()
its priting something like this
.
.
.
.
.
5162 8130 0
5210 8130 0
5244 8130 0
5754 8130 0
6262 8130 0
6771 8130 0
7279 8130 0
7787 8130 0
8295 8130 0
If you notice the trace, the value is incrementing, but the percentComplete is 0
Can someone tell me what I am missing?
I have used Flex SDK 4.6.0 and code works for me:
FGProgressBar.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:ProgressBar xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
indeterminate="false" labelPlacement="center" fontWeight="bold" textDecoration="none" fontStyle="normal" textAlign="center"
chromeColor="0xFFFFFF" mode="manual"
>
<fx:Script>
<![CDATA[
import caurina.transitions.Tweener;
import flash.utils.getTimer;
public var cancel:Boolean = false;
public const MESSAGE_TYPE_DELETE:String = "Delete";
public const MESSAGE_TYPE_REMOVE:String = "Remove";
public const MESSAGE_TYPE_COLLECT:String = "Collect";
public const MESSAGE_TYPE_MAINTAIN:String = "Maintain";
public const MESSAGE_TYPE_BUILD:String = "Build";
public const MESSAGE_TYPE_CONSTRUCT:String = "Construct";
private var _orgMessage:String;
private var _newMessage:String;
private var _completeMessage:String;
private var _lastValue:uint;
private var _tweenCompleted:Boolean;
private function onUpdateProgress(value:Number):void{
var txt:String;
if (!cancel){
this.setProgress(value,_lastValue);
if (value == _lastValue){
txt = _completeMessage;
_tweenCompleted = true;
}else{
txt = _newMessage;
}
label = txt + ":" + int(this.percentComplete).toString() + "%";
trace(value,_lastValue,this.percentComplete);
}
}
private function onComplete():void{
_tweenCompleted = true;
label = _completeMessage + ": 100%";
trace("completed");
}
public function startProgress(message:String,duration:int = 2):void{
_tweenCompleted = false;
_lastValue = getTimer() + duration * 1000;
_newMessage = ((message.charAt(message.length - 1) == "e")?message.substr(0,message.length - 1):message) + "ing";
_completeMessage = "Completed";
Tweener.addTween(this,
{
time:duration,
onUpdate:function():void{this.onUpdateProgress(getTimer());},
onComplete:this.onComplete(),
transition:"liner"
}
);
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
</mx:ProgressBar>
Main.mxml
<?xml version="1.0"?>
<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"
height="600">
<fx:Script><![CDATA[
protected function startProgress(event:MouseEvent):void
{
this.removeAllElements();
var pb:FGProgressBar = null;
pb = new FGProgressBar();
this.addElement(pb);
pb.startProgress("Remove",5);
}
]]></fx:Script>
<s:Button click="startProgress(event)"/>
</s:Application>
Try to set mode="manual"
ex
<mx:ProgressBar
id = "idPercent"
labelPlacement = "center"
mode = "manual"/>