BlackBerry Trackpad Support in Sencha Touch 2


BB_FirstScreen

Problem Statement

Sencha Touch does not provide BlackBerry trackpad support, in-spite of the fact that the BlackBerry mobiles were designed using webkit engine and WebOS version is > 6. Due to this, it will be hard for the user to work with a Sencha Touch application on BB. Specially when the user is on BB devices with keypad as well as touch support ( e.g. BB Bold), the user ends up using the keys quite frequently. In such cases, trackpad support is THE MUST HAVE kind of need for the apps targeted for BlackBerry mobiles. While on one side it makes the navigation easier for the user, on the other side it respects the usability requirement for the device.

Scope of the Article

In this article, following items will be covered:

  1. Auto Scrollable behaviour linked with trackpad mouse position.
  2. Item tap for Sencha Touch List component
  3. Data view Item tap handling
  4. Carousel navigation using trackpad  ( Swiping automatically based on trackpad pointer and indicator tap )
  5. Button tap handling
  6. Image tap handling

Pre-requisites

  1. You need to have a Sencha Touch sample project running in your machine. If you don’t have, visit this blog to know steps to set up or download sample project from here.
  2. Sencha Touch 2.1.
  3. You need to have Blackberry Bold (9930) emulator setup ready on your machine. If you don’t have yet, download and install.

Ho to do?

Step 1)  Auto Scrollable behaviour linked with trackpad mouse position

When user places trackpad mouse pointer at extreme ends of the screen in the application, (which is a general case that may happen when you have list or dataview etc.), you need to auto scroll the view to show more records/data to the user. For that, follow below steps:

1) Create a util class, which will contain static methods, which will be useful to handle all functional part of code related to trackpad handling.

Sample code:

Ext.define('Wtc.utils.TrackPadUtils', {

statics: {

 // contains static methods.

}

});

2)  apply our changes only, if the device type is BlackBerry. So add a check for that in TrackPadUtils.js file.

Sample Code: 

Place below code in statics config of TrackPadUtils class.

handleTrackPad: function() {

if( Ext.os.is.BlackBerry ) {

return true;

 }else {

 return false;

 }

}

3)  Override the container and there handle element’s mouse move event. With this, throughout the application, whenever you move mouse pointer, this event gets fired.

Sample code:

Ext.define('Wtc.ux.ContainerOverride', {

override: 'Ext.Container',

initConfig : function(){

Ext.apply(this.initialConfig,{});

this.callParent(arguments);

if( Wtc.utils.TrackPadUtils.handleTrackPad(this) ) {

var task = Ext.create('Ext.util.DelayedTask', function() {

Wtc.utils.TrackPadUtils.handeleScroller(this.event,this);

});

this.element.on('mousemove',function(event){

this.event = event;

task.delay(30);

task.setScope(this);

},this);

}

}

});

Note:Add ‘Wtc.ux.ContainerOverride’ and ‘’Wtc.utils.TrackPadUtils’ class names in requires config in app.js

In above code, overriding the container and while component is being prepared, checking for device, whether it is BlackBerry or not. Then, in mousemove event, applying delay for the mousemove event by creating delayed task.

You may not want to scroll the view immediately when user places pointer at extreme ends. Hence, using delay of 40 milliseconds, calling a function, handeleScroller to the class Wtc.utils.TrackPadUtils

4)  Write method handeleScroller in Wtc.utils.TrackPadUtils class.

Sample Code:

handeleScroller: function(evt, view, el) {

var element = evt;

 var margin = null;

 var scrollerSize = null;

 var containerSize = null;

 if( view.getScrollable() ) { 

 view.scroller = view.getScrollable().getScroller();

 margin = view.element.getHeight()+25;

 scrollerSize = view.scroller.getSize();

 containerSize = view.scroller.getContainerSize();

 if( !view.initialScroll ) {

 view.initialScroll = 0;

 }

 if( evt.pageY >= margin && (( scrollerSize.y-containerSize.y )>view.initialScroll) ) {

 view.initialScroll = view.initialScroll+8; 

 view.scroller.scrollTo(containerSize.x,view.initialScroll,true);

 }else if ( evt.pageY < 70 && view.initialScroll > 0) {

 view.initialScroll = view.initialScroll - 8;

 view.scroller.scrollTo(containerSize.x,view.initialScroll,true); 

 }

 }

}

