How to do an AJAX search with jQTouch, Part 2
In the last installment of How to do an AJAX search with jQTouch we looked at how to setup a jQTouch interface with the goal of performing an AJAX search. In this article, we will write the necessary JavaScript to perform that AJAX search, as well as a PHP script to respond to those calls.
This article assumes you have read the first part of this series.
Before we start, we should take a step back and consider what we're about to do. Our Searcher app has three parts:
- the client-side jQTouch UI,
- the client-side jQuery AJAX calls,
- the server-side PHP script (that could easily be backed by a database)
At this point we have finished the jQTouch UI. However, instead of immediately moving on to writing the jQuery AJAX calls, let's start with the PHP script instead. This will help us understand our AJAX calls when it comes time to write them.
The PHP Script
Since our PHP script will be performing a search, let's create a file called search.php
and add a single line of boilerplate:
<?php
There's no need for an end tag. In fact, in files containing only PHP, it is recommended that you do not include an end tag:
For files that contain only PHP code, the closing tag ("?>") is never permitted. It is not required by PHP, and omitting it prevents the accidental injection of trailing white space into the response.
Our Searcher app needs to search for something, so let's pretend it's an interface for a music player and we're searching for songs. In order to express that idea into PHP code, we need the following elements:
- a Song class to hold the artist name and the title,
- an array holding a bunch of Song objects,
- a function for searching the Song array,
- a way to get a search value from the AJAX request,
- a way to set the MIME type to JSON,
- a way to encode our Song array as JSON
First, we'll need a class to hold the songs (place this starting at line 3 in search.php
):
class Song {
public $artist;
public $title;
public function __construct($artist, $title) {
$this->artist = $artist;
$this->title = $title;
}
}
Let's break it down for those not familiar with PHP classes:
- at line 3, we declare the class name
- at lines 4-5, we declare two public fields to represent the artist's name and the title of the song,
- at lines 7-10, we declare the class constructor that we use to initialize the two fields of a Song object
Now that we have a way to model songs in our PHP script, we need to make an array of some dummy songs that we can query using AJAX:
$songs = array(
new Song("Weezer", "Say It Ain't So"),
new Song("Weezer", "Undone"),
new Song("Cake", "Meanwhile, Rick James..."),
new Song("The Stars", "Ageless Beauty"),
new Song("Roy Orbison", "In Dreams")
);
Now we have something of a faux database setup. How will we search it? Why, with a search function, of course! Let's write that now:
function search($songs, $value) {
if (empty($value))
return $songs;
$matches = array();
foreach ($songs as $s)
{
$matchArtist = stripos($s->artist, $value) !== false;
$matchTitle = stripos($s->title, $value) !== false;
if ($matchArtist || $matchTitle)
$matches[] = $s;
}
return $matches;
}
So what does this function do? Let's take a look line-by-line:
- at lines 22-23, we check to see if the search value is empty (i.e. an empty string or null). If that's the case, then we just return all the songs
- at line 25, we declare the
$matches
array. This will contain all the songs that match the search value$value
- at line 26, we use a foreach loop to iterate through all the Song objects in the
$songs
array - at lines 28-29, we check to see if the artist name or song title contain the search value
$value
- at line 30-31, we add the Song object to the
$matches
array if it matches the artist name or song title - at line 33, we return whatever matches (if any) we have found
Ok, so now we have a Song class, an array of Song objects, and a function that searches that array. What's left in our PHP script? Well, as it stands, we have no way to interface with it. What we need to do now is have some sort of way to respond to the AJAX GET request that our Searcher app will send. To do that, we harness the awesome power of the $_GET
superglobal:
$value = $_GET['value'];
$matches = search($songs, $value);
On the first line, we extract "value" parameter from the $_GET
superglobal and assign it to the $value
variable. The second line runs our search function on the $songs
database and searches for songs that have an artist or title that contains the $value
string.
We're almost there! At this point we've managed to get an array of Song objects that match the passed search value. All we need to do now is return that PHP array of objects as a JSON-encoded array of objects. Let's do that now:
header('Content-Type: application/json');
echo json_encode($matches);
The first line sets the the MIME type of an HTTP response. MIME types are a sort of meta data that is used to describe what sort of content is being returned. In this case, we are telling jQuery (or whatever client that issued the request) that we are returning content that is JSON formatted. The second line is a built-in PHP function that converts PHP types into a string containing their JSON counterparts. Basically, it allows us to encode our PHP objects into JavaScript and allow us to access them in a nearly identical way:
// PHP
array(
new Song("Artist 1", "Title 1"),
new Song("Artist 2", "Title 2")
);
// Becomes... (after json_encode)
// JavaScript
[
{ artist: "Artist 1", title: "Title 1" },
{ artist: "Artist 2", title: "Title 2" }
];
And we're done the PHP script! If we want to test it, we can load execute the PHP file on our server and try different search values. For example, entering this URL should return a JSON array with two Song objects:
// URL
http://example.com/jQTouch-ajax-search/search.php?value=Weezer
// Response
[{"artist":"Weezer","title":"Say It Ain't So"},{"artist":"Weezer","title":"Undone"}]
The jQuery AJAX calls
The finish line is now in sight. We've successfully written our jQTouch UI and our PHP script. The last thing we need to do is write some jQuery AJAX calls to execute our search and load the results into our UI. In order to do that, we need to do the following:
- listen for the submission of the search form in the jQTouch UI
- when the submission happens, get the search value from the form and set it as a parameter in an AJAX call to
search.php
- register a callback that will populate the jQTouch search results when the AJAX call completes
Let's start with listening for the submit event on the search form. First, we'll need to create a new JavaScript source file search.js
and fill it with the following boilerplate:
(function($){
// Put code here.
})(jQuery);
What this boilerplate does is give our JavaScript script its own context so that can minimize leaking variables into the global JavaScript namespace. It also gives us access to the jQuery object in the convenient $
form, regardless of whether or not "no conflict" mode is enabled.
Recall in part 1 we defined an HTML search form that looked like this:
<form id="search" action="">
<div class="toolbar">
<h1>Search</h1>
<a href="#" class="back">Back</a>
</div>
<ul class="rounded">
<li><input type="text" name="search-text" placeholder="Search" id="search-text" /></li>
</ul>
<ul class="edgetoedge" id="search-results">
<li class="sep">Results</li>
</ul>
</form>
Note that on line 1 we defined the id of the form as search
. We'll use that to find the form and register a handler for its submit event so that we can take action when someone tries to perform a search using the jQTouch UI.
(function($){
$(function(){
$("#search").submit(function(event, info) {
var text = $("input[id=search-text]", this);
text.blur();
var results = $("#search-results", this).empty();
results.append($("<li>", {
"class": "sep",
text: 'Results for "' + text.val() + '"'
}));
$.get("search.php",
{ value: text.val() },
function(data) {
$.each(data, function(i, song) {
var str = song.artist
+ " - "
+ song.title;
$("<li>")
.text(str)
.appendTo(results);
});
}
);
return false;
});
});
})(jQuery);
There's a lot there, so let's break it down line-by-line:
- starting at line 3 and ending at line 32 we have the jQuery ready handler which is run once the DOM has finished loading
- starting at line 5 and ending at line 30 we bind a submit event handler to the submit event for the
#search
form - at lines 6-7, we retrieve the
search-text
element, assign it to a variable (for later use on line 16), and then blur (i.e. deselect) the element so that the iPhone keyboard will go away - at lines 9-13, we clear any previous items in the list that may be hanging around from a previous search and then load in a new separator ("sep") that contains the search value
- at line 15-27, we perform our AJAX GET request to
search.php
with the value of the search text field as our value parameter (line 16) and a callback that adds the results to the list (lines 17-26) - finally, at line 29, we return false to prevent the default form behaviour (i.e. submitting the form) from being carried out
And we're done. All we need to do now and include search.php
in the header of index.html
so that it'll be run:
<script src="search.js" type="application/x-javascript" charset="utf-8"></script>
Conclusion
In this, the final installment of How to do an AJAX search with jQTouch, we finished off the example application we started in the first part of this series.
In part 1, we covered building a UI using jQTouch. In part 2, we helped visualize our problem by pretending that we were writing a front-end UI to a server-side music player. To do that, we jumped into server side programming with PHP to write a script to serve us JSON-encoded Song objects. Once we had that setup, we moved back into JavaScript. In order to make use of the PHP script, we wrote a jQuery handler to respond to a jQTouch form submission. The handler, once triggered, issued an AJAX call to the PHP script to pull down the appropriate Song objects for display in our UI.
What Now?
With respect to the goals of this tutorial, nothing. However, if you want to pimp up the application a bit more, some things you could do are:
- Add genres and albums to the PHP Song object and then make the jQTouch UI menu have two additional options: Genres and Albums
- Try to make a Now Playing sub-menu that is activated when a Song is picked from the Search screen
Source
The source code I have written in this article is public domain, and you are free to do what you will with it. Here is a zip of the source, along with the required jQTouch source. It should work pretty much right out of the box.
24 comments
$url
) and then make the jQuery code create a link if that field isn't empty. I suggest grabbing a book on PHP :)