A Simple Movie Search App w/ jQuery UI

Download

In this tutorial, we are using jQuery UI's autocomplete widget, to build a simple AJAX movie search form. The script is going to use TheMovieDatabase.org's free API, to provide auto suggestions against a vast database of movie titles.

For those of you who might not be familiar with TMDb.org, this is an open, community driven movie database. It is similar to IMDb, which you've probably heard about, but also provides a number of useful API's for developers.

Note: This tutorial is quite old and doesn't work any more due to changes in TheMovieDtabase's APIs.

Prerequisites

Before being able to use the API, you need to get a free developer key from TMDb after a quick registration. After this, remember to copy your key to movieInfo.php from the download archive.

Step 1 - XHTML

The markup consists of the two main div containers - #logo and #holder. The former holds the icon and the logo text in the form of transparent PNG images (defined as backgrounds to the respective divs), while the latter contains the search form and the submit button.

movieApp.html

<div id="page">

    <div id="logo">
        <div id="icon"></div>
        <div id="movieAppLabel"></div>
    </div>

    <div id="holder">
        <form action="http://www.themoviedb.org/search" method="post" target="_blank">
            <fieldset>
                <input type="text" id="movieName" name="search" />
            </fieldset>
        </form>
        <a href="#" class="button">Submit</a>
    </div>

</div>

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.2/jquery-ui.min.js"></script>
<script src="script.js"></script>

Notice that the action attribute of the form is pointed at TMDB's search page. The search terms are passed via POST with the #movieName text field. You can test it by filling in a movie name and submitting the form.

Lastly in the page are included jQuery, jQuery UI and our own script file. We are using jQuery UI's autocomplete widget to display a drop down list of movie titles which are fetched from TMDb's API. You can see the markup that is generated by the widget below.

<input class="ui-autocomplete-input"/>
<ul class="ui-autocomplete ui-menu ui-widget ui-widget-content ui-corner-all">
  <li class="ui-menu-item">
    <a class="ui-corner-all">item 1</a>
  </li>
  <li class="ui-menu-item">
    <a class="ui-corner-all">item 2</a>
  </li>
  <li class="ui-menu-item">
    <a class="ui-corner-all">item 3</a>
  </li>
</ul>

This code is generated automatically by the widget and appended before the closing body tag.

2.jpg

Step 2 - PHP

When you start typing a movie title in the text box of the form, an AJAX request is sent to moveInfo.php. This script sends a search request to TMDb's API, with our developer key. The service returns a JSON object with suitable movie titles. The script processes them and outputs them back as a response to the AJAX request.

Lets take a closer look at how this works.

movieInfo.php

/**
 *  Define your API key below. To obtain one, visit
 *  http://www.themoviedb.org/account/signup
 */

$api_key = '...';

// If the request was not issued by AJAX, or
// the search term is missing, exit:

if(!$_SERVER["HTTP_X_REQUESTED_WITH"] || !$_GET['term']){
    exit;
}

include 'tmdbAPI/TMDb.php';

$tmdb = new TMDb($api_key);

// Send a search API request to TMDb,
// and parse the returned JSON data:

$json = json_decode($tmdb->searchMovie($_GET['term']));

$response = array();

$i=0;
foreach($json as $movie){

    // Only movies existing in the IMDB catalog (and are not adult) are shown

    if(!$movie->imdb_id || $movie->adult) continue;
    if($i >= 8 ) break;

    // The jQuery autocomplete widget shows the label in the drop down,
    // and adds the value property to the text box.

    $response[$i]['value'] = $movie->name;
    $response[$i]['label'] = $movie->name . ' <small>(' . date('Y',strtotime($movie->released)).')</small>';
    $i++;
}

// Presenting the response as a JSON object:

echo json_encode($response);

Luckily for us, there is a PHP class available, that handles all communication with the TMDb API. We just need to include it into the page, and provide the developer API key we received from TMDb. The search terms, that the user has entered into the search box, are available in $_GET['term']. Calling the searchMovie() method with these terms, will yield a JSON object, containing all kinds of information about the movies that match our search criteria. You can see a sample response below.

[{
    "score": 8.750235,
    "popularity": 3,
    "translated": true,
    "adult": false,
    "language": "en",
    "name": "The Hitchhiker's Guide to the Galaxy",
    "alternative_name": "The Hitchhikers Guide to the Galaxy",
    "movie_type": "movie",
    "id": 7453,
    "imdb_id": "tt0371724",
    "url": "http://www.themoviedb.org/movie/7453",
    "rating": 6.8,
    "certification": "PG",
    "overview": "Mere seconds before the Earth is to be demolished by an alien construction crew, Arthur Dent is swept off the planet by his friend Ford Prefect, a researcher penning a new edition of \"The Hitchhiker's Guide to the Galaxy.\"",
    "released": "2005-04-20",
    "posters": [{
        "image": {
            "type": "poster",
            "size": "original",
            "height": 1000,
            "width": 675,
            "url": "http://hwcdn.themoviedb.org/posters/16e/4bcc96cd017a3c0f2600016e/the-hitchhiker-s-guide-to-the-galaxy-original.jpg",
            "id": "4bcc96cd017a3c0f2600016e"
        }
    }],
    "version": 22,
    "last_modified_at": "2010-07-19 22:59:02"
}]