In above code, getting the extreme heights of the device and with some marginal height, increasing certain height every time (in this case 8, you can modify accordingly) using scrollTo method. With this, view should automatically scroll the view to top or bottom based on mouse pointer as shown below:

BB_Screen2

Step 2)  Item tap handling for Sencha touch List

1)  Create a list and use that list xtype where ever you want to prepare list view, so that, for all the lists throughout the application, code will be at one place.

Sample Code:

Ext.define('Wtc.ux.TrackPadList', {

 xtype : 'trackpadlist',

 extend : 'Ext.dataview.List',

 initialize : function() {

 this.callParent();

 if( Wtc.utils.TrackPadUtils.handleTrackPad() ) {

 // List item tap handling

 this.element.on({

 mouseup : Wtc.utils.TrackPadUtils.handleListTap,

 delegate: '.' + Ext.baseCSSPrefix + 'list-item-body',

 scope : this

 });

 // Item disclosure icon tap handling

 this.element.on({

 mouseup : Wtc.utils.TrackPadUtils.handleItemDisclosure,

 delegate: '.' + this.getBaseCls() + '-disclosure',

 scope : this

 });

 }

 }

});

In the above code, handled mouse up event for list. When user taps on list item or disclosure icon, Sencha is firing item tap events based on the delegate property.

2)  The same implementation you need to do for element mouse up. There will be no difference in behaviour. As there will be different classes for item tap and disclosure tap, use different delegates.

And when particular list item tap was identified, firing handleItemDisclosure function, which will be again in TrackPadUtils class.

3)  In TrackPadUtils class, call list itemTap function explicitly for item tap and handleItemDisclosure function for item disclosure.

Sample Code

For Tap event handling,

handleListTap : function(event,target,e) {

 this.onItemTap(this,target,index,e);

}

For Item disclosure handling,

handleItemDisclosure : function(event,target,e){

this.handleItemDisclosure(event);

}

With above code, you should be able to tap on list item and item disclose.

Step 3)  Dataview Item tap handling

Similar to List, for dataview also, create a sample dataview file and use its xtype whenever you want to create dataview in application.

Sample Code:

Ext.define('Wtc.ux.TrackPadDataview', {

 xtype : 'trackpaddataview',

 extend : ‘Ext.dataview.DataView’,

 initialize : function() {

 this.callParent();

 if( Wtc.utils.TrackPadUtils.handleTrackPad() ) {

 this.element.on({

 mouseup : Wtc.utils.TrackPadUtils.handleDataviewTap,

 scope : this

 });

 }

 }

});

Unlike list’s item tap, dataview will have difference in implementation.

As it is a dataview, you cannot assure that user will definitely taps on dataview-item. It is possible that, user may have image in dataview and he can tap on it. In that case, it will not identify the item tap event.

So, When it is not able to identify that, check for the parent class of the particular target and will check whether it is dataview-item or not. If yes, go ahead with Itemtap event that was applied for the list.

handleDataviewTap : function(event,target,e) {

var index = this.getViewItems().indexOf(target);

if( index == -1 ) {

var selectedElement = Ext.get(target).parent('div.x-dataview-item');

 if( selectedElement ) {

 index = this.getViewItems().indexOf( selectedElement.dom );

 }

}

if( index != -1 ) {

 this.onItemTap(this,target,index,e);

}

}

With above code, user should be able to tap on dataview item.

BB_Screen3

Step 4)  Carousel implementation through trackpad:

Swiping automatically based on trackpad pointer:

When comes to carousel, if you want the same functionalities to be achieved through touch, swiping will be tricky. How can user swipe with trackpad mouse pointer? It is not possible to swipe using trackpad. Though, chose one intermediate solution similar to scrollable functionality.

Check for mouse pointer weather it is at horizontal extreme ends or not. If yes, based on end, firing next and previous methods of carousel.

Sample Code:

