PDA

View Full Version : Suggestion on writing extensions



alexb
27 Mar 2010, 12:44 AM
What do you think about the following event-based 'pattern' of writing extensions?



Ext.namespace('Ext.ux');

Ext.ux.ShowTime = Ext.extend(Ext.Panel, {
btnShow : null

,constructor:function(config) {
config.listeners = config.listeners || {};
Ext.applyIf(config.listeners, {
//this syntax is critical to preserve scope
'timeavailable' : {
fn: this.OnTimeAvailable,
scope: this
}

//reference implementation
, 'timerequired' : function(panel){
panel.fireEvent('timeavailable', new Date());
}
, scope: this
});
Ext.ux.ShowTime.superclass.constructor.apply(this, arguments);
}

,OnTimeAvailable:function(time) {
//validate parameters
alert(time);
}

,initComponent:function() {
// call parent
Ext.ux.ShowTime.superclass.initComponent.apply(this, arguments);
this.initEvents();
}

,initEvents:function() {
Ext.ux.ShowTime.superclass.initEvents.apply(this, arguments);

this.addEvents(
/**
* @event timerequired
* Fires when the show time button is clicked.
* @param {Ext.Panel} this This panel
*/
'timerequired'

/**
* @event timeavailable
* Fires when time is available to be shown.
* @param {mixed} time

*/
, 'timeavailable'
);


}

,onRender : function(ct, position){
Ext.ux.ShowTime.superclass.onRender.call(this, ct, position);

btnShow = new Ext.Button({
text: 'Show time',
handler: function(){
this.fireEvent('timerequired', this);
},
scope: this
});
btnShow.render(this.body);
}
});


It makes it very easy to replace functionality with custom behavior. E.g., you swap a PHP based implementation for an ASP.NET based one, or implement remote calls like in example below. Or an extension, demoed locally vs browser - server setting.

When an extension author includes a 'reference' implementation, another developer can see what is needed to adapt the extension to his needs.

Full code:



<!-- drop it to ext/examples/panel -->


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Panel</title>
<link rel="stylesheet" type="text/css" href="../../resources/css/ext-all.css" />

<!-- GC -->
<!-- LIBS -->
<script type="text/javascript" src="../../adapter/ext/ext-base.js"></script>
<!-- ENDLIBS -->

<script type="text/javascript" src="../../ext-all.js"></script>

<!-- Common Styles for the examples -->
<link rel="stylesheet" type="text/css" href="../examples.css" />

<style type="text/css">
.x-panel-body p {
margin:10px;
}
#container {
padding:10px;
}
</style>
</head>
<body>
<script type="text/javascript" src="../examples.js"></script><!-- EXAMPLES -->
<h1>Ext.Panel</h1>
<p>The js is not minified so it is readable. See <a href="panels.js">panels.js</a>.</p>

<div id="container">

</div>

</body>
</html>

<script>

Ext.namespace('Ext.ux');

Ext.ux.ShowTime = Ext.extend(Ext.Panel, {
btnShow : null

,constructor:function(config) {
config.listeners = config.listeners || {};
Ext.applyIf(config.listeners, {
//this syntax is critical to preserve scope
'timeavailable' : {
fn: this.OnTimeAvailable,
scope: this
}

//reference implementation
, 'timerequired' : function(panel){
panel.fireEvent('timeavailable', new Date());
}
, scope: this
});
Ext.ux.ShowTime.superclass.constructor.apply(this, arguments);
}

,OnTimeAvailable:function(time) {
//validate parameters
alert(time);
}

,initComponent:function() {
// call parent
Ext.ux.ShowTime.superclass.initComponent.apply(this, arguments);
this.initEvents();
}

,initEvents:function() {
Ext.ux.ShowTime.superclass.initEvents.apply(this, arguments);

this.addEvents(
/**
* @event timerequired
* Fires when the show time button is clicked.
* @param {Ext.Panel} this This panel
*/
'timerequired'

/**
* @event timeavailable
* Fires when time is available to be shown.
* @param {mixed} time

*/
, 'timeavailable'
);


}

,onRender : function(ct, position){
Ext.ux.ShowTime.superclass.onRender.call(this, ct, position);

btnShow = new Ext.Button({
text: 'Show time',
handler: function(){
this.fireEvent('timerequired', this);
},
scope: this
});
btnShow.render(this.body);
}
});

Ext.onReady(function(){
var p = new Ext.ux.ShowTime({
title: 'My Panel',
collapsible:true,
renderTo: 'container',
width:400
//html: Ext.example.bogusMarkup
});

var p2 = new Ext.ux.ShowTime({
title: 'My Panel2',
collapsible:true,
renderTo: 'container',
width:400
, listeners : {
'timerequired' : function(panel){
//call server here
panel.fireEvent('timeavailable', 'value from server');
}
}
});

});
</script>