Differences between stopPropagation() and stopImmediatePropagation() in Flex - actionscript-3

I am working on event handling in flex.
I need to stop event propagation of an event on a node.
I found no difference between stopPropagation() and stopImmediatePropagation().
Is there any difference between these functions?
<?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"
initialize="init(event);">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<fx:Script>
<![CDATA[
import flash.events.Event;
import flash.events.MouseEvent;
import mx.controls.Alert;
public function init(e:Event):void {
var object:Object
p1.addEventListener(MouseEvent.MOUSE_DOWN, showAlert);
tw1.addEventListener(MouseEvent.MOUSE_DOWN, showAlert);
tw1.addEventListener(MouseEvent.MOUSE_UP, showAlert);
btn.addEventListener(MouseEvent.MOUSE_DOWN, showAlert);
btn.addEventListener(MouseEvent.MOUSE_UP, showAlert);
}
private function showAlert(e:Event):void {
trace("stopPropagation !\n" + "Current Target: " + e.currentTarget + "\n"+ "Target: " + e.target + "\n" +"Type: " + e.type);
//e.stopImmediatePropagation();
e.stopPropagation();
}
]]>
</fx:Script>
<s:Panel id="p1" title="Stops Propagation">
<mx:TitleWindow id="tw1"
width="300"
height="100"
showCloseButton="true"
title="Title Window 1">
<s:Button id="btn" label="Click Me"/>
<s:TextArea id="ta1"/>
</mx:TitleWindow>
</s:Panel>
</s:Application>

event.stopImmediatePropagation() - completely stops the event. No other listener will receive a call for that event.
event.stopPropagation() - prevents moving event to the next display list node but allow invoking listeners on the currentTarget object (if they exists).
See slightly modified your code:
<?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"
initialize="init(event);">
<fx:Script>
<![CDATA[
public function init(e:Event):void {
var object:Object
p1.addEventListener(MouseEvent.MOUSE_DOWN, showAlert);
tw1.addEventListener(MouseEvent.MOUSE_DOWN, showAlert);
btn.addEventListener(MouseEvent.MOUSE_DOWN, showAlert);
}
private function showAlert(e:Event):void {
trace("Event: " + e.type + "; Phase: " + e.eventPhase +"; Target: " + e.target.name + "; Current Target: " + e.currentTarget.name);
}
]]>
</fx:Script>
<s:Panel id="p1" title="Stops Propagation">
<mx:TitleWindow id="tw1"
showCloseButton="true"
title="Title Window 1">
<s:Button id="btn" label="Click Me"/>
<s:TextArea id="ta1"/>
</mx:TitleWindow>
</s:Panel>
</s:Application>
Output:
Event: mouseDown; Phase: 2; Target: btn; Current Target: btn
Event: mouseDown; Phase: 3; Target: btn; Current Target: TitleWindow14
Event: mouseDown; Phase: 3; Target: btn; Current Target: Panel5
First you receive the event on Button in Targeting phase (eventPhase=2) and then on TitleWindow and Panel in Bubbling phase (eventPhase=3).
If you modify event listener like:
private function showAlert(e:Event):void {
trace("Event: " + e.type + "; Phase: " + e.eventPhase +"; Target: " + e.target.name + "; Current Target: " + e.currentTarget.name);
trace("stopPropagation()");
e.stopPropagation();
}
Output:
Event: mouseDown; Phase: 2; Target: btn; Current Target: btn
stopPropagation()
Or:
private function showAlert(e:Event):void {
trace("Event: " + e.type + "; Phase: " + e.eventPhase +"; Target: " + e.target.name + "; Current Target: " + e.currentTarget.name);
trace("stopImmediatePropagation()");
e.stopImmediatePropagation();
}
You will get the same result:
Event: mouseDown; Phase: 2; Target: btn; Current Target: btn
stopImmediatePropagation()
It is because stopPropagation() and stopImmediatePropagation() are prevent event to go into the next phase (Bubbling).
To see difference between these methods you need to have two event listeners on the button 'btn':
<?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"
initialize="init(event);">
<fx:Script>
<![CDATA[
public function init(e:Event):void {
var object:Object
p1.addEventListener(MouseEvent.MOUSE_DOWN, showAlert);
tw1.addEventListener(MouseEvent.MOUSE_DOWN, showAlert);
btn.addEventListener(MouseEvent.MOUSE_DOWN, showAlert);
btn.addEventListener(MouseEvent.MOUSE_DOWN, showAlert2);
}
private function showAlert(e:Event):void {
trace("showAlert(): Event: " + e.type + "; Phase: " + e.eventPhase +"; Target: " + e.target.name + "; Current Target: " + e.currentTarget.name);
trace("showAlert(): stopPropagation()"); e.stopPropagation() // 1
//trace("showAlert(): stopImmediatePropagation()"); e.stopImmediatePropagation(); // 2
}
private function showAlert2(e:Event):void {
trace("showAlert2(): Event: " + e.type + "; Phase: " + e.eventPhase +"; Target: " + e.target.name + "; Current Target: " + e.currentTarget.name);
}
]]>
</fx:Script>
<s:Panel id="p1" title="Stops Propagation">
<mx:TitleWindow id="tw1"
showCloseButton="true"
title="Title Window 1">
<s:Button id="btn" label="Click Me"/>
<s:TextArea id="ta1"/>
</mx:TitleWindow>
</s:Panel>
</s:Application>
For stopPropagation() result is:
showAlert(): Event: mouseDown; Phase: 2; Target: btn; Current Target: btn
showAlert(): stopPropagation()
showAlert2(): Event: mouseDown; Phase: 2; Target: btn; Current Target: btn
For stopImmediatePropagation() result is:
showAlert(): Event: mouseDown; Phase: 2; Target: btn; Current Target: btn
showAlert(): stopImmediatePropagation()
As you can see stopPropagation() has allowed to receive mouseDown event for the second listener showAlert2().
At the same time stopImmediatePropagation() has prevented a call of showAlert2().

