Chapter 5. Events

In the previous chapter, we took a closer look at the components available in Sencha Touch. However, simply creating components isn't enough to build an application. The components still need to communicate with each other in order to make our application do anything truly useful. This is where events come into play.

In this chapter, we will examine events in Sencha Touch: what they are, why we need them, and how they work. We will discuss how to use listeners and handlers to make your application react to the user's touch as well as to events happening behind the scenes. We will also cover some helpful concepts such as observable capture and event delegation. We will finish up with a walkthrough of the touch-specific events and a look at how you can get more information from the Sencha Touch API.

The chapter will cover the following points:

  • Events

  • Listeners and handlers

  • Ext.util.Observable

  • Event delegation

  • Touch-specific events

  • Additional information on events

What are events?

As programmers, we tend to think of code as an orderly sequence of instructions, executing one line, and then the next, and the next. It's easy to lose sight of the fact that our code really spends a lot of time sitting and waiting for the user to do something. It's waiting for the user to press a button, open a window, or select from a list. The code is waiting for an event.

Typically, an event occurs right before or right after a component performs a specific task. When the task is performed, the event is broadcast to the rest of the system, where it can trigger specific code or be used by other components to trigger new actions.

For example, a button in Sencha Touch will trigger an event whenever it is tapped. This tap can execute code inside the button that creates a new dialog box, or a panel component can "listen" to what the button is doing and change its color when it "hears" the button trigger a tap event.

Given that most applications are intended for human interaction, it's safe to say that a lot of the functionality of your programs will come from responding to events. From a user's perspective, the events are what make the program actually "do" something. The program is responding to the user's request.

In addition to responding to requests, events also have an important role to play in making sure that things happen in the correct order.

Asynchronous versus synchronous

Albert Einstein once remarked, "The only reason for time is so that everything doesn't happen at once". While this might seem like an offhand comment, it actually has a great deal of relevance when it comes to writing code.

As we write our code in Sencha Touch, we are directing the web browser to create and destroy components on the user's screen. The obvious limitation of this process is that we cannot manipulate a component before it gets created, nor after it's destroyed.

This seems pretty straightforward at first glance. You would never write a line of code that tries to talk to a component on the line before you actually create the component, so what's the problem?

The problem has to do with asynchronous actions within the code. While most of our code will execute sequentially or in a synchronous fashion, there are a number of cases where we will need to send out a request and get back a response before we can proceed. This is especially true in web-based applications.

For example, let's say we have a line of code that builds a map using a request from Google Maps. We will need to wait until we have received a response from Google and rendered our map before we can begin fiddling about with it. However, we don't want the rest of our application to freeze while we wait on the response. So, we make an asynchronous request, one that happens in the background, while the rest of our application goes about its business.

These asynchronous requests are called AJAX requests. AJAX stands for Asynchronous JavaScript and XML. If we configure one of our buttons to send out an AJAX request, the user can still do other things while the application is waiting for a response.

On the interface side of things, you will probably want to let the user know that we made the request and are currently waiting for a response. In most cases, this means displaying a "loading" message or animated graphic.

Using events in Sencha Touch, we can show the loading graphic by tying into the beforerequest event in the AJAX component. Since we need to know when to make the loading message disappear, our component will wait for the requestcomplete event from our AJAX request. Once that event fires, we can execute some code to tell the loading message to go away. We can also use the requestexception event to inform the user whether errors occurred during the request.

Using this type of event-driven design allows you to respond quickly to the user's actions, without making them wait for some of the more time-consuming requests your code needs to perform. You can also use the events to inform the user of errors. The key to events is getting your other components to "listen" for the event, and then telling them how to handle the information they receive.

Listeners and handlers

Every component in Sencha Touch has a long list of events that it generates. Given the number of components you will likely have in your application, a lot of chatter is going on.

Imagine a party with 100 people, all having lots of different conversations. Now imagine trying to pick out all of the useful information from each conversation. It's impossible. You have to focus on a specific conversation in order to gather anything useful.

