If you haven’t already read Part 1 of this mini blog series then I recommend you do before reading any further, but if you’re fairly confident with the basics of plugins then you can probably manage alright!Quick Recap
In the first post we learnt the basic structure of a plugin is that it extends the basic JavaScript Object class and must at least contain a single function called “init” which takes one parameter that is a reference to the parent component that the plugin is used in. We also learnt that the init method is called when the parent component is initialised but before it is rendered.
You can read the full HOW TO: Create a Sencha Touch Plugin – Part 1 post here.
A Real World Example
Today I’m going to talk you through creating a more useful example that was created for use in our Prop.erti.es application which was an entry in the Sencha Touch contest. Basically the plugin adds an icon to a floating, modal panel and allows actions to be carried out when a user taps it – such as close the panel, submit a form etc. You can read a full description and discussion about the plugin on its own blog article. A screenshot of what we’re aiming for can be seen below. Unfortunately I’m only going to go cover creating the basic plugin and its functionality and won’t go into every feature that it has.

Ext.ux.PanelAction Plugin Example
or view the live demo (please use Safari, Google Chrome or your Smartphone!)
As with all our tutorials make sure you have a basic HTML file setup with references to the Sencha Touch framework and with the basic Ext.setup code in there ready. If you don’t have this then download the Tutorial Package from the link above and you can follow each step with the relevant files from the package.
CSS Overview
I don’t want to go into huge detail with the CSS involved, it’s not very complex so I’m sure there won’t be any problems with it. There are two classes to worry about the x-panel-action-icon which gives the created element its basic styles and the iconClass that provides the image and sizes for what you want. I’m going to work with a basic 32px x 32px clos image defined in the x-panel-action-icon-close class.
.x-panel-action-icon
{
overflow: hidden;
position: absolute;
z-index: 99;
}
.x-panel-action-icon-close
{
background-image: url(data:image/png;base64,iVBORw0KGgoAA...);
width: 32px;
height: 32px;
}
All the CSS is included in the Tutorial Package but you can just copy and paste the CSS above into some <style> tags in your HTML file.
As we did before we’ll create our generic plugin code structure, which you can see below. We will also add a few configuration properties and their defaults that can be overwritten by the developer and used to customise the plugin.
Ext.ux.PanelAction = Ext.extend(Object, {
position: 'tl', // defines where icon sits ( t = top, b = bottom, c = centre; l = left, r = right, c = centre)
baseClass: 'x-panel-action-icon', // base CSS class (rarely changed)
iconClass: 'x-panel-action-icon-close', // CSS class to define background image and sizing
actionMethod: ['hide'], // functions to execute after tapping icon
constructor: function(config){
Ext.apply(this, config);
Ext.ux.PanelAction.superclass.constructor.apply(this, arguments);
},
init: function(parent){
this.parent = parent ; // cache a reference to the Parent component
}
});
Right, so what have we added?
The position property is going to hold a two letter string indicating the position our action icon sits; with the vertical position first, followed by the horizontal (t = top, b = bottom, l = left, r = right and c = centre).
The baseClass is a CSS class that has the basic stylings – this probably shouldnt need to be changed.
The iconClass defines the CSS Class that defines background image and size of our pressable action icon.
Finally, the actionMethod property holds either a name of a method, a reference to a method or an inline function, that will be executed when the icon is tapped, in the form of an array or as a single value.
We have also added a constructor that applies the config options supplied by the developer to the plugin, overwriting the defaults.
Lastly we have added the init method and stored a reference to the parent component so we can access it everywhere in the plugin, this will save us a lot of headaches with scope later on.
Our next step is to create the HTML markup required to display the pressable icon. We want this markup to be created when the panel is shown for the first time so we are going to hook it into the panel’s show event. The main reason we’re using this event is that we know everything will be rendered so there is no danger of referring non-existent HTML elements.
We only want to create a single DIV element to display the icon so we use the createChild method of the Panel’s underlying Ext.Element class to create it. When we create this element we will configure it using the cls config option so the created element has our baseClass and iconClass properties applied to it. You will also notice that we store a reference to the created Ext.Element in a property named iconEl which we will use later on the code, it also a way of ensuring we don’t do this creation code every time the panel is shown.
The snippet code below shows the code for creating the icon element and the screenshot of Chrome’s Developer Tools shows the underlying HTML that is actually created.
...
init: function(parent){
this.parent = parent; // cache a reference to the Parent component
parent.on({
show: this.onParentShow,
scope: this
});
},
/**
* Create the iconEl when panel is shown
* @param {Object} component
*/
onParentShow: function(component){
if (!this.iconEl) { // only run when iconEl hasn't been created
// Create the Icon Element
this.iconEl = component.getEl().createChild({
cls: this.baseClass + ' ' + this.iconClass
});
}
}
...