Related

Centered Fixed Marker on Xamarin.Forms.Maps

I'm trying to integrate a map on Xamarin.Forms that when opened, a fixed marker is placed on the center of the map. By fixed, I mean it does not move when the map is dragged and the marker itself is also not draggable. Can somebody guide me through this or do you have any reference that I can read on? I already have the map displayed.
Don't add a marker to the map, but instead overlay the map with a view on top of it.
I had this same problem and after searching for very long, I finally combined some parchments and logic to arrive at a solution that FINALLY WORKED. I posted a COMPLETE SOLUTION to the Centred Marker problem on Github, here is the link.
https://github.com/amay077/Xamarin.Forms.GoogleMaps/issues/486
but for the purpose of redundancy (in case you can't find the post for one reason or the other), here is the solution
<AbsoluteLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<StackLayout x:Name="PanelMain" AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0,0,1,1">
<StackLayout HorizontalOptions="CenterAndExpand" VerticalOptions="Start">
<StackLayout HorizontalOptions="FillAndExpand" Orientation="Vertical" VerticalOptions="Start" Padding="10,0,10,0">
<Label x:Name="lblTotal" FontSize="14" TextColor="Black" FontAttributes="Bold" HorizontalTextAlignment="Center" Text="[Address Show Here]" />
<Label x:Name="lblCoordinates" VerticalTextAlignment="Center" FontSize="12" HorizontalTextAlignment="Center" Text="[GPS Coordinates]" />
<SearchBar x:Name="SearchTextBox" TextColor="Black" HorizontalOptions="FillAndExpand" CancelButtonColor="Red" SearchButtonPressed="SearchTextBox_SearchButtonPressed" Placeholder="Search for Destination"></SearchBar>
<ActivityIndicator IsVisible="False" x:Name="MyActivityIndicator" Color="#039763" IsRunning="False"></ActivityIndicator>
</StackLayout>
</StackLayout>
<StackLayout x:Name="mystacklayout" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
</StackLayout>
<StackLayout BackgroundColor="White" Orientation="Vertical" HorizontalOptions="FillAndExpand">
<StackLayout BackgroundColor="White" Orientation="Vertical" HorizontalOptions="FillAndExpand" Padding="10">
<synbtn:SfButton x:Name="cmdGetCoordinateDestination" CornerRadius="7" BackgroundColor="#E66C2C" BorderColor="#039763" HasShadow="False" TextColor="White" FontSize="14" HeightRequest="42" Text="Get GPS Coordinates" Clicked="cmdGetCoordinateDestination_Clicked"></synbtn:SfButton>
<synbtn:SfButton x:Name="cmdSUBMIT" CornerRadius="7" IsVisible="False" IsEnabled="True" BorderColor="LightGray" HasShadow="False" BackgroundColor="#039763" TextColor="White" FontSize="16" HeightRequest="45" Text="SUBMIT REPORT" Clicked="CreateAccountClicked"></synbtn:SfButton>
<!--<Label x:Name="lbldistance" Text="Within 50 Kilometers (KM)" HorizontalTextAlignment="Center" TextColor="Black" FontSize="11" />
<syncslider:SfRangeSlider x:Name="theSlider" HeightRequest="60" ShowRange="False" SnapsTo="StepValues" StepFrequency="20" Orientation="Horizontal" HorizontalOptions="CenterAndExpand" TickPlacement="Inline" ValueChangeMode="Default" Minimum="0" Maximum="300" Value="50" ValueChanging="theSlider_ValueChanging"></syncslider:SfRangeSlider>-->
</StackLayout>
</StackLayout>
</StackLayout>
<StackLayout x:Name="mycentremarker_layout" IsVisible="True" Padding="12"
AbsoluteLayout.LayoutFlags="PositionProportional"
AbsoluteLayout.LayoutBounds="0.5,0.5,-1,-1">
</StackLayout>
</AbsoluteLayout>
Now, combine this with some C# code for adding and initializing the Xamarin.Forms.Map and the Centre Marker Icon to the page
private async void PrepareMap()
{
try
{
var request = new GeolocationRequest(GeolocationAccuracy.Medium);
var location = await Geolocation.GetLocationAsync(request).ConfigureAwait(true);
if (location != null)
{
App.lastlatitude = location.Latitude; //double.Parse("8.13463");
App.lastlongitude = location.Longitude; //double.Parse("-13.30254");
}
if (App.lastlatitude != 0)
{
var position = new Position(App.lastlatitude, App.lastlongitude);
customMap = new CustomMap
{
MapType = MapType.Street,
IsShowingUser = true,
WidthRequest = 100,
HeightRequest = 100,
VerticalOptions = LayoutOptions.FillAndExpand
};
customMap.MapType = MapType.Street;
customMap.TrafficEnabled = true;
if (mystacklayout.Children.Any())
{
mystacklayout.Children.Clear();
}
mystacklayout.Children.Add(customMap);
customMap.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(App.lastlatitude, App.lastlongitude), Distance.FromMiles(5)));
customMap.IsShowingUser = true;
TheCoordinates = App.lastlatitude + ", " + App.lastlongitude;
var thelatdecimal = App.lastlatitude.ToString().Split('.')[1];
var thelongdecimal = App.lastlongitude.ToString().Split('.')[1];
if (thelatdecimal.Length > 5)
{
thelatdecimal = thelatdecimal.Substring(0, 5);
}
if (thelongdecimal.Length > 5)
{
thelongdecimal = thelongdecimal.Substring(0, 5);
}
var thelat = App.lastlatitude.ToString().Split('.')[0] + "." + thelatdecimal;
var thelong = App.lastlongitude.ToString().Split('.')[0] + "." + thelongdecimal;
lblCoordinates.Text = thelat + ", " + thelong;
AddTheCentreMarker();
}
}
catch (Exception ex)
{
await DisplayAlert("Error", ex.Message, "OK").ConfigureAwait(true);
}
}
private async void AddTheCentreMarker()
{
try
{
Image _imgMarker = new Image(); //marker holder declaration
int int_markerSize; //marker sizer
_imgMarker.Source = Device.OnPlatform(
iOS: ImageSource.FromUri(new Uri("http://www.launchappy.com/images/Marker.png")),
Android: ImageSource.FromFile("Marker.png"),
WinPhone: ImageSource.FromFile("Marker.png"));
_imgMarker.VerticalOptions = LayoutOptions.CenterAndExpand;
int_markerSize = 20;
_imgMarker.WidthRequest = int_markerSize;
_imgMarker.HeightRequest = int_markerSize;
mycentremarker_layout.Children.Add(_imgMarker);
}
catch (Exception ex)
{
throw;
}
}
Hope this helps to solve the problem