In much the same way, components also have to be told what to listen for, or else, such as our unfortunate partygoer, they would quickly be overwhelmed. Fortunately for us, there's a confuration for that.

A listeners configuration tells the component what events it needs to pay attention to. Listeners can be added like any other configuration option in Sencha Touch. For example, the configuration option on a panel might look like the following:

listeners: {
 tap: {
element: 'body',
fn: function(){ Ext.Msg.alert('Single Tap'), }
}
}

This configuration option tells the panel to listen for the tap event, when the user taps once on the body element of the panel. When the tap event occurs, we execute the function listed in the fn configuration option (this is typically referred to as a handler). In this case, we pop up a message box with the words Single Tap.

Notice that the items in our listeners configuration are always part of an object (curly braces on either side), even if there is only one event we are listening for. If we were to add a second event, it would loolike the following:

listeners: {
 tap: {
  element: 'body',
  fn: function(){ Ext.Msg.alert('Single Tap'), }
 },
 hide: {
  fn: function(){ this.destroy(); }
 }
}

We can also get information back from the listener and use it in our handler functions. For example, the tap event sends back the event object, the DOM element that was clicked, and the listener object itself, if we have the following listener on a panel:

listeners: {
  tap: {
    element: 'body',
    fn: function(event, div, listener) {
      console.log(event, div, listener);
    }
  }
}

When the user taps inside the panel, we will get the following information on the console:

Listeners and handlers

Tip

Arguments for events

You will notice that certain values are passed to our event by default. These default values can be found in the Sencha Touch API event documentation for each component, at http://docs.sencha.com/touch/1-1/.

Each event will have its own default values. Select a component from the Sencha API documentation, and then click Events at the top of the page, to see a list of all events for the component. The description of each event will include its default arguments.

As you can see from the console, our event object contains a Unix timestamp for when the tap occurred, the x and y coordinates of the tap itself, as well as the entire content of the div tag that was tapped. You may have also noticed that our tap event is referred to as a click event in our debug output. In Sencha Touch, the tap and click events are aliased to one another. This preserves compatibility between the desktop browser's traditional click event and the mobile browser's tap event.

We can use all of this information inside our function.

For this example, we will create a simple panel with a red container. Our tap listener will change the size of the red box to match where we tap on the screen:

new Ext.Application({
  name: 'TouchStart',
  launch: function() {
    var eventPanel = new Ext.Panel({
      fullscreen: true,
      layout: 'auto',
      items: [{
        xtype: 'container',
        width: 40,
        height: 40,
        id: 'tapTarget',
        style: 'background-color: #800000;',
      }],
      id: 'eventPanel',
      listeners: {
tap: {
          element: 'body',
          fn: function(event, div, listener) {
              var cmp = Ext.getCmp('tapTarget'),
              cmp.setWidth(event.xy[0]);
              cmp.setHeight(event.xy[1]);
              console.log(event.y);
          }
        } 
      }
    });
    this.viewport = eventPanel;
  }
});

If we run this code with the console open, we can see that the X and Y coordinates of where we tap appear in the console. Our box also grows or shrinks to match these values.

Listeners and handlers

As you can see from the code, we listen for the tap event. We then grab the container component using Ext.getCmp('tapTarget'),, and change the size, based on the value we got back from the tap event:

tap: {
 element: 'body',
 fn: function(event, div, listener) {
  var cmp = Ext.getCmp('tapTarget'),
  cmp.setWidth(event.xy[0]);
  cmp.setHeight(event.xy[1]);
  console.log(event.xy);
 }
}

Since event.xy is an array, we need to grab the individual values using event.xy[0] and event.xy[1].

Adding listeners and events dynamically

Listeners can also be added to a component dynamically. If we were to add a new listener to our previous example, it would look something as the following:

var cmp = Ext.getCmp('tapTarget'),
cmp.on('resize',
function() {
var h = this.getHeight();
var w = this.getWidth();
this.update('height: '+h+'<br>width: '+w)
}, cmp);

