Is there a way to dispatch event again in handler? - apache-flex

For my test I need to load about 1000 files and then perform some actions with each one by one. The problem is that I can not load another file in handler, flexunit just exit after calling load(). It works when I use another loader, with previously added Event Listener(see code), but I don't think it is a good idea to add ~1000 loaders.
I had also tried to create new loader object in handler function, but I got an "Asynchronous Event Received out of Order" error when trying to add Event Listener there.
What should I do here?
[Test(async)]
public function testTest():void
{
loader.addEventListener(Event.COMPLETE, Async.asyncHandler(this, onComplete, 10000), false, 0, true);
loader.load(new URLRequest("file.xml"));
//loader2.addEventListener(...);
function onComplete(e:Event, passTroughtData:Object):void
{
//performing my actions with loaded file
trace("loaded");
//attempt 1 - test finishes after the next line
loader.load(new URLRequest("other_file.xml"));
//attempt 2 - causes Out of order error
//loader = new URLLoader();
//loader.addEventListener(Event.COMPLETE, Async.asyncHandler(this, onComplete, 10000), false, 0, true);
//loader.load(new URLRequest("other_file.xml"));
}
}

The simplest way to do what I wanted is to create an array of loaders (extra loader for each file) and add listeners to them before calling the first load() method.

Related

How to change resource(s) of events

The handling of resource changed in FullCalender 4.0.
In FullCalendar 3.x I changed the resource of an event using:
event.resourceId = newResourceId;
In FullCalendar 4.0 I cannot find the right way...
My current code is:
var calendar_event = calendar.getEventById(data.event.id)
if (calendar_event) {
calendar_event.setProp('title', data.event.title)
calendar_event.setProp('resourceIds', [data.event.resourceId])
}
setProp seems to be not the correct method as afterwards the event does not reflect the change within the grid, only the title has been changed to the new one.
A setter to getResources(), e.g. setResources() does not exist.
The official documentation on https://fullcalendar.io/docs/resource-data only includes resource-fetching, not programmatically set a new one to an existing event.
The migration guide https://fullcalendar.io/docs/upgrading-from-v3 mentions only the methods setProp, setExtendedProp, setStart, setEnd, setDates, setAllDay, moveStart, moveEnd, moveDates to replace updateEvent - resources are missing.
My current workaround is to delete and add the event again:
calendar.getEventById(data.event.id).remove()
calendar.addEvent(data.event)
How to move an event to another resource without loading and initializing the whole event a second time?
Editing resources of an event has been added in version 4.0.2.
The documentation describes the usage as follows:
By ID:
var event = calendar.getEventById('1');
event.setResources([ 'a' ]); // set a single resource
event.setResources([ 'a', 'b' ]); // set multiple
By Resource:
var resourceA = calendar.getResourceById('a');
var resourceB = calendar.getResourceById('b');
var event = calendar.getEventById('1');
event.setResources([ resourceA, resourceB ]);

event.COMPLETE handler question

I want to dispatch a custom event when the two files are downloaded or uploaded successfully. I use
fileRef.addEventListener(Event.COMPLETE, completeHandler);
fileBigRef.addEventListener(Event.COMPLETE, completeHandler);
to listen the complete event with only 1 handler.
function completeHandler(event:Event):void{
var e:Event=new Event("addInfoDone");
dispatchEvent(e);
fileBigRef.removeEventListener(Event.COMPLETE,completeHandler);
fileRef.removeEventListener(Event.COMPLETE,completeHandler);
}
I want the event to be dispatched only once when both of the fileRef and fileBigRef are complete transfered. Any ideas?? My brain is fry now and can't think of anything..... Thanks for the help.
For a quick and dirty solution, how about defining a counter that increments each time completeHandler is fired. Once the counter reaches the number of files you're expecting (sounds like you're expecting 2), you fire your addInfoDone event:
var fileRefCounter:Number = 0;
function completeHandler(event:Event):void{
fileRefCounter++;
if(fileRefCounter == 2)
{
// both files have downloaded; fire your custom event, or whatever
}
}

FileReference.download() not working

I'm building a Flex app which requires me to download files.
I have the following code:
public function execute(event:CairngormEvent) : void
{
var evt:StemDownloadEvent = event as StemDownloadEvent;
var req:URLRequest = new URLRequest(evt.data.file_path);
var localRef:FileReference = new FileReference();
localRef.addEventListener(Event.OPEN, _open);
localRef.addEventListener(ProgressEvent.PROGRESS, _progress);
localRef.addEventListener(Event.COMPLETE, _complete);
localRef.addEventListener(Event.CANCEL, _cancel);
localRef.addEventListener(Event.SELECT, _select);
localRef.addEventListener(SecurityErrorEvent.SECURITY_ERROR, _securityError);
localRef.addEventListener(IOErrorEvent.IO_ERROR, _ioError);
try {
localRef.download(req);
} catch (e:Error) {
SoundRoom.logger.log(e);
}
}
As you can see, I hooked up every possible event listener as well.
When this executes, I get the browse window, and am able to select a location, and click save. After that, nothing happens.
I have each event handler hooked up to my logger, and not a single one is being called! Is there something missing here?
The problem seems to be with my command being destroyed before this could finish.
For a proof of concept, I set my localRef variable to be static instead of an instance variable, and everything went through successfully! I guess Cairngorm commands kill themselves asap!

