SHARE:

Author: Posted on October 26, 2012 at 6:39 pm
CSS/HTML, jQuery, PHP
TUTORIALS
2

PHP jQuery Search Tutorial, done the right way

Creating a fast and efficient jQuery search feature

Welcome to the jQuery search tutorial. This tutorial will help you create a better search UI for your site using PHP, jQuery and mySQL the right way. There are many ways to create a simple search using jQuery and mySQL, this tutorial will show you a simple and very effective way that minimizes the data passed between the PHP and jQuery while using json objects to transfer this information.

HTML

Let’s start by creating the simple HTML which will provide the search form and a place to display the results.

<!DOCTYPE html>
	<head>
		<title>TUTORIAL :: jQuery, PHP, mySQL search, the right way (with loading image)</title>
		<script type='text/javascript' src='http://code.jquery.com/jquery.min.js'></script>
		<script type='text/javascript' src='script.js'></script>
		<link href='style.css' rel="stylesheet" />
	</head>
	<body>
		<div id='frame'>	
			<div class='search'>
				<div class='header'>
					<h1>PHP & jQuery SEARCH</h1>
					<input type='text' id='text' /> <button id='search'>Search</button>
				</div>
				<div id='results-holder'>
					<ul id='results-list'></ul>
				</div>
			</div>
		</div>
	</body>
</html>

CSS

We have the basic HTML for our jQuery search, lets use some CSS to prettify it and create the class which will allow us to add the loading image to an element.

/* Lets use a Google Web Font :)  */
@import url(http://fonts.googleapis.com/css?family=Finger+Paint);
/* Basic CSS for positioning etc */
body {
	font-family: 'Finger Paint', cursive;
	background-image: url('bg.jpg');
}
#frame {
	width: 500px;
	margin: auto;
	margin-top: 125px;
	border: solid 1px #CCC;
	/* SOME CSS3 DIV SHADOW */
	-webkit-box-shadow: 0px 0px 10px #CCC;
    -moz-box-shadow: 0px 0px 10px #CCC;
    box-shadow: 0px 0px 10px #CCC;
    /* CSS3 ROUNDED CORNERS */
    -moz-border-radius: 5px;
    -webkit-border-radius: 5px;
    -khtml-border-radius: 5px;
    border-radius: 5px;
    background-color: #FFF;
}
.search .header {
	margin: 25px;
}
.search .header {
	text-align: center;
}
.search .header input {
	width: 350px;
}
#results-holder {
	min-height: 200px;
}

/* The class which can be applied to elements where we want to display a centered loading image */
.loading {
	/* Image is free and loads of alternatives can be generated from ajaxload, http://ajaxload.info/! */
	background-image: url('loading.gif');
	background-position: center center;
	background-repeat: no-repeat;
}

/* Styling for the results list */
#results-list {
	margin: 0px;
	padding: 0px;
	list-style: none; /* REMOVE THE BULLET POINTS */
}
#results-list li {
	line-height: 30px;
	border-bottom: solid 1px #CCC;
	padding: 5px;
	padding-left: 10px;
	color: #333;
}
/* REMOVE THE BORDER FROM THE LAST LIST ELEMENT SO IT DOESN'T CLASS WITH THE FRAME BORDER */
#results-list li:last-child {
	border: none;
}

/* STYLE THE NO RESULTS LIST ITEM */
#results-list .no-results {
	text-align: center;
	font-weight: bold;
	font-size: 14px;
}

With the comments in the CSS code it should be pretty self explanatory, but not the .loading class which we will use to apply to the list holder which will then display the loading gif image as the background.

jQuery

So we have a nice looking search form now, lets create the javascript that will listen for a button click or an enter press within the search field. You will need to jQuery library included within your page before this javascript is either pasted or included. (This is a jQuery search after all!)

Use the following line to include the jQuery library from the jQuery CDN

<script type='text/javascript' src='http://code.jquery.com/jquery.min.js'></script>

With jQuery included we can now go ahead and create the jQuery which will do the search, this can either be within the HTML page in

<script type='text/javascript'></script>

tags or included as an external javascript file like the jquery.min.js file is above, either way, it must be AFTER the jQuery library has been included.

$(function(){
	//Hide the result list on load
	$('#results-list').hide();
	//Click event when search button is pressed
	$('#search').click(function(){
		doSearch();
	});
	//Keypress event to see if enter was pressed in text input
	$('#text').keydown(function(e){
    	if(e.keyCode == 13){
    		doSearch();
    	}
	});
});

