Comment créer une recherche de remplissage automatique en direct?

22

J'essaie actuellement de créer une fonction de recherche wordpress qui affiche les résultats en direct sous la barre de recherche. Il y a un exemple sur le site Web de la Banque mondiale (écrans ci-dessous). Je ne recherche pas un remplissage automatique comme vous le trouverez sur Google.com qui complète les mots que vous saisissez, je veux plutôt qu'il trouve de vrais messages sur le site.

J'ai essayé de faire un gommage via Wordpress Answers et d'autres ressources similaires, mais je n'ai rencontré que la mise en œuvre d'une recherche de type Google qui n'est pas ce que je recherche. Toute aide ou point dans la bonne direction serait grandement apprécié.

recherche avant

chercher

mmaximaliste
la source
Que voulez-vous qu'il se passe lorsque l'utilisateur clique sur une suggestion? Remplissez simplement le champ de recherche avec?
Rarst
Vous amène au poste respectif. L'utilisateur peut toujours taper et obtenir les résultats de la recherche normalement, seules les suggestions de clic dirigeraient vers le message.
mmaximalist
J'ai une solution rapide à l'esprit pour le remplissage, mais le lien est plus problématique ... J'y penserai.
Rarst

Réponses:

20

Ce qui suit utilise jQuery UI Autocomplete, qui est inclus dans WordPress depuis la 3.3. (J'ai emprunté le format à @Rarst : D).

Ce n'est toujours pas exactement ce que vous recherchez, mais vous donne un bon point de départ. Ce qui suit utilise un style de base jQuery UI, mais vous pouvez utiliser celui qui est actuellement élaboré sur trac et l'appeler à partir de votre dossier de plug-in.

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
la source
12

Ok, ce serait un exemple de code très basique qui utilise un suggest.jsnoyau WP natif pour Ajax et se lie au formulaire de recherche par défaut (à partir d'un get_search_form()appel non modifié ). Ce n'est pas précisément ce que vous avez demandé, mais la recherche incrémentielle est une énorme douleur pour être parfaite. :)

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
la source
0

Vous devez le faire en utilisant Ajax bien sûr, mais ici il y a un problème. Étant donné que WordPress utilise MySQL, vous risquez de surcharger votre serveur de recherche si vous essayez de remplir la recherche avec les vraies requêtes de base de données via Ajax, mais ce que vous pourriez faire est de développer un système où toutes les publications sont enregistrées dans un grand "wp_options" champ et puis quand une recherche est faite, vous interrogez à partir de cela au lieu de faire une vraie recherche. Mais n'oubliez pas que vous devez mettre à jour ce morceau de texte / variable sérialisée à chaque fois que vous créez ou modifiez une publication.

Si vous n'êtes pas disposé à consacrer du temps à développer cette solution, je ne vous recommanderais pas de faire ce genre de "recherche en direct".

Webord
la source
2
Dans un tel cas d'utilisation, l'utilisation des ressources des requêtes MySQL serait complètement insignifiante par rapport au hit de chargement du noyau WP pour les requêtes Ajax.
Rarst
1
Cela dépend de la façon dont vous essayez de faire la demande Ajax, dans ce cas, vous n'avez pas vraiment besoin de tout le noyau WP pour votre réponse, le meilleur scénario serait simplement de charger $ wpdb et de rechercher votre champ. Mais d'accord, en utilisant l'URL principale de WP Ajax, les deux pourraient se transformer en problème, s'ils ne sont pas bien gérés.
Webord
1
Oui, je note simplement que les performances de MySQL ne seraient pas un goulot d'étranglement (à moins que vous n'entriez dans des centaines de milliers de messages et autres). WP core est beaucoup plus lent. Le réseau est également plus lent.
Rarst
Oui, mais faire une sorte de scalling avec des machines WP Core est beaucoup plus facile et plus rapide. Avec les machines MySQL, c'est plus lent et plus difficile. Mais sur une installation normale, je suis d'accord avec vous.
Webord