SwarmOnline Menu Mobile
  • Home
  • About
  • Services
  • Portfolio
  • Blog
  • Contact

Recent Posts

  • PhoneGap and the TestFlight SDK – Taking it Further!
  • Integrating the TestFlight SDK into your PhoneGap Application
  • Retrieving References to Internal View Components
  • Launching Sencha Insights
  • Documenting your Sencha apps with JSDuck

Recent Comments

  • Stuart on Ext.ux.TouchCalendar – A Sencha Touch Calendar component
  • Stuart on Localising Sencha Touch and Ext JS applications with Ux.locale.Manager
  • Manuel Rodriguez on Localising Sencha Touch and Ext JS applications with Ux.locale.Manager
  • Remi Bloch on Ext.ux.TouchCalendar – A Sencha Touch Calendar component
  • Remi Bloch on Ext.ux.TouchCalendar – A Sencha Touch Calendar component

Archives

  • May 2013
  • March 2013
  • February 2013
  • December 2012
  • September 2012
  • August 2012
  • November 2011
  • October 2011
  • May 2011
  • March 2011
  • February 2011
  • January 2011
  • November 2010

Categories

  • Development Tips
  • Ext JS
  • News
  • Sencha Touch
  • Sencha Touch Extensions & Plugins
  • Web Design
  • Web Design & Development Blog

HOW TO: Create a Sencha Touch Plugin – Part 2 – making Ext.ux.PanelAction

4
19 Jan
2011
PanelActionScreenshot

Sencha Touch Extensions & Plugins

Web Design & Development Blog

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

Create a simple Sencha Touch Plugin - Part 2 - Tutorial Package.zip (166kb) (503)

or view the live demo (please use Safari, Google Chrome or your Smartphone!)

Demo – Making Ext.ux.PanelAction

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.

Click the individual Steps’ headings then you will be taken to the page we created in that step so you can follow our progress as we go along!

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.

Step 1 – Create our plugin structure and default config options

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.

Step 2 – Creating the Icon Markup

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.

Step 3 – Calculating the Icon’s Position

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.

Step 4 – Making the Icon Tappable

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!

Create a simple Sencha Touch Plugin - Part 2 - Tutorial Package.zip (166kb) (503)

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/
Tweet

4
  1. Gaz - Reply

    May 25, 2011 at 12:33 am

    Useful article, thanks,
    remove div id=”_mcePaste” in code at Step 4

    • Stuart - Reply

      May 25, 2011 at 11:06 am

      Hi Gaz,

      Thanks for the feedback!

      Good spot – I have updated the snippet :)

      Cheers
      Stuart

  2. Jake - Reply

    July 21, 2011 at 12:30 am

    Hi!

    Great plug-in. My one question though is where does the method iconEl.setLeft and iconEl.setTop come from? Are those pre defined JS functions?

    Thank you,

    Jake

    • Stuart - Reply

      July 21, 2011 at 10:06 am

      Glad you liked the plugin! The setTopand setLeftmethods are part of the Ext.Element class (http://dev.sencha.com/deploy/touch/docs/?class=Ext.Element). They set the Element’s top and left CSS properties to the specified value.

      Thanks
      Stuart

Leave a Comment - Cancel reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

About SwarmOnline

Based in Glasgow’s West End, SwarmOnline provide web development, cross platform mobile app development and training services for local and international organisations. We have expert knowledge of Sencha technologies and have been Sencha Partners since 2011. We specialise in creating dynamic, innovative and practical solutions.

Meet the Team...

Newsletter

Subscribe to our newsletter and we’ll keep you up-to-date. We don't do spam.

Get in touch!

Email: [email protected]   
Skype: andrew-swarmonline stuart-swarmonline   
Phone: 0141 438 2231   


© 2013 SwarmOnline Ltd. All Rights Reserved.

SwarmOnline Ltd is a Limited Company registered in Scotland, with company number SC411633. Our Registered Office is 1-2 249 Byres Road, Glasgow G12 8UB.