¿Cómo crear una búsqueda de autocompletar en vivo?

22

Actualmente estoy tratando de crear una función de búsqueda de WordPress que muestre resultados en vivo debajo de la barra de búsqueda. Hay un ejemplo en el sitio web del Banco Mundial (pantallas a continuación). No estoy buscando un autocompletado como el que encontrarías en Google.com que completa las palabras que escribes, sino que quiero que encuentre publicaciones reales en el sitio.

Intenté hacer un barrido a través de Wordpress Answers y otros recursos similares, pero solo me he encontrado con la implementación de una búsqueda de tipo de Google que no es lo que estoy buscando. Cualquier ayuda o puntos en la dirección correcta sería muy apreciada.

buscar antes

buscar

mmaximalista
fuente
¿Qué quieres que suceda cuando el usuario hace clic en la sugerencia? Solo llene el cuadro de búsqueda con él?
Rarst
Te lleva a la publicación respectiva. El usuario aún puede escribir y obtener resultados de búsqueda normalmente, solo haciendo clic en las sugerencias se dirigen a la publicación.
mmaximalist
Tengo una solución rápida en mente para llenar, pero la vinculación es más problemática ... Lo pensaré.
Rarst

Respuestas:

20

Lo siguiente usa jQuery UI Autocomplete, que se ha incluido en WordPress desde 3.3. (He tomado prestado el formato de @Rarst : D).

Todavía no es precisamente lo que buscas, pero te da un buen punto de partida. Lo siguiente usa un estilo básico de jQuery UI, pero puede usar el que actualmente funciona en trac y llamarlo desde su carpeta de complementos.

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();
Stephen Harris
fuente
12

Ok, este sería un código de ejemplo muy básico que usa un suggest.jsnúcleo WP nativo para Ajax y se une al formulario de búsqueda predeterminado (desde una get_search_form()llamada no modificada ). No es exactamente lo que pediste, pero la búsqueda incremental es un gran dolor para ser perfecto. :)

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();
Rarst
fuente
0

Debes hacerlo usando Ajax, por supuesto, pero aquí hay un problema. Dado que WordPress usa MySQL, puede estresar demasiado su servidor con la búsqueda si intenta completar la búsqueda con las consultas reales de la base de datos a través de Ajax, pero lo que podría hacer es desarrollar un sistema donde todas las publicaciones se guarden en una gran "wp_options" campo y luego, cuando se realiza una búsqueda, consulta desde ese lugar en lugar de hacer una búsqueda real. Pero recuerde que necesita actualizar este fragmento de texto / variable serializada cada vez que crea o edita una publicación.

Si no está dispuesto a pasar un tiempo para desarrollar esta solución, no le recomendaría que haga este tipo de "búsqueda en vivo".

Webord
fuente
2
En tal caso de uso, el uso de recursos de las solicitudes de MySQL sería completamente insignificante en comparación con el impacto de cargar el núcleo de WP para las solicitudes de Ajax.
Rarst
1
Depende de cómo esté tratando de hacer la Solicitud de Ajax, en este caso realmente no necesita todo el núcleo de WP para su respuesta, el mejor de los casos sería simplemente cargar $ wpdb y buscar su campo. Pero de acuerdo, utilizando la URL principal de WP Ajax, ambos podrían convertirse en un problema, si no se manejan bien.
Webord
1
Sí, solo estoy señalando que el rendimiento de MySQL no sería un cuello de botella (a menos que entres en cientos de miles de publicaciones y demás). WP core es mucho más lento. La red también es más lenta.
Rarst
Sí, pero hacer algún tipo de escalado con máquinas WP Core es mucho más fácil y rápido. Con las máquinas MySQL es más lento y más difícil. Pero en una instalación normal, estoy de acuerdo con usted.
Webord