Listing huge amount files and directories include subdirectories in Adobe AIR

I am trying to list files and directories and copy all files existing into any other folder.
By the way, there are many files and directories more than 1000 000+.
Here is a part of code.
private function getFileList(sourceDir:String):void{
var file:File = File.userDirectory.resolvePath(sourceDir);
file.addEventListener(FileListEvent.DIRECTORY_LISTING, directory_listing);
file.getDirectoryListingAsync();
}
private function directory_listing(e:FileListEvent):void{
var getfiles:Array = e.files;
for each(var item:File in e.files){
if(checkDir(item.nativePath)){
// It is a directory, more logic!
totalDirNum++;
item.addEventListener(FileListEvent.DIRECTORY_LISTING, directory_listing);
item.getDirectoryListingAsync();
}
else{
// It is a file, more logic!
totalFileNum++;
if(analyzeFile(item) === true){
if(overwriteChk.selected === false){ // Don't overwrite same file
if(checkFile(destinationDir.nativePath + "\\" + item.name) === false){
copyInto(item, destinationDir.resolvePath(destinationDir.nativePath + "\\" + item.name));
copiedNum++;
}
else uncopiedNum++;
}
else{ // Overwrite same file
copyInto(item,destinationDir.resolvePath(destinationDir.nativePath + "\\" + item.name));
copiedNum++;
}
}
else{
skippedNum++;
}
}
}
As you see, it executes recursive directory_listing().
In case of little files and directories, it works clearly.
But, for example, in the following case it not works clearly(appear not responding.)
Root Directory : A!
A includes 500 000+ subdirectories.
Each subdirectories include 4 or 5 files and one or two subdirectories.
And also the subdirectoy include a 4 or 5 files.
So, I need to copy all files of "A" folder to the specific folder (B!).
Program is stopped in first before loop. i.e. Named "A" folder include huge subfolders, so when program run to select a "A" folder, then it is stopped just in "A" folder listing(stopped at getDirectoryListingAsyc()). So, actually it is not called recursive.
Here is my full source code.
<?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="800" height="600"
title="eveningCopier - Niao Jina"
creationComplete="initApp()">
<fx:Script>
<![CDATA[
import mx.controls.Alert;
public var sourceDir:File;
public var destinationDir:File;
public var totalDirNum:uint;
public var totalFileNum:uint;
public var copiedNum:uint;
public var skippedNum:uint;
public var uncopiedNum:uint;
public var startTime:String;
public var finishTime:String;
/**
* Boot Function
**/
public function initApp():void{
sourceBtn.addEventListener(MouseEvent.CLICK, click_sourceBtn);
destinationBtn.addEventListener(MouseEvent.CLICK, click_destinationBtn);
startBtn.addEventListener(MouseEvent.CLICK, click_startBtn);
totalDirNum = 0;
totalFileNum = 0;
copiedNum = 0;
skippedNum = 0;
uncopiedNum = 0;
}
/**
* Event Listener when click "Source" button
**/
protected function click_sourceBtn(e:MouseEvent):void{
sourceDir = new File();
sourceDir.addEventListener(Event.SELECT, select_source);
sourceDir.browseForDirectory("Please select a source directory...");
}
private function select_source(evt:Event):void {
sourceTxt.text = sourceDir.nativePath;
}
/**
* Event Listener when click "Destination" button
**/
protected function click_destinationBtn(e:MouseEvent):void{
destinationDir = new File();
destinationDir.addEventListener(Event.SELECT, destination_select);
destinationDir.browseForDirectory("Please select a source directory...");
}
private function destination_select(evt:Event):void {
destinationTxt.text = destinationDir.nativePath;
}
/**
* Event Listener when click "Start" button
**/
protected function click_startBtn(e:MouseEvent):void{
if(sourceTxt.text == "") Alert.show("Please select a source directory", "Warning");
else if(destinationTxt.text == "") Alert.show("Please select a destination directory", "Warning");
if(checkDir(sourceTxt.text) === false) Alert.show("A selected Source folder:\n" + sourceTxt.text + "\n is not exist. Please check!", "Warning");
else if(checkDir(destinationTxt.text) === false) Alert.show("A selected Destination folder:\n" + destinationTxt.text + "\n is not exist. Please check!", "Warning");
//Alert.show(checkFile("D:\\New Folder\\f.txt").toString());
//Alert.show(checkDir("D:\\New Folder\\f.txt").toString());
workedTextArea.text = "";
currentLabel.text = "";
timeLabel.text = "";
totalDirLabel.text = "";
totalFileLabel.text = "";
copiedLabel.text = "";
skippedLabel.text = "";
uncopiedLabel.text = "";
totalDirNum = 0;
totalFileNum = 0;
copiedNum = 0;
skippedNum = 0;
uncopiedNum = 0;
startTime = getNow() + "\n";
getFileList(sourceTxt.text);
}
/**
* Get a current date and time as format - YYYY-MM-DD HH:II:SS
*
* #return String
**/
public function getNow():String{
var now:Date = new Date();
return now.getFullYear() + "-" + now.getMonth() + "-" + now.getDate() + " " + now.getHours() + ":" + now.getMinutes() + ":" + now.getSeconds();
}
/**
* Check if the directory is exist.
* #param dirName:String Path of the directory
* #return Boolean true or false
**/
private function checkDir(dirName:String):Boolean{
var dir:File = File.userDirectory.resolvePath(dirName);
return dir.isDirectory;
}
/**
* Check if the file is exist.
* #param fileName:String Path of the file
* #return Boolean true or false
**/
private function checkFile(fileName:String):Boolean{
var file:File = File.userDirectory.resolvePath(fileName);
return file.exists;
}
/**
* Ananlyze a structure of files and directory
* If is a folder, loop in its subfolder.
* If is a file, copy to the destination folder
*
* #param sourceDir:String
**/
private function getFileList(sourceDir:String):void{
var file:File = File.userDirectory.resolvePath(sourceDir);
file.addEventListener(FileListEvent.DIRECTORY_LISTING, directory_listing);
file.getDirectoryListingAsync();
}
private function directory_listing(e:FileListEvent):void{
var getfiles:Array = e.files;
for each(var item:File in e.files){
trace(item.nativePath);
currentLabel.text = "Latest In : " + item.nativePath;
if(checkDir(item.nativePath)){
// It is a directory, more logic!
totalDirNum++;
item.addEventListener(FileListEvent.DIRECTORY_LISTING, directory_listing);
item.getDirectoryListingAsync();
}
else{
// It is a file, more logic!
totalFileNum++;
if(analyzeFile(item) === true){
if(overwriteChk.selected === false){ // Don't overwrite same file
if(checkFile(destinationDir.nativePath + "\\" + item.name) === false){
copyInto(item, destinationDir.resolvePath(destinationDir.nativePath + "\\" + item.name));
copiedNum++;
}
else uncopiedNum++;
}
else{ // Overwrite same file
copyInto(item, destinationDir.resolvePath(destinationDir.nativePath + "\\" + item.name));
copiedNum++;
}
}
else{
skippedNum++;
}
}
}
finishTime = getNow();
timeLabel.text = startTime + finishTime;
totalDirLabel.text = "Total Dir : " + totalDirNum;
totalFileLabel.text = "Total Files : " + totalFileNum;
copiedLabel.text = "Copied Files : " + copiedNum;
skippedLabel.text = "Skipped Files : " + skippedNum;
uncopiedLabel.text = "Uncopied Files : " + uncopiedNum;
}
/**
* Copy files
* #param sourceFilePointer:File
* #param destinationDirPointer:File
* #return void
**/
private function copyInto(sourceFilePointer:File, destinationDirPointer:File):void{
sourceFilePointer.copyTo(destinationDirPointer, true);
if(logsChk.selected === true)
workedTextArea.text += sourceFilePointer.nativePath + "\n";
}
private function analyzeFile(filePointer:File):Boolean{
//Alert.show(filePointer.extension + "\n" + filePointer.size + "\n" + filePointer.name.indexOf("#"));
if((filePointer.extension) == null && (filePointer.size/1024 > 2) && (filePointer.name.indexOf("#") == -1))
return true;
else
return false;
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:BorderContainer width="100%" height="100%">
<s:VGroup width="90%" height="5%" left="0">
<s:HGroup width="100%">
<s:Button id="sourceBtn" label="Source"/>
<s:TextInput id="sourceTxt" width="90%" fontSize="11"/>
</s:HGroup>
<s:HGroup width="100%">
<s:Button id="destinationBtn" label="Destination"/>
<s:TextInput id="destinationTxt" width="90%" fontSize="11"/>
</s:HGroup>
</s:VGroup>
<s:Button id="startBtn" label="Start" height="48" top="0" right="0"/>
<s:HGroup top="50" width="100%">
<s:Label id="currentLabel" width="90%" height="19" text="Latest In : "
textAlign="left" verticalAlign="middle"/>
<s:CheckBox id="overwriteChk" label="Overwrite" selected="false"/>
<s:CheckBox id="logsChk" label="Logs" selected="false"/>
</s:HGroup>
<s:TextArea id="workedTextArea" x="0" top="77" width="100%" height="90%" editable="false"/>
<s:HGroup width="100%" height="5%" bottom="0">
<s:Label id="timeLabel" width="20%" height="100%" textAlign="center" verticalAlign="middle" fontSize="11"/>
<s:Label id="totalDirLabel" width="16%" height="100%" textAlign="center" verticalAlign="middle"/>
<s:Label id="totalFileLabel" width="16%" height="100%" textAlign="center" verticalAlign="middle"/>
<s:Label id="copiedLabel" width="16%" height="100%" textAlign="center" verticalAlign="middle"/>
<s:Label id="skippedLabel" width="16%" height="100%" textAlign="center" verticalAlign="middle"/>
<s:Label id="uncopiedLabel" width="16%" height="100%" textAlign="center" verticalAlign="middle"/>
</s:HGroup>
</s:BorderContainer>
</s:WindowedApplication>
Your problem lies within the execution time. If you're trying to perform everything in one go it will use all the CPU it can get. If one thread is being executed for longer than X seconds (usually 15), flash will abort it saying it takes too much.
Before starting your loop, take a timestamp with getTimer() and in the loop, in the beginning of your loop check if the startTimestamp - currentTimestamp is less than 5000 (5 seconds). If it is, break the array and start it over (with or without delay, flash will allow it) from the place you've left.
For this type of operations it would make sense to use workers, check this.
Here's an abstract example:
var counter:int = 0; // our progress
var startTime:int;
function increaseCounter():void
{
startTime = getTimer();
while(true) // infinite loop
{
if (getTimer() - startTime > 5000)
{
increaseCounter();
break;
}
counter++;
if (counter >= int.MAX_VALUE) // our custom loop exit
{
trace(counter);
break;
}
}
}
Though this thread seems to be quite old but I am posting a working code here which I wrote for searching files with given search string. It goes through all subfolders and pretty fast to respond in comparison to File.getDirectoryListing()
Here is my code
protected function performSearch(event:MouseEvent):void
{
searchResults = new Array(); // instance variable
foldersToBeSearched = new Array(); // instance variable
// keep file search list empty at start
fileSearchList.dataProvider = searchResults;
// instance level variable to store search string
searchString = searchText.text.toLowerCase();
// add root folder to array
foldersToBeSearched.push(File.applicationStorageDirectory);
findoutFolderNames(File.applicationStorageDirectory);
// keep and eye on folder search counter
setTimeout(checkAsyncFolderCounter, 500);
// show controls if search is on
showHideControlsAsPerSearchNeed();
}
// Because folder search is async hence use timeout to confirm if all folders are listed
private function checkAsyncFolderCounter():void
{
if(foldersToBeSearched.length === counterCapturedLast)
{
// I am done searching all folders and subfolder
// show this data now
fileSearchList.dataProvider = searchResults;
trace(searchResults.length);
}
else
{
// I am not yet done with folders...keep finding
counterCapturedLast = foldersToBeSearched.length;
setTimeout(checkAsyncFolderCounter, 500);
}
}
// Find out all folders in this folder
private function findoutFolderNames(folder:File):void
{
folder.addEventListener(FileListEvent.DIRECTORY_LISTING, directoryListingHandler);
folder.getDirectoryListingAsync();
}
// CHECK ALL FILES AND FOLDER AND FIND FOR SEARCH STRING OTHERWISE ADD FOLDER TO SEARCH FOLDERS LIST
private function directoryListingHandler(event:FileListEvent):void
{
event.target.removeEventListener(FileListEvent.DIRECTORY_LISTING, directoryListingHandler);
var list:Array = event.files;
for (var i:uint = 0; i < list.length; i++)
{
var file:File = list[i];
if(file.isDirectory)
{
foldersToBeSearched.push(file);
findoutFolderNames(file);
}
else
{
if(file.extension === "drl" && file.name.toLowerCase().indexOf(searchString) !== -1)
{
searchResults.push({label: file.name, creationDate: file.creationDate, nativePath: file.nativePath});
}
}
}
trace("Folder Count " + foldersToBeSearched.length);
}

ArcGIS API for Flex : dynamic InfoSymbols

I am trying to add some InfoSymbols in my map, here is what I did :
<esri:InfoSymbol id="infoSymbol1">
<esri:infoRenderer>
<fx:Component>
<s:DataRenderer>
<s:layout>
<s:VerticalLayout/>
</s:layout>
<s:Image id="eventImg" source="{imgSource}"/>
<s:Label id="eventName" text="{eventTitle}"/>
</s:DataRenderer>
</fx:Component>
</esri:infoRenderer>
</esri:InfoSymbol>
And I am filling a list from the data passed to the view, ( the application is a mobile view based app)
public function fillDataGrid():void {
for each(var object:Object in data) {
initDG.addItem(object);
drawEvent(object);
}
}
Finally I add the InfoSymbols the drawEvent(objt) method :
private function drawEvent(object:Object):void{
var myGraphicText:Graphic = new Graphic(new WebMercatorMapPoint(
object.local.longitude, object.local.latitude));
var event:InfoSymbol = new InfoSymbol();
imgSource = "http://192.168.0.22:3000" + object.logo_thumb_url;
eventTitle = object.name;
event = infoSymbol1;
myGraphicText.symbol = event;
myGraphicsLayer.add(myGraphicText);
}
of course imgSource and eventTitle are Bindable,
The issue is that I am getting
Description Resource Path Location Type
1120: Access of undefined property eventTitle.
And the same message for imgSource,
Any help would be much appreciated !!
You need to declare eventTitle before you assign a value to it.
var eventTitle:String = object.name;

Dynamic XML with flex

I'm trying to build a type of query GUI, which returns queries from a php script in xml format via an httpservice.
Each query returns different results
eg.
rep with most and leat quotes
store with highest $ value
I'm really stuck on how to display the queries and access the node names and values.
Here's an example of an xml:
<node>
<action>query</action>
<quotes name="Most Quotes">
<first>John</first>
<last>Smith</last>
<quote_num>71</quote_num>
</quotes>
<quotes name="Least Quotes">
<first>Dave</first>
<last>Cook</last>
<quote_num>6</quote_num>
</quotes>
</node>
Id like to present the data in a readable way.
Thanks
Here the example code for read your XML (it works perfectly):
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" creationComplete="init()" horizontalAlign="center">
<mx:Script>
<![CDATA[
import mx.collections.XMLListCollection;
import mx.utils.ObjectUtil;
private var tempXML:XML;
public function init():void{
tempXML = myXML;
txtA.text = myXML.toString();
readXml();
}
public function readXml():void{
var str:String = "";
var myXML:XMLList = new XMLList(myXML);
for each(var node:XML in myXML){
str = str + "action:" + node["action"] + "\n";
for each(var obj2:XML in node.quotes){
str = str + " name:" + obj2.attributes().toXMLString() + "\n";
str = str + " first:" + obj2["first"] + "\n";
str = str + " first:" + obj2["last"] + "\n";
str = str + " quote_num:" + obj2["quote_num"] + "\n";
}
txtB.text = str;
}
}
]]>
</mx:Script>
<mx:XML id="myXML">
<node>
<action>query</action>
<quotes name="Most Quotes">
<first>John</first>
<last>Smith</last>
<quote_num>71</quote_num>
</quotes>
<quotes name="Least Quotes">
<first>Dave</first>
<last>Cook</last>
<quote_num>6</quote_num>
</quotes>
</node>
</mx:XML>
<mx:HBox width="100%">
<mx:TextArea id="txtA" width="400" height="400" />
<mx:TextArea id="txtB" width="400" height="400" />
</mx:HBox>
Note: This code was created in actionscript 3, but should also work in your version. Please try it and tell me if will be useful, otherwise I'll have to post a code for your version. Remember that there are many ways to do this, i posted this way because maybe is more simple.
You can try this HERE.
Please visit this link for more explanation Working with XML
Second Version
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" creationComplete="init()" horizontalAlign="center">
<mx:Script>
<![CDATA[
import mx.collections.XMLListCollection;
import mx.utils.ObjectUtil;
private var tempXML:XML;
public function init():void{
tempXML = myXML;
txtA.text = myXML.toString();
readXml();
}
public function readXml():void{
var str:String = "";
var quotes:XMLList = myXML.quotes;
str = str + "action:" + myXML["action"] + "\n";
for (var i:int = 0; i < quotes.length(); i++){
str = str + "----quote name:" + XMLList(quotes[i]).attributes().toXMLString() + "\n";
var quotes_child:XMLList = quotes[i].children();
for (var j:int = 0; j < quotes_child.length(); j++){
str = str + "--------" + XML(quotes_child[j]).name() + ":" + quotes_child[j] + "\n";
}
}
txtB.text = str;
}
]]>
</mx:Script>
<mx:XML id="myXML">
<node>
<action>query</action>
<quotes name="Most Quotes">
<first>John</first>
<last>Smith</last>
<quote_num>71</quote_num>
</quotes>
<quotes name="Least Quotes">
<first>Dave</first>
<last>Cook</last>
<quote_num>6</quote_num>
</quotes>
<quotes name="other">
<first>other_first</first>
<last>other_last</last>
<quote_num>other_num</quote_num>
<other_property>other_prop</other_property>
</quotes>
</node>
</mx:XML>
<mx:HBox width="100%">
<mx:TextArea id="txtA" width="400" height="400" />
<mx:TextArea id="txtB" width="400" height="400" />
</mx:HBox>
You can try this HERE.
Check that in this new version, I iterate over each child using a "for" statement with increment variable.
Here's a way to do it without knowing what the node names or attribute names will be
for each(var item : XML in yourXML.children()) {
trace(item.name());//this will get the name of the node
for each(var attribute : XML in item.attributes()) {
trace(attribute.name() + " = " + attribute.toXMLString()); // prints out the attribute names and values
}
}

Get a href from xml file into a flash button

I have a flash file where I'm trying to change the value of the same button depending on the image that is clicked but I can't make it work with different values (I can only make it work with a static value).
AS:
var weblinkXML:XML = new XML();
weblinkXML.ignoreWhite = true;
weblinkXML.load("xml/main.xml");
weblinkXML.onLoad = function(success) {
trace("success = "+success);
for (var i:Number = 0; i< weblinkXML.childNodes.length; i++) {
PPTBUTTON.addEventListener(MouseEvent.CLICK, fl_ClickToGoToWebPage_1);
function fl_ClickToGoToWebPage_1(event:MouseEvent):void
{
navigateToURL(new URLRequest("test/test.html"), "_blank");
}
}
}
my XML:
<?xml version="1.0" encoding="iso-8859-1"?>
<content>
<!-- general vars -->
<settings>
<item name="copyright"><![CDATA[<font letterspacing="0.5">© 2012 | PRIVACY POLICY</font>]]></item>
<item name="companyName"><![CDATA[<font letterspacing="-2"><b>TANITA</b></font>]]></item>
<item name="companySlogan"><![CDATA[<font letterspacing="1">PHOTO PORTFOLIO</font>]]></item>
<!--mp3Url srcUrl="music.mp3"/-->
<imagesPage>
<image imageUrl="images/tfile_splash_pic_main.jpg" />
</imagesPage>
</settings>
<!-- menu -->
<menu>
<button><![CDATA[PORTFOLIO]]></button>
<button><![CDATA[ABOUT]]></button>
<button><![CDATA[NEWS]]></button>
<button><![CDATA[CONTACTS]]></button>
</menu>
<gallery gallName="Crystal Cabin Awards 2012">
<image imageUrl="gallery/tfile_gall_small_01.jpg" imagesBig="gallery/tfile_gall_big_01.jpg" buttonName="PPTBUTTON" targ="_self" href="http://www.google.com"/>
<image imageUrl="gallery/tfile_gall_small_02.jpg" imagesBig="gallery/tfile_gall_big_02.jpg" buttonName="PPTBUTTON" targ="_self" href="http://www.youtube.com"/>
<image imageUrl="gallery/tfile_gall_small_03.jpg" imagesBig="gallery/tfile_gall_big_03.jpg" buttonName="PPTBUTTON" targ="_self" href="http://www.yahoo.com"/>
<image imageUrl="gallery/tfile_gall_small_04.jpg" imagesBig="gallery/tfile_gall_big_04.jpg"/>
<image imageUrl="gallery/tfile_gall_small_05.jpg" imagesBig="gallery/tfile_gall_big_05.jpg"/>
<image imageUrl="gallery/tfile_gall_small_06.jpg" imagesBig="gallery/tfile_gall_big_06.jpg"/>
<image imageUrl="gallery/tfile_gall_small_07.jpg" imagesBig="gallery/tfile_gall_big_07.jpg"/>
<image imageUrl="gallery/tfile_gall_small_08.jpg" imagesBig="gallery/tfile_gall_big_08.jpg"/>
</gallery>
I realize my xml is complex but it's being used through the entire flash. Maybe I could reduce it to a stand alone xml just like:
<image imageUrl="gallery/tfile_gall_small_02.jpg" imagesBig="gallery/tfile_gall_big_02.jpg" buttonName="PPTBUTTON" targ="_self" href="http://www.youtube.com"/>
my issue is that I've tried to get the href into a variable and use it instead of "test/test.html" but it never works.
I also realize I have a method inside a for but at this point I've iterated so much over this code that I'm unsure how to proceed.
Here's how i would retrieve the list of href attributes:
var loader:URLLoader = new URLLoader();
var request:URLRequest = new URLRequest("xml/main.xml");
loader.addEventListener(IOErrorEvent.IO_ERROR, function errorHandler(event:IOErrorEvent):void {
trace("Error loading XML" + event.type);
});
loader.addEventListener(Event.COMPLETE, function(event:Event):void {
trace("success = " + event);
var xml:XML = new XML(loader.data);
var xmllist:XMLList = xml.gallery.children();
for (var i:Number = 0; i < xmllist.length(); i++) {
trace(XML(xmllist[i]).attribute("href"));
}
});
loader.load(request);
I had the following output:
success = [Event type="complete" bubbles=false cancelable=false eventPhase=2]
http://www.google.com
http://www.youtube.com
http://www.yahoo.com
I hope that helps.