Jak utworzyć wyszukiwanie autouzupełniania na żywo?

22

Obecnie próbuję utworzyć funkcję wyszukiwania wordpress, która wyświetla wyniki na żywo pod paskiem wyszukiwania. Istnieje przykład na stronie internetowej Banku Światowego (ekrany poniżej). Nie szukam autouzupełniania, które można znaleźć w Google.com, które uzupełnia wpisywane słowa, ale chcę, aby znajdowało rzeczywiste posty w witrynie.

Próbowałem zrobić przeglądanie za pomocą Wordpress Answers i innych podobnych zasobów, ale natknąłem się tylko na wdrożenie wyszukiwania typu Google, które nie jest tym, czego szukam. Każda pomoc lub punkty we właściwym kierunku byłyby bardzo mile widziane.

szukaj przed

szukaj po

mmaximalist
źródło
Co chcesz zrobić, gdy użytkownik kliknie sugestię? Wystarczy wypełnić to pole wyszukiwania?
Rarst
Przenosi Cię do odpowiedniego stanowiska. Użytkownik nadal może pisać i uzyskiwać wyniki wyszukiwania normalnie, tylko sugestie kliknięć przekierowują do postu.
mmaximalist
Mam na myśli szybkie rozwiązanie problemu, ale połączenie bardziej problematycznych ... Zastanowię się.
Rarst

Odpowiedzi:

20

Poniższe informacje wykorzystują autouzupełnianie interfejsu użytkownika jQuery, które jest zawarte w WordPress od 3.3. (Pożyczyłem format od @Rarst : D).

Nadal nie jest to dokładnie to, czego szukasz, ale stanowi dobry punkt wyjścia. W poniższym przykładzie użyto podstawowej stylizacji interfejsu użytkownika jQuery, ale można użyć tej, która jest obecnie opracowywana dla trac i wywołać ją z folderu wtyczki.

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
źródło
12

Ok, to byłby bardzo prosty przykładowy kod, który używa natywnego suggest.jsWP core dla Ajax i wiąże się z domyślną formą wyszukiwania (z niezmodyfikowanego get_search_form()wywołania). Nie jest to dokładnie to, o co prosiłeś, ale wyszukiwanie przyrostowe jest ogromnym bólem, aby stać się doskonałym. :)

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
źródło
0

Musisz to zrobić oczywiście za pomocą Ajax, ale tutaj jest problem. Ponieważ WordPress używa MySQL, możesz przeciążać serwer wyszukiwaniem, jeśli spróbujesz wypełnić wyszukiwanie prawdziwymi zapytaniami do bazy danych przez Ajax, ale możesz stworzyć system, w którym wszystkie posty są zapisywane w jednym dużym „wp_options” pole, a następnie, gdy wyszukiwanie jest zakończone, wyszukujesz z niego zapytanie zamiast prawdziwego wyszukiwania. Pamiętaj jednak, że musisz aktualizować ten fragment tekstu / serializowanej zmiennej za każdym razem, gdy tworzysz lub edytujesz post.

Jeśli nie chcesz poświęcić trochę czasu na opracowanie tego rozwiązania, nie polecam wykonywania tego rodzaju „wyszukiwania na żywo”.

Webord
źródło
2
W takim przypadku użycie zasobów żądań MySQL byłoby zupełnie nieistotne w porównaniu z trafieniem ładowania WP core dla żądań Ajax.
Rarst
1
Zależy od tego, jak próbujesz wykonać żądanie Ajax, w tym przypadku tak naprawdę nie potrzebujesz całego WP do odpowiedzi, najlepszym scenariuszem byłoby załadowanie $ wpdb i poszukiwanie pola. Ale zgodzili się, korzystając z głównego adresu URL Ajax WP, obaj mogą mieć problem, jeśli nie zostaną dobrze rozwiązane.
Webord,
1
Tak, po prostu zauważam, że wydajność MySQL nie byłaby wąskim gardłem (chyba że dostaniesz się do setek tysięcy postów itp.). Rdzeń WP jest znacznie wolniejszy. Sieć jest również wolniejsza.
Rarst
Tak, ale wykonywanie Scallingu za pomocą maszyn WP Core jest znacznie łatwiejsze i szybsze. Z MySQL maszyny są wolniejsze i trudniejsze. Ale przy normalnej instalacji zgadzam się z tobą.
Webord