The response contains the title of the movie, an overview, release date, a corresponding IMDB id, and even posters and fan art. We do not need most of this information, so PHP reduces it only to a title and a release year, after which outputs it in the form of a JSON object, ready to be used by the autocomplete. This brings us to the next step.

Step 3 - jQuery

As you know, jQuery comes with a lot of useful functionality in the form of plugins. There is also a dedicated extension of the library, for building user interfaces, known as jQuery UI. It gives developers widgets, which are ready for use and easy to customize. One of these widgets is the new autocomplete widget, introduced in the newer versions of the library.

Lets take a look at how it is used.

script.js

$(document).ready(function(){

    // Caching the movieName textbox:
    var movieName = $('#movieName');

    // Defining a placeholder text:
    movieName.defaultText('Type a Move Title');

    // Using jQuery UI's autocomplete widget:
    movieName.autocomplete({
        minLength   : 5,
        source      : 'movieInfo.php'
    });

    $('#holder .button').click(function(){
        if(movieName.val().length && movieName.data('defaultText') != movieName.val()){
            $('#holder form').submit();
        }
    });
});

// A custom jQuery method for placeholder text:

$.fn.defaultText = function(value){

    var element = this.eq(0);
    element.data('defaultText',value);

    element.focus(function(){
        if(element.val() == value){
            element.val('').removeClass('defaultText');
        }
    }).blur(function(){
        if(element.val() == '' || element.val() == value){
            element.addClass('defaultText').val(value);
        }
    });

    return element.blur();
}

To create an autocomplete, we just need to call the autocomplete() method. It takes a number of optional parameters. The most important ones are minLength (which prevents request to the server from being fired before a certain number of characters has been typed) and source, which determines the data that is shown in the drop down list.

Source can take either an array with strings, a URL (to which an AJAX request will be sent) or a callback function. In our case, the URL of movieInfo.php will suffice.

Here is a sample response, which is returned by movieInfo.php (this JSON object was compiled after a request to TMDb's API for "Hitchhiker's guide").

[{
    "value": "Hachiko: A Dog's Story",
    "label": "Hachiko: A Dog's Story <small>(2009)<\/small>"
},
{
    "value": "Teenage Hitch-hikers",
    "label": "Teenage Hitch-hikers <small>(1975)<\/small>"
},
{
    "value": "The Hitchhiker's Guide to the Galaxy",
    "label": "The Hitchhiker's Guide to the Galaxy <small>(2005)<\/small>"
},
{
    "value": "The Hitch-Hiker",
    "label": "The Hitch-Hiker <small>(1953)<\/small>"
}]

Each object in the array contains a value and a label property. The label is only shown in the dropdown list, while the value is inserted into the textbox once the item is selected.

1.jpg

Step 4 - CSS

Now that all the markup is generated and is in place, it is time to start beautifying.

styles.css - Part 1

#page{
    width:600px;
    margin:150px auto 0;
}

/* Logo */

#logo{
    width:380px;
    position:relative;
    height:90px;
    margin:0 auto;
}

#icon{
    width:80px;
    height:86px;
    background:url('img/icon.png') no-repeat;
    float:left;
}

#movieAppLabel{
    width:268px;
    height:58px;
    background:url('img/logo_txt.png') no-repeat;
    position:absolute;
    right:0;
    top:18px;
}

/* The Search Box & Holder */

#holder{
    width:530px;
    height:145px;
    background:url('img/holder.png') no-repeat center center;
    margin:30px auto;
    position:relative;
}

#holder fieldset{
    position:absolute;
    top:52px;
    left:40px;
    border-bottom:1px solid #fff;
}

#holder input{
    font-family:'Myriad Pro',Arial,Helvetica,sans-serif;
    border:none;
    border-bottom:1px solid #bbb;
    background:none;
    color:#8D8D8D;
    font-size:20px;
    padding:4px 0;
    width:250px;
    text-shadow:1px 1px #fff;
    outline:none;
}

In the first part of the code, we style the #logo, and the #holder divs. The shutter icon and the logo text are defined as backgrounds to the #icon and #movieAppLabel divs respectively. Relative positioning is applied to the #holder so that it is easier to position the input box and the submit button.

styles.css - Part 2

fieldset{
    border:none;
}

/* The Blue Button */

a.button{
    background:url('img/buttons.png') no-repeat;
    width:105px;
    height:37px;
    position:absolute;
    top:52px;
    right:42px;
    text-indent:-9999px;
    overflow:hidden;
    border:none !important;
}

a.button:hover{
    background-position:left bottom;
}

/* Styling the markup generated by the autocomplete jQuery UI widget */

ul.ui-autocomplete{
    width:250px;
    background-color:#f5f5f5;
    border:1px solid #fff;
    outline:1px solid #ccc;
}

ul.ui-autocomplete li{
    list-style:none;
    border-bottom:1px solid #e0e0e0;
    border-top:1px solid #fff;
}

ul.ui-autocomplete li:first-child{
    border-top:none;
}

