Placed in: Home arrow Programming arrow Webdesign arrow A fancy Apple.com-style search suggestion viagra australia
viagra online
viagra sale
cialis online
cialis australia
A fancy Apple.com-style search suggestion

Apple is known to create beautiful products (next to the needed functionality of course). I already wrote several articles on how you can transfer some amazing iPhone designs to your webbrowser, I own a MacBook Pro (which also looks pretty sleek) and many other products from Apple are well known for their amazing design.

The website from Apple isn't less: The layout is simple yet beautiful. Yet, one of the most awesome things about the website is the search functionality. It gives you suggestions (with images) about the several products they offer, making it really user-friendly.

Today, we're trying to recreate the effect from that website by creating a fancy apple.com-style search suggestion. Make sure you check out the demo (or visit Apple.com) to see this awesome effect work.

A fancy Apple.com-style search suggestion

This example makes use of several techniques: MySQL (for the database), HTML/CSS for styling, PHP for retrieving the data and jQuery for the AJAX request. How about that for some nice way of combining powerful techniques to create something nice like this. You do need some basic knowledge about these techniques to fully understand this tutorial.

Demo Apple.com-style search suggestion   Download Apple.com-style search suggestion

IMPORTANT NOTE:
As you can see, the demo is located on another server. The reason for this is, that every time a user presses on his keyboard, a call is made to the MySQL database. When loads of users do loads of calls (at the same time), this could result in slowing down the database. The answer for this would that the results should be cached - Something that isn't implemented right now.

Safari, Chrome and Opera are currently the only webbrowsers that support the drop shadow effect around the the search results. Other browsers will simply display the results without the drop shadow.

This technique would be great if it were converted to a plugin for a CMS (WordPress/Joomla/Drupal etc.), but also just very cool to have on your website.

Safari Demo

Check out this small video I placed on YouTube, showing this effect in full glory.

Want to learn how I created it? Check it out.

MySQL

We'll need two tables in MySQL to do the job. I created a search table (containing most of the data) and a categories table (referenced by the search items). Visually, they look like this:

MySQL Categories

MySQL Search

The SQL dump looks like this:

 
CREATE TABLE IF NOT EXISTS `categories` (
  `cid` int(11) NOT NULL AUTO_INCREMENT,
  `cat_name` varchar(255) NOT NULL,
  `cat_url` text NOT NULL,
  PRIMARY KEY (`cid`)
);
 
CREATE TABLE IF NOT EXISTS `search` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `cat_id` int(11) NOT NULL,
  `name` varchar(255) NOT NULL,
  `img` varchar(255) NOT NULL,
  `desc` text NOT NULL,
  `url` text NOT NULL,
  PRIMARY KEY (`id`)
);

I assume the names of the columns are pretty straight forward. You'll need to fill in the data yourself (in the download, you can find all the INSERTS that can be found in the demo). Also, take note of the AUTO_INCREMENT from both id's.

Now that we have the data stored, we'll need a front-end to place the data in. On to the next part!

HTML

Page

The HTML from the page isn't the spectecular: It simply holds one form element with an input box. Take note that no action is defined to the form. If you actually want to pass the data to the search page, you should add it. Also, no input-submit was added.

 
<div>
   <form id="searchform">
      <div>
         What are you looking for? <input type="text" size="30" value="" />
      </div>
      <div id="suggestions"></div>
   </form>
</div>

More interesting in the code above, is the (empty) divider with an id suggestions. We'll fill up this divider later on with jQuery to place the actual found search results in.

Search results

Even more interesting is the searchresults that we're going to display. Here's the HTML, I'll explain it below.

 
<p id="searchresults">
   <span class="category">[CATEGORY_FROM_DATABASE]</span>
      <a href="[URL_FROM_DATABASE]">
         <img alt="" src="search_images/[IMG_FROM_DATABASE]"/>
         <span class="searchheading">[HEADING_FROM_DATABASE]</span>
         <span>[TEXT_FROM_DATABASE]</span>
      </a>
      <a href="[URL_FROM_DATABASE]">
         <img alt="" src="search_images/[IMG_FROM_DATABASE]"/>
         <span class="searchheading">[HEADING_FROM_DATABASE]</span>
         <span>[TEXT_FROM_DATABASE]</span>
      </a>
      <!-- more items -->
   <span class="category">Webdesign</span>
      <a href="[URL_FROM_DATABASE]">
         <img alt="" src="search_images/[IMG_FROM_DATABASE]"/>
         <span class="searchheading">[HEADING_FROM_DATABASE]</span>
         <span>[TEXT_FROM_DATABASE]</span>
      </a>
   <!-- more categories -->
   <span class="seperator">
      <a href="http://www.marcofolio.net/sitemap.html">Nothing interesting here? Try the sitemap.</a>
   </span>