Highlighted line shows created element
It’s easy to get bogged down in JavaScript and Sencha’s components and their configuration options and forget that at the end of the day we’re still just creating HTML. Try to keep an eye on what HTML is being created by the framework (via the Elements tab of the Developer’s Tools) because it is a very useful learning tool to get a much deeper understanding of what the framework is doing instead of leaving it as a completely black box.
As you will have noticed from testing the previous step the icon isn’t in the right place, its just sort of floating about. So next we’re going to figure out where it needs to be based on the position config option. Unfortunately this is where we need some maths so bear with me with this boring section!
Firstly we’re going to store the width and height of the created element (in the onParentShow method just below the createChild call) which we will use later in our calculations. We do this by simply using the getHeight and getWidth methods of the Ext.Element class (see the code below).
...
// Cache the element's Width and Height for use later
this.iconDimensionX = this.iconEl.getWidth();
this.iconDimensionY = this.iconEl.getHeight();
...
Next we create a new method called positionIcon which will do all the calculations to reposition our new element.
/**
* Positions the Close Icon based on config options
*/
positionIcon: function(){
var characters = this.position.split(''); // get the Y and X axis positions
var top = 0;
var left = 0;
if (characters.length >= 2) {
var posY = characters[0].toLowerCase();
var posX = characters[1].toLowerCase();
// Figure out Y position
switch (posY) {
case 't':
top = -1 * (this.iconDimensionY / 2);
break;
case 'b':
top = this.parent.getHeight() - (this.iconDimensionY / 2);
break;
case 'c':
top = (this.parent.getHeight() / 2) - (this.iconDimensionY / 2);
break;
}
// Figure out X position
switch (posX) {
case 'l':
left = -1 * (this.iconDimensionX / 2);
break;
case 'r':
left = this.parent.getWidth() - (this.iconDimensionX / 2);
break;
case 'c':
left = (this.parent.getWidth() / 2) - (this.iconDimensionX / 2);
break;
}
// Set the Element with the new positions
this.iconEl.setLeft(left);
this.iconEl.setTop(top);
}
}
Although quite a long daunting method it’s actually fairly simple and repetitive. Firstly we split our position property so we have the individual letters in an array (e.g. [t, l] = top, left). For safety we check we actually have 2 elements in the array and we turn them to lowercase.
We now know where the dev wants the icon to be placed so we just have to figure out the numbers. This is done with 2 switch statements (one for Y axis, another for the X axis) which, depending on what position has been configured, calculates the top and left positions. I’m not going to explain all the maths (its fairly straightforward) but the idea is that the centre of the icon gets placed on the edge of the panel.
Finally we set the left and top properties using the respective set methods. If you open the Step 3 HTML file from the Tutorial Package you should see the icon positioned at the Top Left corner of the panel.

The icon has been positioned in Top Left of Panel
Now the plugin is taking shape! All that is left now is to make it interactive.
We want to make this plugin as easily configurable as possible and so that is why we’re allowing the actionMethod config option to allow arrays or just single values. This means we have to add some code to deal with both cases. All we’re going to do is convert a single value to an array so we always know we’re dealing with an array of values, even if it is only 1 element long.
// in the init method just after "this.parent = parent;"
// Make it an array if it isn't so we know what we're dealing with
if (!Ext.isArray(this.actionMethod)) {
this.actionMethod = [this.actionMethod];
}
Right, now the fun bit! Let’s make it do something!
We’re going to add 2 methods: one called onIconTap which is going to be the tap event handler and anbother called doCallbackCall which is a helper method that figures out how to execute the actionMethod elements.
/**
* Handler for the Tap on the Icon
*/
onIconTap: function(){
// loop through the actionMethod array calling each one
for (var i = 0; i < this.actionMethod.length; i++) {
this.doCallbackCall(this.actionMethod[i]);
}
},
/**
* Runs the callback method, depending on if it's a reference to a method or the name of one
* @param {Object} method - Can be string with method name or reference to a function
*/
doCallbackCall: function(method){
if (Ext.isFunction(method)) {
method();
}
else {
this.parent[method]();
}
}
The onIconTap is very straightforward, it is a simple for loop that calls the doCallbackCall method passing in the current element of the actionMethod property.
The doCallbackCall method then works out how to call whatever is passed in. Because the actionMethod property can contain strings of method names, references to method or inline functions there are two ways to call them. The If statement checks if the value is an actual function, if it is then we just stick some parenthesis on the end and it will run. The else portion assumes that if the method isn’t an actual function then it must be a string containing the name of a method that exists on the parent component. Thanks to the ‘object’ nature of JavaScript we can refer to this method within the parent as a key, like you might do in a Dictionary collection – stick parenthesis on the end and the method will be executed.
The last piece of the puzzle is to attach this event handler to the tap event of the icon element we created at the beginning. We add this code to the onParentShow method just below where we called the positionIcon method, it is a simple use of the on method.
...
// Attach Tap events to Icon
this.iconEl.on({
tap: this.onIconTap,
scope: this
});
...
And there you have it! If you open the Step 4 HTML file you will see the pluign working – if you tap on the icon the panel will hide.
Now have a play with the configuration options and see what you can do. Try using a custom iconClass to show a different icon; changing the position or add some new actionMethods!
If you want to see the full plugin which contains a few other features such as a pressed state, a full cleanup of handlers etc and a few other goodies then check out the blog post or download it here.
Leave it a comment if you’ve created your own plugin and share it with the community! Or just if you have questions or suggestions!
http://www.swarmonline.com/2011/01/ext-ux-panelaction-add-action-buttons-to-floating-sencha-touch-panels/