I'm currently using a PHP shopping cart, and finally decided to implement a search suggestion feature.
There are some already available solutions out there, but I wanted to gain control over how mine is implemented and how it functions.
I'm asking for some assistance here and code review on two things:
Can anyone spot any security flaws with my implementation (PHP security is already dealt with I'm explain later)
I've thrown in two variables, into the JavaScript,
recurringRequest
andrequest
. These two variables perform the following task:- The
request
variable initiates the request based on the characters that a user has typed into the search input box. - The
recurringRequest
variable stores a boolean, true or false, and is used to check if the user is still typing, and if they are, then it aborts therequest
variable and stops it from processing past requests, so that we can facilitate minimal server load.
- The
Am I doing it correctly?
My PHP page, searchsuggestion.php is a simply copy/paste of the original shopping cart search page code, with the exception that it removes all the other content (header, footer, everything is gone). All this page does is takes the get variable "keyword" value - and performs a search of the database for products matching the keyword.
I've used htmlentities on the returned results, so that it returns it in plain text. The reason I did this was because I want to show images in the search suggestions, but I don't want these images being loaded by the jQuery. Which is why in the jQuery code, you will see the replace command converting the tags back to html entities [(t.replace('<','<').replace('>', '>'));]. This provides near-instant results, and loads the images after the search suggestion list has already been populated, and slid down, so that the user can review search results instantly while typing instead of the lag that it produced when I initially had it loading the images from the PHP page via the jQuery.
Here is the full JavaScript:
var recurringRequest = false; // var to check if user is still typing
var request; // var to store request to abort if user is still typing
$( document ).ready(function() {
// this function will unhide the search suggestion list
// when a user focuses on the search input box
$("input[name='keyword']").focus(function() {
$("#ssugg").slideToggle("fast");
});
// this function starts generating search suggestions when
// the user types into the search input box
$("input[name='keyword']").keyup(function() {
var value=$.trim($("input[name='keyword']").val());
if(value.length>1) // only pay attention to two characters or more
{
value = value.split(' ').join('+'); // replace spaces with + signs
if (recurringRequest) {
request.abort(); // abort a the previous request if the user is still typing
}
recurringRequest = true;
// this block of code performs the request, adds the results which are
// in htmlentities form to an always-hidden div, then converts it and
// adds it to the slide down search suggestion list, and then empties
// out the always-hidden div
request = $( "#ssugghidden" ).load( "searchsuggestion.php&keyword="+value+
" #searchsuggestlist", function() {
var t = $( "#ssugghidden" ).text();
$( "#ssugg" ).html(t.replace('<','<').replace('>', '>'));
$( "#ssugghidden" ).empty();
});
// finally set this to false because the request was allowed to fully complete
recurringRequest = false;
}
else
{
$( "#ssugg" ).empty(); // empty the div if less 2 characters were typed
}
});
// this simply hides the search suggestion list if the user focuses away from the search input box
$("input[name='keyword']").blur(function() {
// hide drop down suggestions
$("#ssugg").slideToggle("fast");
});
});
The request
variable and recurringRequest
variable was something I saw in another already coded plugin. The plugin didn't explain that it would reduce server load by aborting a previous request that was still being processed, but it did specify that it aborts the request should the user be still typing. It did mention that it was mostly if the user was typing very quickly, so that it is likely unneeded, and won't help much, but I'd like to ensure maximum performance always.