This code will get the height and width of the container. It will then use the update method to add the height an d width as text to the container, when the resize event fires.

However, there is one slight problem with this approach: the resize event only fires when a container is manually resized by dragging the lower-left corner of a manually-resizable container. Since ours is changed programmatically, the resize event is never fired.

We can fix this by manually firing the event in our previous code using the fireEvent() method:

listeners: {
  tap: {
    element: 'body',
    fn: function(event, div, listener) {
      var cmp = Ext.getCmp('tapTarget'),
      cmp.setWidth(event.xy[0]);
      cmp.setHeight(event.xy[1]);
      console.log(event.xy);
      cmp.fireEvent('resize'),
    }
  }
}

The fireEvent() method can be used with both existing events as well as your own custom events.

Custom events

While Sencha Touch components respond to a large number of events, it can sometimes be helpful to fire custom events within your application.

For example, you could fire a custom event called vikinginvasion, using the same type of syntax as our previous example:

cmp.fireEvent('vikinginvasion'),

You can then add a listener in your code for vikinginvasion, along with a function to handle the event:

var cmp = Ext.getCmp('tapTarget'),
 cmp.on('vikinginvasion',
 function() {
alert("Man The gates!");
 }, this);
Custom events

You can also check a component to see if it has a specific listener, using the hasListener() method:

