Strange thing happened to me today. The above message started displaying. I have a controller that list presentations. It has actions index (=list), detail and play (that plays the slideshow). I can repeat the dispatch transition from list to detail and back as many times I want. But when I dispatch the play action and return back to detail, I can't return there any more, because of an error:
Uncaught TypeError: Object [object Object] has no method 'call'
I examined what happens. Problem is that in the first call in the next code (sencha-touch.debug.js:line 10630) "controller[action]" is a function - the contents of function written in controller class.
Code:
if (controller && action) {
controller[action].call(controller, interaction);
interaction.dispatched = true;
}
But after that when i dispatch the action second time, there is no function anymore. It's been replaced with an object (looks like the view panel). And "call" method does not work on it. What am I doing wrong, that the function is replaced with an object?
Here is my Controller's code:
Code:
Ext.regController('videos', { index : function(options) {
if (!this.listPanel) {
this.listPanel = new app.views.VideoList({
listeners : {
list : {
select : function(list, record) {
Ext.dispatch({
controller : 'videos',
action : 'show',
list : list,
record : record,
historyUrl : 'videos/show/' + record.get('id'),
animation : {
type : 'slide'
}
});
},
scope : this
},
activate : function() {
if (this.detail) {
this.detail.destroy();
}
if (this.play) {
this.play.destroy();
}
}
}
});
}
this.application.viewport.setActiveItem(this.listPanel,
options.animation);
this.application.currentItem = 2;
},
show : function(options) {
if (!options.record) {
Ext.dispatch({
controller : 'videos',
action : 'index',
historyUrl : 'videos/index'
});
return;
}
this.record = options.record;
options.list.deselectAll();
console.log('detail created');
this.detail = new app.views.VideoDetail({
data : this.record.data,
listeners : {
el : {
tap : function() {
console.log('element tapped');
console.log('record is', this.record);
Ext.dispatch({
controller : 'videos',
action : 'play',
historyUrl : 'videos/play/'
+ this.record.get('id'),
animation : {
type : 'slide',
direction : 'left'
}
});
},
scope : this,
delegate : '.video-disclose'
},
deactivate : function(component) {
console.log('detail destroyed');
component.destroy();
}
}
});
this.detail.query('#backButton')[0].on({
tap : function() {
Ext.dispatch({
controller : 'videos',
action : 'index',
historyUrl : 'videos/index',
animation : {
type : 'slide',
direction : 'right'
}
});
},
scope : this
});
this.application.viewport.setActiveItem(this.detail, {
type : 'slide'
});
},
play : function(options) {
if (!options.record) {
if (!this.record) {
Ext.dispatch({
controller : 'videos',
action : 'index',
historyUrl : 'videos/index'
});
return;
}
} else {
this.record = options.record;
}
console.log('play created');
this.play = new app.views.VideoPlay({
data : this.record.data,
listeners : {
deactivate : function(component) {
console.log('play destroyed');
component.destroy();
},
beforerender : function() {
console.log('beforerender event fired');
this.store.load({
scope : this,
callback : function(records, operation, success) {
Ext.each(records, function(record) {
this.carousel.add(new Ext.Component({
'tpl' : app.partials.videoPlayCarouselItem,
'data' : record.data
}));
}, this);
this.carousel.doLayout();
}
});
},
show : function () {
Ext.each(this.carousel.items.items, function(item) {
console.log(item);
item.el.on('tap', function() {
console.log('tap item fired');
me.play.toolbar.show();
me.doComponentLayout();
});
});
}
}
});
this.play.query('#VideoPlayBackButton')[0].on({
tap : function() {
Ext.dispatch({
controller : 'videos',
action : 'show',
historyUrl : 'videos/show/' + this.record.get('id'),
animation : {
type : 'slide',
direction : 'right'
}
});
},
scope : this
});
this.play.query('#VideoPlayHideButton')[0].on({
tap : function() {
me = this;
this.toolbar.hide({
type : 'slide',
direction : 'down'
});
this.toolbar.on('hide', function() {
console.log('hide event fired');
me.doComponentLayout();
});
},
scope : this.play
});
this.play.carousel.on({
afterrender : function(c) {
console.log(c.items.getCount());
console.log('afterrender event fired');
me = this;
console.log(c.items);
Ext.each(c.items, function(item) {
console.log(item);
item.el.on('tap', function() {
console.log('tap item fired');
me.play.toolbar.show();
me.doComponentLayout();
});
});
}
});
this.application.viewport.setActiveItem(this.play, options.animation);
}
});
And the view that I want to show:
Code:
app.views.VideoPlay = Ext.extend(Ext.Panel, {
store : app.stores.presentations,
initComponent : function() {
this.carousel = new Ext.Carousel({
itemId : 'videoPlayCarousel',
tpl : app.partials.videoPlayCarouselItem
});
this.audio = new Ext.Audio({
url : this.data.url,
autoPause : true,
autoResume : true
});
this.toolbar = new Ext.Toolbar({
//floating : true,
top : 0,
items : [ {
xtype : 'button',
ui : 'back',
text : 'Zpět',
itemId : 'VideoPlayBackButton'
}, {
xtype : 'button',
text : 'Skrýt panel',
itemId : 'VideoPlayHideButton'
} ],
itemId : 'playerToolbar'
});
this.items = [ this.carousel, this.audio ];
this.dockedItems = [ this.toolbar ];
Ext.apply(this, {
layout : 'fit',
});
app.views.VideoPlay.superclass.initComponent.apply(this, arguments);
}
});
Ext.reg('video-play', app.views.VideoPlay);