Flex 3 multiple upload progress monitoring

I have a Flex3 application which has to be capable of uploading multiple files and monitoring each files individual progress using a label NOT a progress bar.
My problem is that a generic progress handler for the uploads has no way (that I know of) of indicating WHICH upload it is that is progressing. I know that a file name is available to check but in the case of this app the file name might be the same for multiple uploads.
My question: With a generic progress handler how does one differentiate between 2 multiple uploads with the same file name?
EDIT: answerers may assume that I am a total newb to Flex... because I am.
I use this:
private function _addFileListeners(dispatcher:IEventDispatcher):void {
dispatcher.addEventListener(Event.OPEN, this._handleFileOpen);
dispatcher.addEventListener(Event.SELECT, this._handleFileOpen);
dispatcher.addEventListener(Event.CANCEL, this._handleFileCancel);
dispatcher.addEventListener(ProgressEvent.PROGRESS, this._handleFileProgress);
dispatcher.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA,this._handleFileComplete);
dispatcher.addEventListener(IOErrorEvent.IO_ERROR, this._handleError);
dispatcher.addEventListener(SecurityErrorEvent.SECURITY_ERROR, this._handleError);
}
where "dispatcher" is the file:
for (var i:uint = 0; i < fileList.length; i++) {
file = FileReference(fileList[i]);
this._addFileListeners(file);
this._pendingFiles.push(file);
}
and a sample handler:
private function _handleFileOpen(e:Event):void {
var file:FileReference = FileReference(e.target);
...
}
I'm not sure how you want to differentiate between two files with the same name. In my case, I send the files in a queue. So there's only ever 1 file being uploaded at a time. (pendingFiles).
If you are listening for ProgressEvents, these events have a currentTarget attribute that would have a reference to the object that has registered the event listener.
I'm assuming you know which file-uploading object goes with each object in the first place.
EDIT: Example using FileReference:
import flash.net.FileReference;
import flash.events.ProgressEvent;
import flash.utils.Dictionary;
public var files:Dictionary = new Dictionary(); // This will hold all the FileReference objects
public function loadFile(id:String):void
{
var file:FileReference = new FileReference();
// Listen for the progress event on this FileReference... will call the same function for every progress event
file.addEventListener(ProgressEvent.PROGRESS, onProgress);
// TODO: listen for errors and actually upload a file, etc.
// Add file to the dictionary (as key), with value set to an object containing the id
files[file] = { 'id': id };
}
public function onProgress(event:ProgressEvent):void
{
// Determine which FileReference dispatched thi progress event:
var file:FileReference = FileReference(event.target);
// Get the ID of the FileReference which dispatched this function:
var id:String = files[file].id;
// Determine the current progress for this file (in percent):
var progress:Number = event.bytesLoaded / event.bytesTotal;
trace('File "' + id + '" is ' + progress + '% done uploading');
}
// Load some files:
loadFile('the first file');
loadFile('the second file');
I ended up creating my own class that manages events for each uploading file

Flex - Dispatch custom Event on receipt of standard Event

I am processing a FileReferenceList.fileList[] of multiple files a user selects in the following code..
for (i=0;i < event.currentTarget.fileList.length; i ++){
fileByteData = new ByteArray();
fileByteData = (event.currentTarget.fileList[i].data as ByteArray);
loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, checkImageDimensions);
loader.loadBytes(fileByteData);
}
I need to pass i into checkImageDimensions to keep track of which image is which, I can easily enough create a custom event, but I need this to fire at the right time. Ideally I could do something like this..
var myEvent:CustomEvent = new CustomEvent(i);
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, this.dispatchEvent(CustomEvent))
But to be honest, I am unsure of how to proceed...
Can anyone help me out? Thanks!
You need to make a listener function - a function call does not suffice. Passing a class name to dispatchEvent does not work either. Here's how to do it.
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, function(e:Event):void {
dispatchEvent(new CustomEvent(i));
});
Note that you don't necessarily need a custom event class, if all you need in the event is a type string. You can simply use the Event class in this case:
public static const MY_CUSTOM_EVENT:String = "myCustomEvent";
...
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, function(e:Event):void {
dispatchEvent(new Event(MY_CUSTOM_EVENT));
});
Edit: If you're really lazy, but still want to pass values with the event, you can use the DinamicEvent class:
var evt:DynamicEvent = new DynamicEvent(MY_CUSTOM_EVENT);
evt.attr1 = val1;
evt.attr2 = val2;
dispatchEvent(evt);
Of course, it is cleaner and less error prone to declare your own error class.

Resources