PDA

View Full Version : Ext.Animator.runningAnimationsData does not clear after animation finished



blackswanny
24 Sep 2012, 10:31 PM
I have encountered some strange behavour with animation. May be it's my mistake, but I would like to describe the case.
I have MVC app, where we support views and card layout. One view - is login page and I have login and lgout procedure. Our transition is slide. Everything works fine. But I found one case:
1) after login and running the app I make logout at any time, which makes these steps
- destroy all views and controllers:

view.destroy();
delete Ext.app.Application.getControllerInstances()[controllerName];
delete Ext.app.Application.controllers[controllerName];
- redirect to Login Page

Ext.Viewport.setActiveItem(loginPageViewInstance);

At the moment of logout I have only one view, because I destroy view every time after switching to another.

2) I enter my app for the second time, and everyting is fine, but when I try to open view, which was the last showed in a previous session before logout, this view has got visibility: "hidden !important" style and I see only blank page with my invisible view.

I found, why is it happened. Every time I switch between views I run Ext.Animator's CSS transition for animation. It log every animation in Ext.Animator.runningAnimationsData array, where in my case I have two animation sessions for previous hiding view and next showing view at one transition operation.
When I make logout and invoke view.destroy as a child of Ext.Viewport it makes parent.remove(view), i.e. Ext.Viewport.remove(view). Which starts animation operation over my last view, and unfortunately it leaves info of last view in Ext.Animator.runningAnimationsData like animation did not finished. As a result after logout and second view showing Ext.Animator thinks that this view is visible (because of this info) and doesn't remove visibility: hidden from it's style.
I make this hack code:

delete Ext.Animator.runningAnimationsData[view.id];
but it's not good to use private code. I would be happy to receive someone's advice or make it clear, what is wrong.

mitchellsimoens
27 Sep 2012, 6:21 AM
Why are you trying to delete a controller? You shouldn't do this.

blackswanny
27 Sep 2012, 7:15 AM
I destroy view to release free resources. When it happened event listeners are removed too. And controller looses reference to view's DOM, it becomes useless. So when we create view again there are no listeners and we need to recreate it's controller to renovate listeners.

mitchellsimoens
27 Sep 2012, 7:17 AM
Controllers aren't much, listeners aren't placed on components so there is no need for it really.

blackswanny
27 Sep 2012, 7:30 AM
I don't understand. You say listeners are not linked with real DOM-elements? Or Sencha components?

mitchellsimoens
27 Sep 2012, 7:31 AM
In controllers, the listeners in the control config are not actually placed on the components.

blackswanny
27 Sep 2012, 7:49 AM
I have just debugged. When we create new controller config's property Control applying by method Ext.app.Controller.applyControl , which adds listeners to the components of view.

mitchellsimoens
27 Sep 2012, 8:08 AM
No, it adds a listener to the dispatcher.

The applyControl method executes this.control on the controller. The control method on the controller then executes the control method on the application. In the control method on the application, the addListener is on the dispatcher (in red):


control: function(selectors, controller) {
//if the controller is not defined, use this instead (the application instance)
controller = controller || this;

var dispatcher = this.getEventDispatcher(),
refs = (controller) ? controller.getRefs() : {},
selector, eventName, listener, listeners, ref;

for (selector in selectors) {
if (selectors.hasOwnProperty(selector)) {
listeners = selectors[selector];
ref = refs[selector];

//refs can be used in place of selectors
if (ref) {
selector = ref.selector || ref;
}
for (eventName in listeners) {
listener = listeners[eventName];

if (Ext.isString(listener)) {
listener = controller[listener];
}

dispatcher.addListener('component', selector, eventName, listener, controller);
}
}
}
},

blackswanny
28 Sep 2012, 5:37 AM
You can create controller for view and afterwards destroy view. As result in property below it deletes subscribers-listeners, since than controller cannot control the newly created view.


controller.eventDispatcher._publishers.dom.dispatcher.listenerStacks.component

But my question is why during destroying view the code invokes animation process of viewport as a parent

mitchellsimoens
28 Sep 2012, 5:43 AM
No, you can remove and add components and the controller will remain to listen for events. Try this test case that removes a button, adds a new one and you can do this all day:


Ext.define('Test.controller.Test', {
extend : 'Ext.app.Controller',

config : {
control : {
'button' : {
tap : 'onButtonTap'
}
}
},

onButtonTap : function(button) {
var parent = button.parent;

parent.remove(button);

console.log('button removed');

parent.add({
xtype : 'button',
text : 'Destroy and create new button'
});

console.log('new button added');
}
});

Ext.application({
name : 'Test',

controllers : [
'Test'
],

launch : function () {

Ext.Viewport.add({
items : [
{
xtype : 'button',
text : 'Destroy and create new button'
}
]
});

}
});