View Full Version : Optimizing search functions (I'll show you mine, you show me yours?)

4 Apr 2013, 10:10 AM
I've made a Sencha Touch PhoneGap app (which is now live in the AppStore (https://itunes.apple.com/se/app/labblistan/id624197547?mt=8&uo=4) for iOS, Android will be ready soon).
The basic premise of the app is a (somewhat huge) searchable list (with a couple of additional filters). Thus search performance is essential. I'd like to propose a "I'll show you mine, you show me yours thread" on search optimizations.
A rundown of my search controller:
When looking at examples I found people using either a submit button or search on keyup, since the latter interested me the most this is where I started.
config: control
In the examples I found, only the keyup listener was activated, a quick fix:

'searchfield[itemId=searchBox]' : {
clearicontap : 'onSubmit',
keyup: 'onSearchKeyUp',
submit: 'onSubmit',
action: 'onSubmit',
paste: 'onSubmit'
Now, why are keyup and submit different you might ask?
Well, the onSubmit function just runs the search function (more on that later).
The clearicontap first clears the search field regardless of what function you add here so adding the onSubmit function will clear the filters and then add the non search based filters back in, and as the search field is empty, it won't trigger a new search based filter.

The onSearchKeyUp function is where it gets interesting. Since the list is huge, searching on every single letters equals poor performance. The search field stalls while searching (especially on older devices), so while the user keeps tapping letters on the keyboard nothing shows up all the while queuing up javascript and (in some cases) leading to the user tapping again so that when the searching is actually done, the input might not even be what the user intended.

I remedied this by trying to deduce when the user has finished typing. I did this by having the keyup triggering a timer, in this instance 450 ms, if another keyup event is triggered within this period, the timer is cancelled, if it runs its course it triggers the search function. This timer can of course be set higher or lower. Lower means the user has type faster for it not to search while typing. Higher means that the user will have to wait longer from their last keyup event for the actual searching to begin (perceived as lag).

Of course, there is an exception, if the keyup event is from the enter key, it searches right away. Code:

onSearchKeyUp: function(searchField,e) {
if (e.event.keyCode == 13){
} else {
function timedCount()
function timedSearch()
console.log('b4 search');

function doTimer()
if (timer_is_on === 0)
} else {
console.log('cleared timeout');
So for the search function. I think I might have some room for improvement here.
First off, I noticed that when I had scrolled down the list and searched, I could end up below the actual list content, unable to scroll up. So the first thing the search function does is scroll to top.

As I mentioned in the beginning of the post, I have some additional filters. These are toolbar buttons which basically set variables and then triggers the search function. Within the search function filtering is done based on the variables. I combined the search and filter functions as they needed to clear filters and add them back in, so instead of filtering and then calling the search function which would clear all filters and then add the filtering again combined them.
(Any way of clearing one individual filter?
I've found one, store.filter('field', '', true); would actually clear a filter that was set in the same way, I couldn't however clear the search filter in the same way…)
My search function code:

function searchFunction() {
Ext.getCmp('lablist').getScrollable().getScroller().scrollTo(0, 0);
var searchField = Ext.getCmp('searchBox');
queryString = searchField.getValue();
console.log('Please search by: ' + queryString);
var store = Ext.getStore('LabListStore');
if (queryString) {
var thisRegEx = new RegExp(queryString, "i");
store.filterBy(function (record) {
if (thisRegEx.test(record.get('Analysis')) || thisRegEx.test(record.get('Groupname'))) {
return true;
return false;

function ageFilterFuncForSearch() {
if (ageFilter === 'A') {
Ext.getStore('LabListStore').filter('adult', '1');
} else if (ageFilter === 'C') {
Ext.getStore('LabListStore').filter('child', '1');

function genderFilterFuncForSearch() {
if (genderFilter === 'M') {
Ext.getStore('LabListStore').filter('Male', '1');
} else if (genderFilter === 'F') {
Ext.getStore('LabListStore').filter('Female', '1');
That's basically my search setup. As this is my first Sencha Touch project it's been sort of a trial and error based workflow but where it's at now seems pretty good.
Hopefully you'll have a few pointers to share, or I had some that you hadn't thought of :)