PDA

View Full Version : Ext.ux.FlashControl - Mediator for Flash Movies



ThorstenSuckow
15 Jul 2009, 10:53 AM
Project Home: http://code.google.com/p/ext-ux-flashcontrol/ (http://code.google.com/p/ext-ux-flashcontrol/)
Live example: http://www.siteartwork.de/flashcontrol/examples/ (http://www.siteartwork.de/flashcontrol/examples/)

Tired of (what seems to be) randomly restarting/crashing Flash Movies in your Ext-driven web application?
Take a look at Ext.ux.FlashControl (http://code.google.com/p/ext-ux-flashcontrol/) - a control that mediates between Ext.Container and Ext.FlashComponent.

When using this control, the registered FlashComponent gets rendered on top of the document.body and adjusts its state (height, width, position, zIndex, visibility) based on the configuration passed and the state of the registered container it would usually have been added to.



Ext.ux.FlashControl is a mediator for flash movies in Ext JS driven applications - it delegates state informations from the Ext.Container the flash movie would have been usually added to and takes care of properly rendering the flash movie into the UI, preventing flaws like reload/restart/loss of the flash movie during DOM operations.


Here's a live example:
http://www.siteartwork.de/flashcontrol/examples/ (http://www.siteartwork.de/flashcontrol/examples/)

Ext.ux.FlashControl is another component that grew out of a sub-project from conjoon (http://www.conjoon.org).

mystix
15 Jul 2009, 11:09 AM
impressive :)

how does this compare with @hendricd's ux.FlashPanel?
or does this play a different role / serve a different purpose?

ThorstenSuckow
15 Jul 2009, 11:16 AM
how does this compare with @hendricd's ux.FlashPanel?


good question, it's been some time since I last looked at Doug's solution.

I guess FlashPanel automates a lot for you regarding component management, while FlashControl follows the approach of loose coupling - more or less the complete process of adjusting the FlashComponent's state is done using listeners, and due to this you are able to switch the Flash's parent during runtime - while the parent is not directly a parent in the DOM tree, but more a parent that gets observed by the mediator.

ThorstenSuckow
16 Jul 2009, 4:45 PM
Ext.ux.FlashControl 0.1.1 has been commited to the trunk and introduces "autoAddListeners" which automates the process of adding some standard listeners for events that hide/show the FlashComponent. For a complete list of changes, see http://code.google.com/p/ext-ux-flashcontrol/source/detail?r=5

Ronaldo
21 Jul 2009, 6:24 AM
Impressive!

I didn't dive in the code yet, but is it possible to pass parameters to the swf, like you can in swfobject?

Ronaldo

Ronaldo
29 Jul 2009, 7:21 AM
Hi,

I tried to use your FlashControl in an east region of a tabpanel in a form, in a tab in a viewport... A little complex but there's no window, which may cause trouble in the detectWindows method... (lastwindow == null)...

So I changed (see bold)


if (Ext.isGecko && this.quirksFF && this.lastWindow && (this.lastWindow.maximizable) && this.lastWindow.container.dom == document.body) {

And that worked. I'm not sure what is missing but in FF3.5.1 I can see a movie!

There are some problems when switching to another tab, or closing the main tab. The FlashControl remains and overlaps other portions of the screen.
I guess you expect the FlashControl to be always in a window, and thus it doesn't listen to close/hide events from other components :-?.

Anyway, any chances of being able to set parameters to the movieclip as in jsObject?

Best regards,
Ronaldo

ThorstenSuckow
29 Jul 2009, 8:16 AM
Hi,

I tried to use your FlashControl in an east region of a tabpanel in a form, in a tab in a viewport... A little complex but there's no window, which may cause trouble in the detectWindows method... (lastwindow == null)...

Ronaldo

Hi Ronaldo,


no, the quirksFF just has to be activated as soon as you want to use the flash movie within an Ext.Window, otherwise it is not needed. Try to use it without setting quirksFF=true.

Setup in conjoon is as follows: Viewport - > East Region -> AccordionLayout->TabPanel->Tab. The tab can be dragged, as can the TabPanel.
The TabPanel can be dragged between the east and the west panel of the workbench. The Tab itself can be dragged to the center TabPanel of the workbench itself and invokes creating a new Tab in the center panel of the workbench. Closing the TabPanel renders the FlashContainer back into teh original TabPanel sitting either in the west or in the east region of the workbench.

I know my use case might differ from yours but maybe my setup of FlashControl can give you a hint:



return new Ext.ux.util.FlashControl({
flashComponent : player,
container : basePanel,
getListenerConfig : function() {

var featurePanel = com.conjoon.groupware.service.youtube.ViewBaton.getFeaturePanel();
var quickPanel = com.conjoon.groupware.QuickEditPanel.getComponent();

var westPanel = com.conjoon.util.Registry.get(
'com.conjoon.groupware.Workbench'
).getWestPanel();
var eastPanel = com.conjoon.util.Registry.get(
'com.conjoon.groupware.Workbench'
).getEastPanel();

var itemsWest = westPanel.items.items;
var itemsEast = eastPanel.items.items;

return {
activate : {
items : [this.container, featurePanel],
fn : function(){
var ct = this.container.ownerCt;
while(ct) {
if (ct.hidden === true) {
this.hideFlashComponent();
return;
}
ct = ct.ownerCt;
}
this.showFlashComponent();
},
scope : this,
strict : true
},
deactivate : {
items : [this.container, featurePanel],
fn : this.flashComponent.hide,
scope : this.flashComponent,
strict : true
},
drop : {
items : [eastPanel, westPanel],
fn : 'refreshListeners',
strict : false
},
show : {
items : [quickPanel, eastPanel, westPanel],
fn : this.flashComponent.show,
scope : this.flashComponent,
strict : true
},
hide : {
items : [quickPanel, eastPanel, westPanel],
fn : this.flashComponent.hide,
scope : this.flashComponent,
strict : true
},
afterlayout : {
items : [eastPanel, westPanel],
fn : 'afterContainerLayout',
strict : true
},
beforeexpand : {
items : itemsEast.concat(itemsWest),
fn : this.flashComponent.hide,
scope : this.flashComponent,
strict : [eastPanel, westPanel]
},
expand : {
items : itemsEast.concat(itemsWest),
fn : this.flashComponent.show,
scope : this.flashComponent,
strict : [eastPanel, westPanel]
},
beforecollapse : {
items : itemsEast.concat(itemsWest),
fn : this.flashComponent.hide,
scope : this.flashComponent,
strict : [eastPanel, westPanel]
},
collapse : {
items : itemsEast.concat(itemsWest),
fn : function(component) {
if (component != this.container.ownerCt) {
this.flashComponent.show();
}
},
strict : [eastPanel, westPanel]
}
};
}
});



Below are the two methods that get called when the FlashContainer (basePanel) should change its position. "featurePanel" is the panel thet gets rendered in the centerPanel of the workbench:



/**
* Attempts to remove the basePanel from the
* {com.conjoon.groupware.QuickEditPanel} container and add it to the
* FeatureTab to the contentPanel. The feature tab will be build if not already
* available and inserted at the specified position in the contentPanel.
*
*/
showInFeaturePanel : function(position)
{
if (!featurePanel) {
featurePanel = buildFeaturePanel();
}

var contentPanel = com.conjoon.util.Registry.get(
'com.conjoon.groupware.ContentPanel'
);

if (com.conjoon.groupware.QuickEditPanel.getComponent().findById(basePanel.getId())) {
basePanel.ownerCt.remove(basePanel, false);
featurePanel.add(basePanel);
}

flashControl.refreshListeners();

if (!Ext.isNumber(position)) {
contentPanel.add(featurePanel);
} else {
contentPanel.insert(position, featurePanel);
}
contentPanel.setActiveTab(featurePanel);
},

/**
* Attempts to remove the basePanel from the featurePanel
* container and add it to the QuickEditPanel. This is the listener for the
* featurePanels 'close' operation. The feature panel will get destroyed, thus
* we will reset the featurePanel variable to null.
*
* @return {com.conjoon.groupware.service.youtube.FeaturePanel}
*/
showInQuickPanel : function(position)
{
var quickPanel = com.conjoon.groupware.QuickEditPanel.getComponent();

if (featurePanel && basePanel.ownerCt == featurePanel) {
basePanel.ownerCt.remove(basePanel, false);
quickPanel.add(basePanel);
}

featurePanel = null;

flashControl.refreshListeners();

quickPanel.setActiveTab(basePanel);
},

Ronaldo
29 Jul 2009, 12:04 PM
Thanks! I got it now. I needed to grasp the intention of the getConfigListeners() method, the scope it runs in, but after that it works fine now.
Thanks again!

Ronaldo

Ronaldo
30 Jul 2009, 2:15 AM
Hi,

Do you know of an easy way to reload the complete swf file? During development, I'm also working on the as3 project, and after having changed the swf, I'd like to be able to reload the FlashComponent/FlashControl so that it reflects the latest changes in the swf.
I have a 'reload swf' button in my interface which should just do that ;)

Otherwise, I have to reload the complete tab/interface over and over again...

So, I'd like to be able to completely destroy the flash in the region, and re-add it, so the new swf is loaded, or somehow force a reload of the swf without closing and opening the surroundig tab/viewport.

TIA
Ronaldo

ThorstenSuckow
30 Jul 2009, 4:12 AM
Do you know of an easy way to reload the complete swf file?

Not quite sure - did you take a look at the Ext.FlashComponent-API and see if the swfobject supports anything like that?

Otherwise this might be a question for the help forum, I guess, since it's not related to the FlashControl - it only mediates between container/component.

Ronaldo
30 Jul 2009, 11:53 AM
Thanks for answering. I found the answer (https://extjs.com/forum/showthread.php?p=258291#post258291) and adapted it to my needs (this points to the Ext.form.FormPanel)



this.previewPanel = new Ext.Panel({
title: 'Preview',
region: 'east',
layout: 'fit',
width: '50%',
collapsible: true,
split: true,
tbar: [{
text:'Reload player',
scope: this,
handler:function(){
this.previewPanel.remove(this.flashComponent);
this.flashComponent = this.getFlashComponent(); // returns a new Ext.FlashComponent
this.previewPanel.add(this.flashComponent);
this.doLayout();
}
}]
});


Works like charm!

Cheers,
Ronaldo

Ronaldo
31 Jul 2009, 12:34 AM
Hi,

One last question (I hope 8-| )

When I minimize the panel, or deactivate the tab the panel is on, the flash movie restarts every time when it becomes visible again... which is rather annoying... It should continue playing, as it does in your examples.

Your example shows a window, and when minimizing that, the movie just keeps playing.
In my case (with the same youtube movie) it stops playing and on re-opening the panel, the movie is stopped at time 0.

Any idea what might cause this behaviour?

I added a collapsible:true to your panel example, and that seems to work fine. With the following changes, your flashmovie continues playing when collapsed:


northPanel = new Ext.Panel({
region : 'north',
height : 100,
layout : 'fit',
bodyStyle : 'background:#EDEDED',
title: 'north',
collapsible: true,
split: true
});I also noted that you don't include an items property in the northpanel, like


items:[flashComponent]But that appearantly the flashControl attaches itself to the northpanel when rendered/activated:



flashControl = new Ext.ux.util.FlashControl({
flashComponent : movie,
container : northPanel,
....
If I omit the items property in my collapsible panel, I don't see the flash movie when the tab is opened on which the panel is situated...

Here's my code:



this.flashComponent = this.getFlashComponent();
this.flashControl = this.getFlashControl();

this.previewPanel = new Ext.Panel({
title: 'Preview',
region: 'east',
layout: 'fit',
width: '50%',
collapsible: true,
split: true,
tbar: [{
text:'Reload player',
scope: this,
handler:function(){
this.reloadPlayer(this.contentField.getRawValue());
}
}]
,
items:[this.flashComponent]
});

this.tabPanel = new Ext.TabPanel({
xtype:'tabpanel',
activeTab: 0,
anchor:'0 -65',
height: 200,
autoWidth: true,
hideLabel: true,
plain: true,
items:[{
title: 'General',
...
}, {
title: 'Content',
layout:'border',
items: [{
title: 'Content',
region: 'center',
split: true,
layout: 'fit',
items: [this.contentField] // A textArea
},
this.previewPanel
]
}]
});

getFlashComponent: function() {
return new Ext.FlashComponent({
// its important to set the FlashComponents hideMode to offsets
hideMode : 'offsets',
id : 'dustinthewind',
swfId : 'dustinthewind',
url : 'http://www.youtube.com/v/1qxSwJC3Ly0&hl=de&fs=1&'
});
},
getFlashControl : function() {
return new Ext.ux.util.FlashControl({
flashComponent : this.flashComponent,
container : this.previewPanel,
quirksFF : false,
quirksIE : false,
autoDragTracker : false, // true gives same behaviour
autoDestroy : true, // false gives same behaviour
autoAddListeners : [
'collapse',
'beforecollapse',
'expand',
'beforeexpand',
'maximize'
],
getListenerConfig : function() {
//var tabPanel = this.container.ownerCt;
//var mainTabPanel = tabPanel.ownerCt.ownerCt;
return {
activate : {
fn : this.flashComponent.show,
scope : this.flashComponent,
items : [this.container]//, tabPanel, mainTabPanel]
},
deactivate : {
fn : this.flashComponent.hide,
scope : this.flashComponent,
items : [this.container]//, tabPanel, mainTabPanel]
},
beforecollapse : {
// hideFlashComponent...
fn : 'hideFlashComponent',
// ...will be called when this.container's
// beforecollapse event triggers
scope : this,
strict : false,
items : [this.container]
},
maximize : {
// showFlashComponent...
fn : 'showFlashComponent',
// ...will be called when this.container's
// maximize event triggers
scope : this,
strict : false,
items : [this.container]
},
expand : {
// showFlashComponent...
fn : 'showFlashComponent',
// ...will be called when this.container's
// expand event triggers
scope : this,
strict : false,
items : [this.container]
},
beforeexpand : {
// hideFlashComponent...
fn : 'hideFlashComponent',
// ...will be called when this.container's
// beforeexpand event triggers
scope : this,
strict : false,
items : [this.container]
},
collapse : {
// hideFlashComponent...
fn : 'hideFlashComponent',
// ...will be called when this.container's
// collapse event triggers
scope : this,
strict : false,
items : [this.container]
}
};
}
});

ThorstenSuckow
31 Jul 2009, 12:47 AM
Try the following code.



this.previewPanel = new Ext.Panel({
title: 'Preview',
region: 'east',
layout: 'fit',
width: '50%',
collapsible: true,
split: true,
tbar: [{
text:'Reload player',
scope: this,
handler:function(){
this.reloadPlayer(this.contentField.getRawValue());
}
}]

// no need to add this, as the container is just a placeholder and
// no real container for the flashpanel
//,items:[this.flashComponent]

});

this.tabPanel = new Ext.TabPanel({
xtype:'tabpanel',
activeTab: 0,
anchor:'0 -65',
height: 200,
autoWidth: true,
hideLabel: true,
plain: true,
items:[{
title: 'General',
...
}, {
title: 'Content',
layout:'border',
items: [{
title: 'Content',
region: 'center',
split: true,
layout: 'fit',
items: [this.contentField] // A textArea
},
this.previewPanel
]
}]
});

getFlashComponent: function() {
return new Ext.FlashComponent({
// its important to set the FlashComponents hideMode to offsets
hideMode : 'offsets',
id : 'dustinthewind',
swfId : 'dustinthewind',
url : 'http://www.youtube.com/v/1qxSwJC3Ly0&hl=de&fs=1&'
});
},


getFlashControl : function() {
return new Ext.ux.util.FlashControl({
flashComponent : this.flashComponent,
container : this.previewPanel,
autoAddListeners : true
});



// Moved here just to make sure components are available when methods are called
this.flashComponent = this.getFlashComponent();
this.flashControl = this.getFlashControl();

Ronaldo
31 Jul 2009, 3:08 AM
Hi,

Your fixes work fine! Thanks!

The flashComponent is on a tab in a tabpanel nested in another tabpanel.
It would be great if your component could autodetect this and automagically attach listeners to it's parenttabpanels for the beforetabchange and tabchange events...

I did this for my situation like this, but in general, there's no previewPanel.


getListenerConfig : function() {
var pItems = [this.container];
var ow = this.container.ownerCt;
while(ow != null) {
if(ow.constructor.xtype=='tabpanel') {
pItems.push(ow);
}
ow = ow.ownerCt
}

return {
beforetabchange: {
fn: function(p,newTab,currentTab) {
if(newTab.previewPanel != this.container) {
this.hideFlashComponent();
}
},
scope : this,
items : pItems
},
tabchange: {
fn: function(p,newTab) {
if(newTab.previewPanel == this.container) {
this.showFlashComponent();
}
},
scope : this,
items : pItems
},...

Ronaldo

Ronaldo
31 Jul 2009, 3:25 AM
Ow, still a small issue... When I reload the player using



this.previewPanel.remove(this.flashComponent);
this.flashComponent = this.getFlashComponent(data);
this.previewPanel.add(this.flashComponent);
this.doLayout();
where this is an Ext.Panel, it displays fine.
However when I now start the flash movie, and then collapse its surrounding panel, the movie stops playing.
It should continue playing.

After expanding the panel, the movie has jumpt to the start and is not playing any more.
It just has something to do with the reloading code above, because this scenario works fine when I don't reload the flashComponent using the code above.

Best regards,
Ronaldo

casbar
25 Aug 2009, 2:58 AM
Hello,

really great Extension... !! :)
But I have one problem, when I implement the last version of the ManagedIFrame in my application, and I want to close a window, containing a FlashComponent, the Flash movie doesn't will disappear!

Any idea?
Thankyou,
casbar

darkdestruction
17 Nov 2011, 3:51 AM
Hello Folks!,

I fixed a bug in flashControl Component.
When you had this component into a window which is child of a "renderTo" attribute Ext.Window, You could not destroy it, causing a crash (the component remained in the Window). Bellow, follow the solution:





autoEvents : [ 'expand',
'beforeexpand',
'collapse',
'beforecollapse',
'activate',
'deactivate',
'maximize',
'close' //add "close" to autoEvent
],

autoInstallListeners : function() {
//preserve the old code here...

//Destroy flashComponent when the last container is a child Window case (container.container):
if (activeEvents['close'] && container.getXType() == 'window') {

var masterContainer = container.container instanceof Ext.Element? Ext.getCmp(container.container.id):container.container;
masterContainer.on('close',this.onDestroy,this);
this.appliedListeners.push([
masterContainer, 'close', this.onDestroy, this
]);
}
}


That worked for me!!!

ThorstenSuckow
17 Nov 2011, 5:18 AM
Sweet, thanks. Which Ext-version did you use with this code?

darkdestruction
17 Nov 2011, 8:08 AM
I'm using Ext 3.4