ul.ui-autocomplete li:last-child{
    border-bottom:none;
}

ul.ui-autocomplete li a{
    color:#999;
    border:none !important;
    text-decoration:none !important;
    padding:10px 17px;
    display:block;
}

#ui-active-menuitem{
    background-color:#fff;
    color:#666;
    cursor:pointer;
}

jQuery UI does come with its own styles, however they are rather clunky and do not fit well into the current design. This is why we are applying a number of rules (starting from line 23), which apply a custom design to the autocomplete widget. The structure of the widget is basically an unordered list, with each of the suggested items being a hyperlink in a li element. With this in mind (and after looking up the appropriate class names from the code in step one) we can safely style the drop down list and perfectly blend it with the rest of the design.

With this our Simple Movie Search App is complete!

To Wrap it Up

You can modify this script to use any kind of api and data. This can be a powerful tool, as it might assist users in typing search terms that they may not normally think of themselves. For example providing your product names as search suggestions, may be an effective tactic to expose more of your merchandise and improve sales.

What do you think? How would you improve this app?

Bootstrap Studio

The revolutionary web design tool for creating responsive websites and apps.

Learn more

Related Articles

John Green

Interesting engine you just made. Very smart; it´s nice to see: your -in last time- often made "Movie" tutorials! ;)

Does'n work.....

Martin Angelov

Thank you for the comments!

@ GHJKIKO

Can you describe what problems you are facing?

Rafael Ortiz

Hi, i'm not being able to input on the search field on the demo
s this a bug ?.

Rafael Ortiz

Hm ok working now.

Michael Jones

I have download it but when i try it my self on computer it don't autocomplete (the box don't come up with movie titles in it) what is wrong with it and what do i do to fix it?

esranull

very very good working thanks for sharing

LordTinchen

Very nice! I think that putting the picture of the movie in the autocomplete list will be nice....

Martin Angelov

@ Michael Jones

There might be a number of things interfering if you run it on your local PC (from firewalls to restrictions in your PHP config). It would be best to try to upload it directly to your host. Also do not forget to add your API key in movieInfo.php.

@ LordTinchen

Yes it would be a nice touch and a great exercise for Tzine's readers. If someone is willing to do it I would be more than happy to add a link to their page in the the article : ).

search videos

Thank you so much , i like your design !

Thanks again.

If you click on a title when the auto-complete shows can you include the year in the input box as this will direct you to the movie page on TMDb when you click search.

Great article Martin, as usual :D.

Towards the end, you started talking about using it for different scenarios. How difficult would it be to use your own data from a database rather than using an API for another site. For instance (in my case, it's WordPress), if someone had their own movie site and they wanted the search box to only display movie titles (which are each a page), how would they get that information to the search box and autocomplete (securely)?

My question is probably more complicated than that which could be answered in comments. If so and you don't think you'll be doing a follow-up to this that covers my question, would you be able to give me some terms to search for that could help with using data from a database (preferably WordPress)?

Thanks. I understand if you don't have time for any of this :D

Martin Angelov

@ James

Yes, to do this you can replace lines 37 - 39 in movieInfo.php, which are currently:

$response[$i]['value'] = $movie->name;
$response[$i]['label'] = $movie->name . ' (' . date('Y',strtotime($movie->released)).')';
$i++;

With this code:

$response[]  =  $movie->name . ' (' . date('Y',strtotime($movie->released)).')';

This way the autocomplete widget will use the same data for both displaying in the dropdown, and inserting in the textbox .

@ Vinnie

Actually it won't be that hard. You just need to do a MySQL query instead of the API call.

Something like this:

mysql_query("SELECT title FROM movies WHERE title LIKE '%".
    mysql_real_escape_string($_GET['term'])."%'");

I would suggest that you stay away from WordPress' APIs if you can. They can bring a significant overhead to your code. Just copy movieInfo.php to the root of your site, modifying it a bit to handle its own database connection and output the results of the select query, instead those of the API call.

Thanks Martin for the above edit.

To get this to work i had to include Services_JSON by Michal Migurski .

Download link:
http://pear.php.net/pepr/pepr-proposal-show.php?id=198

Download the PEAR package file (.tgz) and include function below at the top of movieInfo.php

JSON Function:

if ( !function_exists('json_decode') ){ function json_decode($content, $assoc=false){ require_once '../includes/JSON.php'; if ( $assoc ){ $json = new Services_JSON(SERVICES_JSON_LOOSE_TYPE); } else { $json = new Services_JSON; } return $json->decode($content); } }

if ( !function_exists('json_encode') ){ function json_encode($content){ require_once '../includes/JSON.php'; $json = new Services_JSON;

return $json->encode($content); } }

This is the only way it would work on my free hosting, maybe it's useful for someone else.

RafaelOrtiz

Would be interesting to have multi-language search suport for movies, maybe the IMDB API allows this ?.

Hi,

I like this application a lot. It is very simple and good to see.

I would like to have this on my website.

Stewart McKie

Thanks for sharing this elegant search tool. Re. Vinnie's question above is the answer much the same if I wanted the search to point to a database of titles that are linked to a URL that displays other data about the movie?