</p>
  • #searchresults - Main container to place the search results in.
  • .category - When a new category is displayed, simply use this span to differ it from the actual links.
  • .seperator - This is used at the bottom of the suggestion, linking to another page (in this case: the sitemap).
  • As you can expect, all values between the [] and written in capitals needs to be data from the database.

On to some CSS styling and make it look a lot more pretty!

CSS

Page

First, we'll fancy-up the page (looks pretty boring now, right?). I used the same background as in the polaroid viewer (hey, it looks pretty nice) and wrote the following CSS.

 
/* HTML ELEMENTS */
body { font-family:"Lucida Grande","Lucida Sans Unicode",Arial,Verdana,sans-serif;
   background-color:#efefef; background-image:url(../images/bg.jpg); }
 
/* SEARCH FORM */
#searchform { margin:50px 200px; font-size:18px; }
#searchform div { color:#eeeeee; }
#searchform div input { font-size:18px; padding:5px; width:320px; }
#suggestions{ position: relative; left:235px; width:320px; display:none; }

Nothing really fancy going on over here, except for the #suggestions. As you can see, the display is set to none. Like I said, we'll fill that container using jQuery but we'll also show it (fade it in) using the javascript framework. We'll get to that later.

Our page should now look like this:

Web Page

Search results

The search results use a little bit more complex CSS. This is what I came up with.

 
/* SEARCHRESULTS */
#searchresults { border-width:1px; border-color:#919191; border-style:solid; width:320px; background-color:#a0a0a0; font-size:10px; line-height:14px; }
#searchresults a { display:block; background-color:#e4e4e4; clear:left; height:56px; text-decoration:none; }
#searchresults a:hover { background-color:#b7b7b7; color:#ffffff; }
#searchresults a img { float:left; padding:5px 10px; }
#searchresults a span.searchheading { display:block; font-weight:bold; padding-top:5px; color:#191919; }
#searchresults a:hover span.searchheading { color:#ffffff; }
#searchresults a span { color:#555555; }
#searchresults a:hover span { color:#f1f1f1; }
#searchresults span.category { font-size:11px; margin:5px; display:block; color:#ffffff; }
#searchresults span.seperator { float:right; padding-right:15px; margin-right:5px;
      background-image:url(../images/shortcuts_arrow.gif); background-repeat:no-repeat; background-position:right; }
#searchresults span.seperator a { background-color:transparent; display:block; margin:5px; height:auto; color:#ffffff; }

Nothing really fancy going on over here actually. Only the #searchresults a is displayed as an block element, making the click-area have a full width and height. The search results page (when filled with data) should now look like this.

Search Results

Awesome, looks pretty good already! Now for the fun stuff: The PHP.

PHP

You'll need to understand that the actual page is a static HTML file. The search results is a dynamic page generated by PHP based on the data retrieved.

