PhpRiot
Become Zend Certified

Prepare for the ZCE exam using our quizzes (web or iPad/iPhone). More info...


When you're ready get 7.5% off your exam voucher using voucher CJQNOV23 at the Zend Store

Cloning Google Suggest With Ajaxac

Piecing Together Googlesuggestclonejax.class.PHP

Now all the major parts have been developed, everything needs to be put together.

Just to keep the constructor code sparse as possible, we create a setup() method which loads in the application javascript library (googlesuggestclone.js), and creates the widgets we made on the last page.

Below is the whole class, but please note, we still need to make some changes to index.php:

Listing 17 listing-17.php
<?php
    require_once('AjaxACApplication.class.php');
 
    class GoogleSuggestCloneJax extends AjaxACApplication
    {
        /**
         * Database connection details
         */
        var $db_hostname = 'localhost';
        var $db_username = 'ajaxac';
        var $db_password = '';
        var $db_database = 'ajaxac';
        var $db_table    = 'google_suggest_clone_data';
 
        /**
         * Time to wait after a keypress before fetching suggestions
         */
        var $keypress_timeout_ms = 350;
 
        /**
         * Maximum number of suggestions to return
         */
        var $suggestion_limit = 10;
 
        /**
         * Constructor. Creates the necessary action and then inits widgets
         */
        function GoogleSuggestCloneJax()
        {
            parent::AjaxACApplication();
            $this->registerActions('getsuggestions');
            $this->setup();
        }
 
        /**
         * Create necessary widgets and events
         */
        function setup()
        {
            // utility functions for the app
            $this->addJsLib('googlesuggestclone.js');
 
            // the form input where users type their query
            $query = $this->createWidget('query');
            $query->addEvent(AJAXAC_EV_ONKEYDOWN, 'querykeydown');
            $this->addWidget($query);
 
            // the div where results will be displayed
            $results = $this->createWidget('results');
            $results->addEvent(AJAXAC_EV_ONLOAD, 'resultsload');
            $this->addWidget($results);
 
            // the countdown timer that is started/reset after a key is pressed
            require_once('Widgets/AjaxACWidgetTimer.class.php');
            $timer = new AjaxACWidgetTimer($this, 'gsctimer');
            $timer->addEvent(AJAXAC_EV_ONTIMEREXPIRE, 'timerexpire');
            $timer->setTimeoutFromInt($this->keypress_timeout_ms);
            $this->addWidget($timer);
        }
 
        /**
         * Handle the getsuggestions HTTP subrequest
         */
        function action_getsuggestions()
        {
            $suggestions = array();
            $this->getSuggestions($this->getRequestValue('q'), $suggestions);
            $this->sendResponseData('jsarray', $suggestions);
        }
 
        /**
         * Initialise results output by clearing and hiding it
         */
        function event_resultsload(&$widget, $event)
        {
            return "function() { gsc_emptyresults(this); }";
        }
 
        /**
         * Handle various keypresses that occur on query input
         */
        function event_querykeydown(&$widget, $event)
        {
            $callback = "
                            function(e)
                            {
                                key = ajaxac_getkeycode(e);
                                switch (key) {
                                    case 27: // escape
                                        gsc_hide(%1\$s);
                                        return false;
                                        break;
                                    case 38: // up arrow
                                        gsc_handleup(%1\$s, %2\$s);
                                        return false;
                                        break;
                                    case 40: // down arrow
                                        gsc_handledown(%1\$s, %2\$s);
                                        return false;
                                        break;
                                    default:
                                        %3\$s.start();
                                }
                                return true;
                            }
                        ";
 
            $callback = sprintf($callback,
                                $this->getHookName('results'),
                                $this->getHookName('query'),
                                $this->getHookName('gsctimer'));
 
            return $callback;
        }
 
        /**
         * Handle the time expiring (i.e. initiate the HTTP sub request
         */
        function event_timerexpire(&$widget, $event)
        {
            require_once('Widgets/AjaxACWidgetXMLHttpRequest.class.php');
            $xmlhttp = new AjaxACWidgetXMLHttpRequest($this, 'gscfetch', AJAXAC_METH_GET);
            $xmlhttp->setFilenameFromString($this->getApplicationUrl('getsuggestions'));
            $xmlhttp->addParamFromHookValue('q', '_q', '');
            $xmlhttp->addEvent(AJAXAC_EV_ONXMLHTTPSUCCESS, 'handlesuggestions');
            $this->addWidget($xmlhttp);
 
            $callback = "
                            function()
                            {
                                _q = gsc_getquery(%1\$s, %2\$s.value);
                                if (_q.length == 0)
                                    return false;
                                try {
                                    %3\$s
                                }
                                catch (e) { }
 
 
                                return false;
                            }
                        ";
 
            $callback = sprintf($callback,
                                $this->getHookName('results'),
                                $this->getHookName('query'),
                                $xmlhttp->getJsCode());
 
            return $callback;
        }
 
        /**
         * Receive the suggestions and load them into results box
         */
        function event_handlesuggestions(&$widget, $event)
        {
            $callback = "
                         function()
                         {
                             _data = ajaxac_receivejsarray(%1\$s.responseText);
                             gsc_emptyresults(%2\$s);
                             if (_data.length > 0) {
                                 for (i = 0; i < _data.length; i++) {
                                     gsc_addresult(%2\$s, %3\$s,
                                                   _data[i][0], _data[i][1],
                                                   i == 0);
                                 }
                                 gsc_show(%2\$s);
                             }
                         }
                        ";
            $callback = sprintf($callback,
                                $widget->getHookName(),
                                $this->getHookName('results'),
                                $this->getHookName('query'));
            return $callback;
        }
 
        /**
         * Get the suggestions from the database and write to array
         */
        function getSuggestions($prefix, &$arr)
        {
            $conn = @mysql_connect($this->db_hostname, $this->db_username, $this->db_password);
            if (!$conn)
                return;
            if (!@mysql_select_db($this->db_database, $conn)) {
                mysql_close($conn);
                return;
            }
 
            // firstly clean up the data
            $prefix = ltrim(preg_replace('/[^a-z0-9_. ]/', '', strtolower($prefix)));
            $prefix = preg_replace('/\s+/', ' ', $prefix);
            if (strlen($prefix) > 0) {
                $query = sprintf("select search_term, num_results
                                    from %s
                                    where search_term like '%s%%'
                                    limit %d",
                                 $this->db_table,
                                 mysql_real_escape_string($prefix),
                                 $this->suggestion_limit);
                $result = mysql_query($query);
                while ($row = mysql_fetch_row($result)) {
                    if ($row[1] == 0)
                        $row[1] = '';
                    else
                        $row[1] = number_format($row[1]) . ' result' . ($row[1] != 1 ? 's' : '');
                    $arr[] = $row;
                }
            }
            mysql_close($conn);
        }
    }
?>

In This Article