function doSearch() {
	var searchText = $('#text').val();
	//Rehide the search results
	$('#results-list').hide();
	$.ajax({
		url: 'search.php',
		type: 'POST',
		data: {
			'text': searchText
		},
		beforeSend: function(){
			//Lets add a loading image
			$('#results-holder').addClass('loading');
		},
		success: function(data) {
			//Take the loading image away
			$('#results-holder').removeClass('loading');
			//Was everything successful, no errors in the PHP script
			if (data.success) {
				//Clear the results list
				$('#results-list').empty();
				//Display the results
				//Check to see if there are any results to display
				if(data.results.length > 0) {
				//Loop through each result and add it to the list
					$.each(data.results, function(){
						//Give the list element a rel with the data results ID in case we want to act on this later, like selecting from the list
						$('#results-list').append("
  • " + this.title + "
  • "); }); } else { //If there are no results, inform the user - add 'no-results' class so we can style it differently $('#results-list').append("
  • Your search did not return any results
  • "); } //Show the results list $('#results-list').fadeIn(); } else { //Display the error message alert(data.error); } } }); }

    This tutorial assumes a basic understand of javascript and jQuery so we wont be going into a great amount of detail but the comments within the javascript should make things easy to understand.

    The first thing to do is tell the javascript to run the doSearch() function if either the search button is clicked, or the enter key is pressed while in the text input, using the following lines:

    $(function(){
    	//Hide the result list on load
    	$('#results-list').hide();
    	//Click event when search button is pressed
    	$('#search').click(function(){
    		doSearch();
    	});
    	//Keypress event to see if enter was pressed in text input
    	$('#text').keydown(function(e){
        	if(e.keyCode == 13){
        		doSearch();
        	}
    	});
    });
    

    Note that the “$(‘#results-list’).hide();” line is just hiding the results list on load. So now when the user interacts with the search form the doSearch function will be called and perform the search. Note that the function is not within the jQuery $(function(){});

    First of all we capture the text that is within the search input using this line:

    	var searchText = $('#text').val();
    

    Now that we have a variable that holds this text we do an ajax call to the search.php script which resides within the same directory as the HTML file that the javascript is either included or written in.

    	$.ajax({
    		url: 'search.php',
    		type: 'POST',
    		data: {
    			'text': searchText
    		},
    		beforeSend: function(){
    			//Do stuff before the search text is sent
    		},
    		success: function(data) {
    			//Do stuff if the ajax request is successful
    		}
    	});
    

    • url: specifies the location of this file
    • type: specifies whether it is GET or POST
    • data: is an object which holds the data we are sending via post

    You can see that the text is defined within the data: {} object, “‘text’” is what the POST or GET variable will be in the search.php script and “searchText” is the variable holding the input text.

    This is where we implement the loading image, previously we defined the following class in CSS

    .loading {
    	/* Image is free and loads of alternatives can be generated from ajaxload, http://ajaxload.info/! */
    	background-image: url('loading.gif');
    	background-position: center center;
    	background-repeat: no-repeat;
    }
    

    The image itself is a free image generated from http://ajaxload.info/. There are loads of different ones to choose from so get yourself over there!

    In this class we are simple setting the background image of the element to this loading image and centering it, so when we give an element (in this case the #results-holder DIV) this class it will show the animated loading div. We do this by using the jQuery .addClass() method, so its as easy as:

    beforeSend: function(){
    	$('#results-holder').addClass('loading');
    },
    

    This will then add the class to the image before the ajax request is sent, then we simple remove it when we get a response back from the PHP using the following code:

    success: function(data) {
    	$('#results-holder').removeClass('loading');
    }
    

    Easy!

    So what do we do with the response and how do we display the information? Take a look at the code below:

    success: function(data) {
    	//Take the loading image away
    	$('#results-holder').removeClass('loading');
    	//Was everything successful, no errors in the PHP script
    	if (data.success) {
    		//Clear the results list
    		$('#results-list').empty();
    		//Display the results
    		//Check to see if there are any results to display
    		if(data.results.length > 0) {
    		//Loop through each result and add it to the list
    			$.each(data.results, function(){
    				//Give the list element a rel with the data results ID in case we want to act on this later, like selecting from the list
    				$('#results-list').append("
  • " + this.title + "
  • "); }); } else { //If there are no results, inform the user - add 'no-results' class so we can style it differently $('#results-list').append("
  • Your search did not return any results
  • "); } //Show the results list $('#results-list').fadeIn(); } else { //Display the error message alert(data.error); } }

    Notice the function(data){}, the “data” variable is what we use to access any information that is passed from the PHP. As we are doing this the proper way, the PHP is only sending back a JSON object with a set of information. First we check the success of the transaction, as we are expecting an object, we can do if(data.success) to see if the success variable is equal to true, if it is we can then run the next bit of code.

    //Display the results
    //Check to see if there are any results to display
    if(data.results.length > 0) {
    //Loop through each result and add it to the list
    	$.each(data.results, function(){
    		//Give the list element a rel with the data results ID in case we want to act on this later, like selecting from the list
    		$('#results-list').append("
  • " + this.title + "
  • "); }); } else { //If there are no results, inform the user - add 'no-results' class so we can style it differently $('#results-list').append("
  • Your search did not return any results
  • "); } //Show the results list $('#results-list').fadeIn();

    Here we check the length of the results variable which should hold any results from our search to see if there are any at all. If not (a.k.a the length is 0) instead of adding the results to this list we just add a single item which informs the user their search didn’t match any results and add a class to it so we can style it differently.

    If there are some results we use the jQuery $.each() method and loop through each returned result and add an element to the HTML list. Often people will use this method and return all the HTML with the list and results, this way is much more efficient as we are sending much less data over the transaction, why bother sending all the HTML when it can be ready and waiting on the page.

    Finally we do $(‘#results-list’).fadeIn(); to show the results, we previous hid it so that depending on the style of the list we wouldn’t let it get in the way of the loading image.

    SQL for mySQL Database

    We have everything functioning on the client side, now its time to do some server side development and create the PHP required to finish this tutorial, but first we are going to need a database that the PHP can query to return the search results. Create a new database and use the following SQL code to create the required table and populate it with test data.

    --
    -- Table structure for table `items`
    --
    
    CREATE TABLE IF NOT EXISTS `items` (
      `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
      `title` varchar(128) NOT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;
    
    --
    -- Dumping data for table `items`
    --
    
    INSERT INTO `items` (`id`, `title`) VALUES
    (1, 'Bottle'),
    (2, 'Pencil'),
    (3, 'Dolphin'),
    (4, 'Blade of Grass'),
    (5, 'Sea Cucumber');
    

    PHP

    Now we have the database set up, lets get right into the PHP, first lets create a file called db.inc.php, which of course is going to create our connection to the database.

    
    $dbhost = 'localhost'; //hostname
    $dbuser = 'root'; //database username
    $dbpass = ''; //database password
    $dbname = 'test'; //database name
    
    //Create the connection to the mySQL database or catch the exception if there is an error
    $db = new mysqli($dbhost, $dbuser, $dbpass);
    
    $db->select_db($dbname);
    
    if($db->connect_errno > 0){
        die('ERROR! - COULD NOT CONNECT TO mySQL DATABASE: ' . $db->connect_error);
    }
    

    Very simple code and if you have done any PHP before you will have seen this 1,001 times. For those of you that have not, this creates a connection to the mySQL database you just created with the provided credentials, you may need to change this information depending on what you called the table and what login information you have set up.

    Now we have the connection to the database, lets create the search.php file that the jQuery ajax request is posting to.

    		//Prepare an array to hold data we are going to send back to the jQuery
    	$data = array(
    		'results' => array(),
    		'success' => false,
    		'error' => '' 
    	);
    	//Has the text been posted?
    	if (isset($_POST['text'])) {
    		//Connect to the database
    		require_once('db.inc.php');
    		//Escape the text to prevent SQL injection
    		$text = $db->real_escape_string($_POST['text']);
    		//Run a LIKE query to search for titles that are like the entered text
    		$q = "SELECT * FROM `items` WHERE `title` LIKE '%{$text}%'";
    		$result = $db->query($q);
    		//Did the query complete successfully?
    		if (!$result) {
    			//If not add an error to the data array
    			$data['error'] = "Could not query database for search results, MYSQL ERROR: " . $db->error;
    		} else {
    			//Loop through the results and add to the results array
    			while ($row = $result->fetch_assoc()) {
    				$data['results'][] = array(
    					'id' => $row['id'],
    					'title' => $row['title']
    				);
    			}
    			//Everything went to plan so set success to true
    			$data['success'] = true;
    		}
    	}
    	//Set the content type for a json object and ensure charset is UTF-8. NOt utf8 otherwise it will not work in IE (Darn IE! >.<)
    	header("Content-Type: application/json; charset=UTF-8");
    	//json encode the data and cast to an object so we can reference items like this.id in the javascript instead of this['id'] etc.
    	echo json_encode((object)$data);
    

    Again, I have ensured that all the code is commented well to make it as easy as possible to understand. First we create an array which we will store all the information in and send back to the jQuery. We then check that some test has been posted to the script and if it has required the db.inc.php file so we create a connection to the database. After this we escape the posted text using $db->real_escape_string and store the clean search text into a variable called "text".

    We then create an SQL LIKE query which will search for any rows in the table "items" that have a title which is "like" the searched text, note the "%" signs either side of the variable, read more about SQL LIKE queries here.

    We then check to see if the query failed by doing

    if(!$result)
    and if it wasn't, we store an error in the $data array we created earlier. This will then skip to the results part of the code and just return the error message back to the jQuery with success set to false, as this is its default value. The jQuery will then alert() the error message on the screen.

    Providing everything went to plan, we will then loop through all the results and add them to the results part of the $data array. After this we set the success variable to true so the jQuery knows to add the results to the list element.

    The final section to this code is to set the content type and charset, this will ensure that the browsers are expecting the right type of content, in this case JSON. We have also set the charset to UTF-8 to prevent many issues, I find many IE related issues (#headache), I won't go into these here, this tutorial is long enough ^^

    Last but not least, we json_encode() the data and cast it to an object so we can reference it like data.success for convenience. The jQuery will catch this and perform the actions we coded earlier in this tutorial.

    That's it, a fast efficient and great looking jQuery search feature! Please comment and ask questions or provide constructive criticism, we are all here to learn and that includes me. Thank you for reading and please provide suggestions for more tutorials!

    • /li>
    • Nick Jones

      Really awesome post for Jquery Ajax. Hats off to Leon. OSIpage http://www.osipage.com for quick web access.

      • revillwebdesign

        Thanks Nick, i am glad it helped :)

    • REVIEWS

    • No categories have been added yet

    TABLE OF CONTENTS