var cmp = Ext.getCmp('tapTarget'),
if(cmp.hasListener('vikinginvasion') {
  console.log('Component is alert for invasion'),
} else {
  console.log('Component is asleep at its post'),
}

There are also a number of helpful options you can use to contrl how the listeners will check for events.

Listener options

For the most part, listeners can simply be configured with the event name, handler, and scope, but sometimes you need a bit more control. Sencha Touch provides a number of helpful options to modify how the listener works:

  • delay: This will delay the handler from acting after the event is fired. It is given in milliseconds.

  • single: This provides a one-shot handler that executes after the next event fires and then removes itself.

  • buffer: This causes the handler to be scheduled to run as part of an Ext.util.DelayedTask component. This means that if an event is fired, we wait a certain amount of time before we execute the handler. If the same event fires again within our delay time, we reset the timer before executing the handler (only once).

  • element: This allows us to specify a specific element within the component. For example, we can specify a body within a panel for a tap event. This would ignore taps to the docked items and only listen for a tap on the body of the panel.

  • target: This will limit the listener to the events coming from the target and it will ignore the same event coming from any of its children.

Using the different listener options would look something like the following:

var cmp = Ext.getCmp('tapTarget'),
cmp.on('vikinginvasion', this.handleInvasion, this, {
single: true,
delay: 100
});

This example would add a listener for vikinginvasion and execute a function called this.handleInvasion. The handler would only execute once, after a 100-millisecond delay. It would then remove itself from the component.

This basic list of configuration options gives you quite a bit of flexibility when adding listeners. However, there is one additional configuration option available in listeners that will require a bit more explanation. It's called scope.

Scope

Within your handler function is a special variable called this. Usually, this refers to the component that fired the event, in which case, the scope would typically be set to scope: this. However, it's possible to specify a different value for scope in your listener configuration. From our previous example, a change in scope might look like the following:

tap: {
 element: 'body',
 scope: eventPanel,
 fn: function(event, div, listener) {
  this.setWidth(event.xy[0]);
  this.setHeight(event.xy[1]);
  console.log(event.xy);
 }
}

In this example, the scope (and as such, the variable this) has been changed to our eventPanel component. We can now set values directly, instead of having to use Ext.getCmp('tapTarget'), to get the panel at the beginning of our function.

We can also set the scope component in a similar fashion, by using the on method to add a listener:

var myPanel = new Ext.Panel({…});
var button = new Ext.Button({…});

button.on('click', function() {
  console.log('This should be myPanel:', this);
}, myPanel);

Here, we added myPanel as an argument after the handler definition, which means that when the click event is fired and the handler function is called, you will be able to access myPanel by referring to this.

Within handler functions, you aren't guaranteed to have access to the same variables when you define the function. Changing the scope of a function can allow you to access a specific variable that's not easy to get to with Ext.getCmp() or Ext.get() . It can also be a simple convenience for getting to the component you are most likely to use in the function.

While scope may be a hard concept to grasp, it is a very useful part of the listener configurations.

Removing listeners

Normally, listeners are removed automatically when a component is destroyed. However, sometimes you will want to remove the listener before the component is destroyed. To do so, you'll need a reference to the handler function you created the listener with.

So far, we've been using anonymous functions to create our listeners, but if we're going to remove the listener, we have to do it a bit differently:

var myPanel = new Ext.Panel({…});

var myHandler = function() {
  console.log('myHandler called.'),
};

myPanel.on('click', myHandler);

This can be a good practice, since it allows you to define the handler functions once and reuse them wherever you need them. It also allows you to remove the handler later:

myPanel.removeListener('click', myHandler);

Tip

In Sencha parlance, on() is an alias for addListener() and un() is an alias for removeListener(), meaning that they do the exact same thing. Feel free to use whichever you prefer, when dealing with events.

Managed listeners

In some cases, listeners are part of a relationship between two objects, and when one of the objects is destroyed, the listener is no longer necessary.

For example, say you have two panels, panel1 and panel2, and you want to change the size of panel1 to match the size of panel2, whenever panel2 is resized. You could put a listener on the resize event for panel2, but if panel1 were to be destroyed, the listener would still be there.

You could add an additional listener to panel1 that would wait for the destroy event and then remove the listener from panel2, but that could become cumbersome quickly.

You can get around this particular problem by using a managed listener. A managed listener works a little bit differently from a regular listener:

var panel1 = new Ext.Panel({…});
var panel2 = new Ext.Panel({…});

panel1.addManagedListener(panel2, 'resize',
  function() {
  console.log('Panel 2 was resized.'),
panel1.setSize(panel2.getSize());
  }
);

This can get a bit confusing, because when we call panel1.on() or panel1.addListener(), we're adding a listener to panel1. However, when we call addManagedListener(), the first argument is actually a different component we're adding the listener to. In this case, we're adding a resize listener to panel2 that will automatically be removed if panel1 is destroyed.

Essentially, addManagedListener adds listeners that clean up after themselves, which can help greatly with memory management.

Handlers and buttons

As you might have noticed from some of our previous code, buttons have a default configuration called handler . This is because the purpose of a button is generally to be clicked or tapped. The handler configuration is just useful shorthand for adding the tap listener. As such, the following two pieces of code do exactly the same thing:

var button = new Ext.button({
text: 'press me',
  handler: function() {
    this.setText('Pressed'),
  }
})

var button = new Ext.button({
  text: 'press me',
  listener: {
tap: {
      fn: function() {
        this.setText('Pressed'),
     }
    }
  }
});

This same default handler behavior applies to tabs as well. The handler simply serves as a quick way to access the most routinely used event for the component.

Suspending and queuing events

Sometimes, you will want to keep components from firing events. Perhaps you want to do some additional processing on data returned from an AJAX query, or you want to write some custom code to handle resizing your component. Observable gives you a way to do so via the suspendEvents() and resumeEvents() methods. You can call these methods on any object that extends Observable, such as a panel:

var myPanel = new Ext.Panel({…});

myPanel.suspendEvents();

myPanel.setHeight(100);
myPanel.setWidth(100);

myPanel.resumeEvents();

Normally, the setHeight() and setWidth() functions cause the resize event to fire. In this example, though, we essentially put the panel to sleep while we resize it, and then wake it back up when we're done. In this case, the resize event will never fire, so any components listening for that event will never hear it.

Note that we only suspended events on the myPanel object. If we had resized another panel at the same time, then that panel's events would still have fired.

This is very useful when you need to do things behind the scenes in your application, but sometimes you'll want to have the events fire after you're done with your work, so that the other components can catch up. In that case, simply pass true as the argument to suspendEvents():

myPanel.on('resize', function() {
  console.log('Resized!'),
});

myPanel.suspendEvents(true);

myPanel.setHeight(100);
myPanel.setHeight(100);
console.log('Resuming Events.'),
myPanel.resumeEvents();
Suspending and queuing events

You can see how the Resuming Events line comes before the resize events. This is because we didn't fire any events until after the console.log() and resumeEvents() calls.

You should be very careful with suspending events. Much of the built-in Sencha Touch functionality relies heavily on events, and suspending them can cause unexpected behavior.

Common events

Let's take a look at our old friend Ext.Component and see some of the common events available to us. Remember, since most of our components will inherit from Ext.Component, these events will be common across most of the components we use.

Most of our events will fall into two categories. The first set of events revolves around the creation of the component.

When the web browser executes your Sencha Touch code, it writes the components into the web page as a series of div, span, and other standard HTML tags. These elements are also linked to code within Sencha Touch that standardizes the look and functionality of the component for all supported web browsers. This process is referred to as rendering the component.

This rendering takes place in a number of stages, each of which fires an event:

  • beforerender: Before the render process begins

  • added: When the component is added to the container

  • beforeactivate: Before the component is visually activated

  • activate: When the component is visually activated

  • render: After the component's HTML is rendered

  • afterrender: After rendering is finished

These events give you a number of places to interact with your component before, during, and after the rendering process.

The second set of events is concerned with the actions taken by or done to the component itself. These events include:

  • show: Fires when the show method is used on the component

  • hide: Fires when the hide method is used on the component

  • destroy: Fires when the component is destroyed

  • disable: Fires when the disable method is used on the component

  • enable: Fires when the enable method is used on the component

  • orientationchange: Fires when the orientation of the device is changed

  • remove: Fires when the component is removed from a container

  • resize: Fires after the component is resized

These events provide a way to base the actions of your code on what is being done by, or done to, your components.

Each component will also have some specific events associated with it. For a list of these events, please consult the API docs at http://docs.sencha.com/touch/1-1/. Just select a component from the list on the left side and click the Events button at the top of the page.

Ext.util.Observable

Ext.util.Observable is the base class that handles listening to, and firing of, events for all Sencha Touch components. Any class that fires events extends Ext.util.Observable. For the most part, you won't need to directly use Ext.util.Observable itself, since it comes built into almost every Sencha Touch component, but there are a few cases where using it directly can make things easier.

Centralizing event handling with Observe

Sometimes, over the course of building an application, you will find yourself adding the same listeners to the same kind of objects multiple times. For large applications, this can take up quite a bit of memory. That's where Ext.util.Observable.observe() comes in. This method will allow you to add listeners to a class, instead of a particular instance of that class. Normally, when we add listeners, we do something such as this:

var panel = new Ext.Panel({…});
panel.on('resize', function(){…});

The listener will only run if that exact panel is resized. To add a listener to all Ext.Panel components, you can pass the component constructor you want to observe, then add your listeners:

Ext.util.Observable.observe(Ext.Panel);
Ext.Panel.on('resize', function(){…});

You'll notice that we didn't create a new panel here. Instead, we added the resize listener to Ext.Panel itself. Now, any panel you create with the new Ext.Panel() component, it will have the resize listener enabled automatically.

Additionally, this gives you a single place to update when you need to make changes to the resize listener and function. This type of class-based listener can save time, memory, and a lot of headaches.

Capture: a tool for debugging

Ext.util.Observable.capture is a static method. This means you won't have to create a new instance of an object—you can call it directly. This method will call a handler for every single event that an object fires, which can come in handy when you're trying to figure out if you've added listeners to the proper event and if those events are firing.

Using our resizing eventPanel example, add the following line after this.viewport = eventPanel;:

Ext.util.Observable.capture(eventPanel, function() {
  console.log('The eventPanel fired an Event:', arguments);
});
Capture: a tool for debugging

As you can see, this generates a lot of console lines. The first argument to the function will always be the event name, and the subsequent arguments will be the arguments that are typically passed to that particular event. If you want to start capturing events only after a certain known event fires, you can add the capture statement to a listener. For example, if you wanted to only start capturing events after the panel was rendered, you would do someting such as the following:

listeners: {
  render: {
    fn: function(myPanel) {
      Ext.util.Observable.capture(eventPanel,
      function() {
        console.log('The eventPanel fired an Event:', arguments);
      });
    }
  }
}

Now, Ext.util.Observable.capture will only be started once the render event has fired. From that point on, it will continue to capture all events fired by the panel.

You can stop capturing with Ext.util.Observable.releaseCapture(), as well. Say we want to stop capturing events after a resize event. Then, in our capture function, we could do the following:

Ext.util.Observable.capture(eventPanel, function() {
  console.log('The eventPanel fired an Event:', arguments);
   if (arguments[0] == 'resize') {
     Ext.util.Observable.releaseCapture(eventPanel);
   }
});

Tip

Even with releaseCapture() handy, you want to be very sure to remove any capture statements from your code before deploying in production, as they can be very memory- and processor-intensive.

Event delegation

When a component in Sencha Touch fires an event, the event "bubbles up" the chain to the parent component. This gives us some interesting opportunities with regards to memory and efficiency.

Events and memory

One of the common uses of event delegation is in lists. Let's say, we have a list of people such as those you would find in a common address book. When a name in the address book is clicked, we switch to the details panel with all of the contact information. This is a pretty straightforward setup most of us would recognize.

However, let's say we want to add a phone icon to each of our list items. When the phone icon gets clicked, the person's phone number is dialed. You might be inclined to add a click handler for each icon, but this is a very bad idea, because all of those listeners take up space in memory.

An address book with 400 people would have 400 listeners. This will slow down a web-based application, as it tries to listen to 400 separate elements within the DOM (in addition to everything else in your code that has a listener).

However, you can get around this problem using event delegation.

Delegating events

Let's start with a very simplified version for our contact list:

var contactList = new Ext.List({
  tpl: '<tpl for="."><li><img src="images/phone.png"/><h1>{contactName}</h1></li></tpl>',
  listeners: {
    el: {
      tap: callContact,
      delegate: 'img'
    }
  }
});

Unlike our previous examples, where we instructed the component which event to listen to, in this case, we tell the component where to listen for the event. In this case, we chose el, which is a property common to all components and basically means within the item (we could also use body).

Now that the component knows where to listen, we tell it what to listen for on the line tap: callContact. This also tells the List component what to run when the tap event occurs.

The last line, delegate: 'img' delegates the event to any img tag inside our List component. In this case, it would be our phone.png icon on each row of the list.

The result is a single listener, which checks to see if an image is tapped in our list.

This saves on memory, and also means that if you add or remove any list items, you don't have to add and remove listeners, too.

Touch-specific events

In addition to component events, Sencha Touch also understands a number of touch-specific events. These events include:

  • touchstart: An event that records the initial contact point with the device.

  • touchend: An event that records where the contact ended on the device.

  • touchmove: An event that records where the touch moved (this one will fire off as a series of events that map the path of the user's touch along the screen).

  • touchdown: An event that records when the element is touched as part of a drag or swipe.

  • dragstart: An event that records when the element is initially dragged.

  • drag: Similar to touchmove, drag tracks the path of the element, when dragged.

  • dragend: An event that records where the element stopped being dragged.

  • singletap: A single tap on the screen. This will fire once for the first tap, when a screen is double-tapped. It will not fire on the second tap.

  • tap: A tap on the screen. This will fire both for the first and second tap, when a screen is double tapped.

  • doubletap: Two quick taps on the screen.

  • taphold: A tap and hold on the screen.

  • tapcancel: An event that fires when you stop tap holding.

  • swipe: A single finger brushed across the screen from left to right.

  • pinch: Two fingers brought together in a pinching motion.

  • pinchstart: Where the pinch started.

  • pinchend: Where the pinch ended.

There is one small caveat to note with these touch-specific events: with the exception of tap and doubletap, Sencha Touch is actually receiving the events from the web browser rather than the component itself. Since the web browser is doing our listening for us, we need to attach our listener to something the web browser understands.

This means that instead of binding the event to the component itself, we have to bind the event to the underlying element of the component.

Tip

Component versus element

One of the harder concepts for people new to web programming is the relationship between the web browser and the Sencha Touch components. At its core, when a Sencha Touch component is rendered in the web browser, it gets translated into a complex series of div and span that the web browser can read and display. When we refer to the underlying element of the component, we are talking about one of these div containers.

Since a WebKit-based browser, such as Safari or Chrome, is designed to understand all of our touch-specific events, the Sencha Touch component can be instructed to monitor a div tag on the web page to see if these events occur.

Additionally, since the component can only monitor a div tag, it can only do it after the div tag has been rendered to the web page. This means we have to set our component to listen for the render event, and then tell it to add the monitoring. It looks something like the following:

new Ext.Application({
  name: 'TouchStart',
  launch: function() {
    var eventPanel = new Ext.Panel({
      fullscreen: true,
      layout: 'fit',
      html: 'Tap Me',
      id: 'eventPanel',
      listeners: {
        afterRender: function() {
          this.mon(this.el, {
          swipe: this.event2Console
          });
        }
      },
      event2Console: function(e) {
        console.log(e);
      }
    });
    this.viewport = eventPanel;
  }
});

We create our panel, as usual, and we add a listener for afterRender. This tells the panel that, once it exists within the browser window, it should execute the following code (in this case, we want it to run):

this.mon(this.el, {
  swipe: this.event2Console
});

This will cause Sencha Touch to listen for browser events generated by panel's DOM element, rather than the panel itself. The element then listens for the swipe event to occur. When the swipe event occurs, we execute our function this.event2Console.

Notice that we did things a bit differently this time. Usually, we create the function as part of the listener:

this.mon(this.el, {
  swipe: function(e) {
    console.log(e);
  }
}

Instead of that, we added the function onto the component itself, just as a configuration object:

event2Console: function(e) {
  console.log(e);
}

We then referenced the function as this.event2Console. This can be incredibly useful when you want to call the function from multiple places within the component. Both methods will produce the same result: a console log with our event object.

Touch-specific events

As you can see, we get a considerable amount of information from this event, including direction, distance, deltaX, time, and an event type. We can use this information as follows:

this.update(e.type+':'+e.direction+':'+e.distance);

This method can be added to our this.event2Console function, to update our panel with the type, direction, and distance of our swipe. Give it a try.

Also, play around with changing the swipe event in the code to any of the other functions in the list. Get a feel for what triggers each event and what information they return.

By using these touch events and the other events built into Sencha Touch, your program should be able to respond to just about any situation.

Additional information on events

The best place to get information about events is the Sencha Touch API docs at http://docs.sencha.com/touch/1-1/. Select a component in the list on the left, and look for the Events button at the top. You can click Events to go to the beginning of the section or hover your mouse pointer to see the full list of events and select a specific event from that list.

Clicking the down arrow next to the event will display a list of parameters for the event and any available examples on how the event can be used.

Another good place to find out about touch-specific events is the Kitchen Sink example application (http://dev.sencha.com/deploy/touch/examples/kitchensink/). Inside the application is a Touch Events section. This section allows you to tap or click on the screen to see which events are generated from the different taps and gestures.

Additional information on events

The WebKit team at Sencha Touch has also created an event recorder for Android. You can get more information at http://www.sencha.com/blog/event-recorder-for-android-web-applications/.

Summary

In this chapter, we have covered a basic overview of events, and how to use listeners and handlers to get your program to respond to these events. We also covered a few of the more common events and took an in-depth look at Ext.util.Observable, which handles the events for every component in the Sencha Touch framework.

We talked about event delegation and the potential memory issues that can occur with listeners. We finished up the chapter with a look at touch-specific events and some tips on finding additional information about events.

In the next chapter, we will cover how to get and store data in Sencha Touch, using JSON, data stores, models, and forms.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset