Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I am currently trying to create a wordpress search function that shows live results underneath the search bar. There is an example on the World Bank website (screens below). I'm not looking for an autofill like you would find on Google.com which completes words you type, rather I want it to find actual posts on the site.

I tried doing a scrub through Wordpress Answers and other similar resources but have only run into implementing a Google type search which is not what I am looking for. Any help or points in the right direction would be greatly appreciated.

search-before

search after

share|improve this question
    
What do you want to happen when user clicks suggestion? Just fill search box with it? –  Rarst Feb 20 '12 at 9:16
    
Takes you to the respective post. User can still type and get search results normally, only clicking suggestions would direct to the post. –  mmaximalist Feb 20 '12 at 9:53
    
I have quick solution in mind for filling, but linking more problematic... Will think about it. –  Rarst Feb 20 '12 at 9:58
add comment

3 Answers

up vote 15 down vote accepted

The following uses jQuery UI Autocomplete, which has been included in WordPress since 3.3. (I've borrowed the format from @Rarst :D).

It's still not precisely what you're after, but gives you a good starting point. The following uses a the basic jQuery UI styling, but you can use the one that's currently worked out on trac and call that from your plug-in folder.

class AutoComplete {

    static $action = 'my_autocomplete';//Name of the action - should be unique to your plugin.

    static function load() {
        add_action( 'init', array( __CLASS__, 'init'));
    }

    static function init() {
        //Register style - you can create your own jQuery UI theme and store it in the plug-in folder
        wp_register_style('my-jquery-ui','http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css');    
        add_action( 'get_search_form', array( __CLASS__, 'get_search_form' ) );
        add_action( 'wp_print_footer_scripts', array( __CLASS__, 'print_footer_scripts' ), 11 );
        add_action( 'wp_ajax_'.self::$action, array( __CLASS__, 'autocomplete_suggestions' ) );
        add_action( 'wp_ajax_nopriv_'.self::$action, array( __CLASS__, 'autocomplete_suggestions' ) );
    }

    static function get_search_form( $form ) {
        wp_enqueue_script( 'jquery-ui-autocomplete' );
        wp_enqueue_style('my-jquery-ui');
        return $form;
    }

    static function print_footer_scripts() {
        ?>
    <script type="text/javascript">
    jQuery(document).ready(function ($){
        var ajaxurl = '<?php echo admin_url( 'admin-ajax.php' ); ?>';
        var ajaxaction = '<?php echo self::$action ?>';
        $("#secondary #searchform #s").autocomplete({
            delay: 0,
            minLength: 0,
            source: function(req, response){  
                $.getJSON(ajaxurl+'?callback=?&action='+ajaxaction, req, response);  
            },
            select: function(event, ui) {
                window.location.href=ui.item.link;
            },
        });
    });
    </script><?php
    }

    static function autocomplete_suggestions() {
        $posts = get_posts( array(
            's' => trim( esc_attr( strip_tags( $_REQUEST['term'] ) ) ),
        ) );
        $suggestions=array();

        global $post;
        foreach ($posts as $post): 
                    setup_postdata($post);
            $suggestion = array();
            $suggestion['label'] = esc_html($post->post_title);
            $suggestion['link'] = get_permalink();

            $suggestions[]= $suggestion;
        endforeach;

        $response = $_GET["callback"] . "(" . json_encode($suggestions) . ")";  
        echo $response;  
        exit;
    }
}
AutoComplete::load();
share|improve this answer
    
+1 - kool that you added the link. –  kaiser Feb 20 '12 at 17:45
1  
Couldn't thank you enough. Sometimes it seems all you need is a new perspective. I had a bad case of tunnel vision back there. And while it isn't completely what I was looking for it has definitely put me on the right track. Will post any further updates later. –  mmaximalist Feb 21 '12 at 4:51
add comment

Ok, this would be very basic example code that uses native suggest.js, WP core for Ajax and binds to default search form (from unmodified get_search_form() call). It's not precisely what you asked for, but incremental search is huge pain to get perfect. :)

class Incremental_Suggest {

    static function on_load() {

        add_action( 'init', array( __CLASS__, 'init' ) );
    }

    static function init() {

        add_action( 'wp_print_scripts', array( __CLASS__, 'wp_print_scripts' ) );
        add_action( 'get_search_form', array( __CLASS__, 'get_search_form' ) );
        add_action( 'wp_print_footer_scripts', array( __CLASS__, 'wp_print_footer_scripts' ), 11 );
        add_action( 'wp_ajax_incremental_suggest', array( __CLASS__, 'wp_ajax_incremental_suggest' ) );
        add_action( 'wp_ajax_nopriv_incremental_suggest', array( __CLASS__, 'wp_ajax_incremental_suggest' ) );
    }

    static function wp_print_scripts() {

        ?>
    <style type="text/css">
        .ac_results {
            padding: 0;
            margin: 0;
            list-style: none;
            position: absolute;
            z-index: 10000;
            display: none;
            border-width: 1px;
            border-style: solid;
        }

        .ac_results li {
            padding: 2px 5px;
            white-space: nowrap;
            text-align: left;
        }

        .ac_over {
            cursor: pointer;
        }

        .ac_match {
            text-decoration: underline;
        }
    </style>
    <?php
    }

    static function get_search_form( $form ) {

        wp_enqueue_script( 'suggest' );

        return $form;
    }

    static function wp_print_footer_scripts() {

        ?>
    <script type="text/javascript">
        jQuery(document).ready(function ($) {
            $('#s').suggest('<?php echo admin_url( 'admin-ajax.php' ); ?>' + '?action=incremental_suggest');
        });
    </script><?php
    }

    static function wp_ajax_incremental_suggest() {

        $posts = get_posts( array(
            's' => $_REQUEST['q'],
        ) );

        $titles = wp_list_pluck( $posts, 'post_title' );
        $titles = array_map( 'esc_html', $titles );
        echo implode( "\n", $titles );

        die;
    }
}

Incremental_Suggest::on_load();
share|improve this answer
add comment

You must do it using Ajax of course, but here there is a problem. Since WordPress uses MySQL, you might over stress your server with searching if you try to fill the search with the real Database queries trough Ajax, but what you might do is develop a system where all the posts are saved in to one big "wp_options" field and then when a search is done you query from that instead of doing a real search. But remember you need to update this chunk of text/serialized variable every time you create or edit a post.

If you are not willing to spend some time to develop this solution, I wouldn't recommend you doing this sort of "live search".

share|improve this answer
2  
In such use case resource usage of MySQL requests would be completely insignificant comparing to hit of loading WP core for Ajax requests. –  Rarst Feb 20 '12 at 9:15
1  
Depends on how you are trying to do the Ajax Request, in this case you don't really need all the WP core for your answer, the best case scenario would be just to load $wpdb and search for your field. But agreed, using the main WP Ajax url both of them could turn in to a problem, if not well handled. –  Webord Feb 20 '12 at 9:18
1  
Yes, I am just noting that MySQL performance would not be bottleneck (unless you get into hundreds of thousands of posts and such). WP core is much much slower. Network is also slower. –  Rarst Feb 20 '12 at 9:23
    
Yes, but doing some sort of Scalling with WP Core machines is much easier and faster. With MySQL machines is slower and harder. But on a normal installation, I agree with you. –  Webord Feb 20 '12 at 9:36
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.