This is the final PHP file that retrieves the data from the database and generates the needed HTML. I've added some comments to make the code more clear.

 
<p id="searchresults">
<?php
   // PHP5 Implementation - uses MySQLi.
   // mysqli('localhost', 'yourUsername', 'yourPassword', 'yourDatabase');
   $db = new mysqli('localhost', 'yourUsername', 'yourPassword', 'yourDatabase');
   
   if(!$db) {
      // Show error if we cannot connect.
      echo 'ERROR: Could not connect to the database.';
   } else {
      // Is there a posted query string?
      if(isset($_POST['queryString'])) {
         $queryString = $db->real_escape_string($_POST['queryString']);
         
         // Is the string length greater than 0?
         if(strlen($queryString) >0) {
            $query = $db->query("SELECT * FROM search s INNER JOIN categories c ON s.cat_id = c.cid WHERE name LIKE '%" . $queryString . "%' ORDER BY cat_id LIMIT 8");
            
            if($query) {
               // While there are results loop through them - fetching an Object.
               
               // Store the category id
               $catid = 0;
               while ($result = $query ->fetch_object()) {
                  if($result->cat_id != $catid) { // check if the category changed
                     echo '<span class="category">'.$result->cat_name.'</span>';
                     $catid = $result->cat_id;
                  }
                     echo '<a href="'.$result->url.'">';
                     echo '<img src="search_images/'.$result->img.'" alt="" />';
                     
                     $name = $result->name;
                     if(strlen($name) > 35) { 
                        $name = substr($name, 0, 35) . "...";
                     }                     
                     echo '<span class="searchheading">'.$name.'</span>';
                     
                     $description = $result->desc;
                     if(strlen($description) > 80) { 
                        $description = substr($description, 0, 80) . "...";
                     }
                     
                     echo '<span>'.$description.'</span></a>';
                  }
                  echo '<span class="seperator"><a href="http://www.marcofolio.net/sitemap.html" title="Sitemap">Nothing interesting here? Try the sitemap.</a></span><br class="break" />';
            } else {
               echo 'ERROR: There was a problem with the query.';
            }
         } else {
            // Dont do anything.
         } // There is a queryString.
      } else {
         echo 'There should be no direct access to this script!';
      }
   }
?>
</p>

Some final explanation:

  • isset($_POST['queryString']) - When the PHP file received a POST request with a value queryString, it'll work (otherwise, it doesn't). We'll do the POST request with jQuery.
  • mysqli - This script makes use of the PHP5 implementation of MySQLi. It created an object from the database (really handy). You'll need to change the values in the PHP file to make it connect to your database.
  • $db->query - This is the place where the query is executed. As you can see, I join on the categories table to retrieve the correct category name. You can also see, that the $queryString only looks (and searches) by the name. You could enhance this query to also look in the description etc.
  • strlen($name) > 35 - At this point, the script checks if the name is larger than 35 characters. If it is, it trims it down to 35 characters + "..." to make it fit.

jQuery

First things first: We'll need to change the original HTML to let the browser react to the "keydown" when the user is typing in the input field. To do so, add the following to the input:

 
onkeyup="lookup(this.value);"

Now, we'll need to actually define the lookup function within jQuery. Once again, I've added comments to make the code clear.

 
function lookup(inputString) {
   if(inputString.length == 0) {
      $('#suggestions').fadeOut(); // Hide the suggestions box
   } else {
      $.post("rpc.php", {queryString: ""+inputString+""}, function(data) { // Do an AJAX call
         $('#suggestions').fadeIn(); // Show the suggestions box
         $('#suggestions').html(data); // Fill the suggestions box
      });
   }
}

As you can see, when the inputString is empty, the suggestions box is being fadeOut. If not, it does an AJAX call to the PHP file (rpc.php) giving the inputString ad queryString. That's about it! jQuery makes this AJAX stuff prety simple.

Look in the JavaScript file to see how the CSS3 is injected to display the drop shadow.

Conclusion and Download

Although this tutorial may seem pretty hard, it actually isn't. It does really improve the search of your website and when this comes available as plugin for something, it would be really great. It's pretty fun to see too!

Demo Apple.com-style search suggestion   Download Apple.com-style search suggestion

Hope this was useful for you and that you can use this somewhere in your next project. Please share your thoughts!

UPDATE: PHP4 version

Ryan McDonough took the time and effort (thanks!) to create and share a PHP4 version of this script. You can download this version (that doesn't make use of mysqli) from the download section.

When using the PHP4 script, open the SystemComponent.php file and change the variables to connect with the database.

UPDATE: Wordpress Plugin

Daniel Kowalski from IT Systempartner took the time and effort (thanks!) to convert this script into a WordPress plugin called Searchlight. Feel free to visit his site and try it out.


Tags:  apple.com search suggestion mysql php jquery ajax

Interested in this topic? You might enjoy another article I've written called

Did you like this article? Subscribe to my feed or email to keep updated on new articles.

Spread the word and submit to:
Digg!Reddit!Del.icio.us!Facebook!StumbleUpon!
 
< Prev   Next >
Subscribe

Subscribe to Marcofolio