List View / Enable Record Search

Open the sample app and create a few tenant records. Then play with the search box in the tenant list view and see how "search-as-you-type" works.



In the previous section, we have created a sub-loader landlordlist in the slv0 loader. Now we are ready to add search function to the landlord list view.

First let's add an input field:

//...
if ($mode=='embed'){
?>
<div class="section">
  <div style="padding:10px 0;">
    <input id="landlordkey" onkeyup="lookuplandlord(this);">
  </div>

<div id="landlordlist">
...

Note that the input field is added before the landlordlist container. That way, when the content of the list is updated, the input box doesn't lose focus.

The onkeyup event handler in the input field sends a request to the server, along with the value of the input field, each time a key is pressed. The response of the server is loaded in the landlordlist container.

In landlords.js, add the following function:

lookuplandlord=function(d){
  var key=encodeHTML(d.value);
  ajxpgn('landlordlist', document.appsettings.codepage +
    '?cmd=slv0&key='+key);
}

Again, we're using the slv0 message to trigger the listlandlords server handler.

Edit the listlandlords function to the following:

<?php
function listlandlords(){
  global $db;
  $key=GETSTR('key');

  $query="select * from landlords.*, persons.* ";
  $query.=" from landlords, persons where ";
  $query.=" landlords.personid=persons.personid ";

  if (trim($key)!='') $query.=" and persons.fname like '%$key%'";

  $query.=" order by persons.fname ";

In the interest of simplicity, the search only matches first names. You can later write more sophisticated queries. For now, we just need to set up the wiring.

If you test the search box in the list view, you'll see it's almost working. But don't get too excited.

Use a non-limiting search term, such as the letter "a", so that there are more pages. Click on the Next page link. See how the search term is no longer honored? We'll need to fix the paging links so that the search term is forwarded.

<a
    onclick="ajxpgn('lv0',document.appsettings.codepage +
    '?cmd=slv0&page=<?echo $page+1;?>
    &key=' + encodeHTML(gid('landlordkey').value)
    +'&mode=embed');">
  Next »
</a>

There!

In practice, the following lines are used to allow a sound-based search:

...
$soundex=0;
if (strpos($key,'?')) {
  $soundex=1;
  $key=str_replace('?','',$key);
}

...

if (trim($key)!=''){
  $query.=" where (person.fname like '$key%' ";
  if ($soundex) $query.=" or person.fname sounds like '$key%' ";
  $query.=") ";
}

Now when the user enters the search term Sara with a question mark, the question mark is first removed from the search key, but any result that sounds like Sarah is pulled from the database.

We are almost done with a fully functional list view. There's one more enhancement, which we'll see again when building auto-complete lookup in future chapters.

Enable Firebug and watch the requests being sent to the server in the Console tab while typing letters in the search box. You notice that every key stroke sends a request. This is exactly how we designed the lookup, but it's wasteful. If we need to look up a landlord "Dane", it would be wasteful to generate results that match "D", "Da" and "Dan".

The ajxpgn function has built-in optimization so that when multiple requests are sent to populate the same content loader, all previous in-flight requests are aborted. This makes sure that the browser doesn't wait on searchs for "D", "Da" or "Dan" when the response for "Dane" is ready. This doesn't help elminating useless queries, however. The server still does work for nothing.

Imagine you're planning a family trip with a roomful of opinionated yet indecisive relatives. Some wants to go to the islands while some suggests a ski trip; the Tuesday flight is in contest with the Thursday alternative. Being an efficient person, or simply someone who hates the overhead of traveling logistics, you are not going to book and then rebook anything unless there's a consensus. If a final decision hasn't been objected by yet another final decision in 30 minutes, you'll likely to pick up the phone or hit that Purchase button.

Following the same concept, we use a keystroke delay to throttle the requests:

lookuplandlord=function(d){
  var key=encodeHTML(d.value);
  if (d.timer) clearTimeout(d.timer);
  d.timer=setTimeout(function(){

  ajxpgn('landlordlist', document.appsettings.codepage +
    '?cmd=slv0&key='+key);
  },500);
}

When the user enters "D", a request is scheduled to be sent out in half of a second. The handle of this scheduled event is stored in the d.timer flag. The name of the flag is arbitrary. If another key is pressed before the request is sent, the scheduled event will be detected and aborted. Now the user has another 500 millisecond window to type another character without sending a request.

You can finetune the delay to strike a balance between responsiveness and computing time.

Table of Content

Our Services

Targeted Crawlers

Crawlers for content extraction, restoration and competitive intelligence gathering.

Learn More

Gyroscope™ ERP Solutions

Fully integrated enterprise solutions for rapid and steady growth.

Learn More

E-Commerce

Self-updating websites with product catalog and payment processing.

Learn More