Ext.define('Wtc.ux.TrackPadList', {

 xtype : 'trackpadlist',

 extend : 'Ext.dataview.List',

 initialize : function() {

 this.callParent();

 if( Wtc.utils.TrackPadUtils.handleTrackPad(this) ) {

 var task = Ext.create('Ext.util.DelayedTask', function() {

 Wtc.utils.TrackPadUtils.handleCarouselSwipe( this.event,this );

 });

 this.element.on('mousemove',function(event){

 this.event = event;

 task.delay(600);

 task.setScope(this);

 },this);

 // handling for indicator tap.

 this.element.on('mouseup',Wtc.utils.TrackPadUtils.handleCarouselIndicatorTap,this);

}

}

});

In Trackpadutils.js file, add code for the function handleScroller.

Sample Code:

handleCarouselSwipe : function(event,carouselView) {

 if( carouselView.element && ( carouselView.element.getWidth() - event.pageX ) < 40 ) {

 carouselView.next();

 }else if( event.pageX < 40 ) {

 carouselView.previous();

 }

}

View: before swipe,

BB_FirstScreen

After swipe,

BB_Screen4

Indicator tap:

For indicator tap handing, write a function in TrackPadUtils.js and check for mouse up event, weather the tap occurred from indicator or not.

Sample Code:

handleCarouselIndicatorTap : function( e,target ) {

var indicator = this.getIndicator();

 var selectedElement = Ext.get(target);

 var selectedIndex = null;

 if( target.nodeName == 'SPAN' ) { 

 if( indicator && indicator.indicators.length >0 ) {

 selectedIndex = indicator.indicators.indexOf(selectedElement);

 if( selectedIndex != -1 ) {

 if( selectedIndex < indicator.activeIndex ) {

 this.previous();

 }else {

 this.next();

 }

 }

 }

 }

}

In above code, getting the indicator active index and comparing for selected index and active index weather it is less or more. If more, calling next method of carousel and if less, calling previous method of carousel

BB_FirstScreen

Step 5)  Button tap handling:

Buttons are commonly used for Sencha Touch applications. Hence, it is important to handle button tap for trackpad.

Override the button and there handle the tap functionality. Get the element of button and handling element’s tap event and firing tap event explicitly.

Sample Code:

Ext.define('Wtc.ux.ButtonOverride', {

 override: 'Ext.Button',

 initConfig : function(){

 var me = this;

 Ext.apply(this.initialConfig,{ 

});

 this.callParent(arguments);

 if( Wtc.utils.TrackPadUtils.handleTrackPad(this) ) {

 this.element.on('mouseup',function(e){

 this.fireEvent('tap',this,e);

 });

 }

 }

});

BB_Screen5

Step 6)  Image tap handling:

For image, prepare a image default view and there handle the code for trackpad tap

Ext.define('Wtc.ux.TrackPadImage', {

 extend: 'Ext.Img',

 xtype: ‘trackpadimg’,

 initConfig : function(){

 var me = this;

 this.callParent(arguments);

 if( Wtc.utils.TrackPadUtils.handleTrackPad(this) ) {

 this.element.on('mouseup',function(event){

this.onItemTap(event);

 });

 }

 }

});

After Arabic image tap,

Summary

This article has provided implementation steps to provide trackpad support for BlackBerry in Sencha Touch. There is no doubt that BB users are emotionally attached to the keyboard and this support kind of puts smile on their face. I hope you find this useful.

At Walking Tree we practice and recommend Sencha Products like ExtJS and Sencha Touch to build amazing web / touch apps. In case you are looking for training or professional assistance, contact us by visiting our website.

 

References 

Tagged with: , , , , , , , ,
Posted in Sencha Touch
One comment on “BlackBerry Trackpad Support in Sencha Touch 2
  1. James says:

    I’ve tried everything to get this working but when I load up the app I get an error stating: Uncaught TypeError: Object [object Object] has no method ‘getDocked’ for “container.js” and this seems to be related to the doAdd. I’m using Touch 2.1. Are you able to post the completed project so I can compare and ensure I’ve got it right please?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

We Have Moved Our Blog!

We have moved our blog to our company site. Check out https://walkingtree.tech/index.php/blog for all latest blogs.

Sencha Select Partner Sencha Training Partner
Xamarin Authorized Partner
Do More. With Sencha.

Recent Publication
%d bloggers like this: