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'm trying to create a search bar that will show me titles of posts when the user types into the text field.

I'm completely new to this and I really don't know how to go about doing this. What would I do?

Here is the text input html element:

<input type='text' id='searchField' class='pushLeft tabRight hide' onKeyUp="autoSearch('<?php echo esc_js(site_url()); ?>')"/>

And here is the javascript, which I'd like to point out is in a folder called "js" and in that is my javascript file "general.js:"

function autoSearch(link)
{
    $("#searchResults").width($("#searchArea").width());
    if($("#searchField").val() != "")
    {
        $.post(link,{autoSearch:"", value:$("#searchField").val()},function(data){
            $("#searchResults").show();
            $("#searchResults").html(data.everything);
        },"json");
    }
    else
    {
        $("#searchResults").hide();
    }
}

Then in functions.php I have the following section of code:

isset( $_POST['autoSearch'] ) && add_action( 'after_setup_theme', 'wpse_60353_autosearch' );
    function wpse_60353_autosearch()
    {
        global $wpdb;

        $searchQuery = mysql_escape_string($_POST['value']);

        $mypostids = $wpdb->get_col("SELECT ID FROM $wpdb->posts WHERE post_title LIKE '$searchQuery' LIMIT 5");

        $args = array('post__in='.$mypostids);

        $res = new WP_Query($arg);  

        $titles ="";

        while ( $res->have_posts() ) : $res->the_post();
            $titles .= get_the_title().'<br />';
        endwhile;

        echo json_encode(array("everything"=>"hello"));

        wp_reset_postdata();

        exit; // All done, stop WP continuing
    }

I get a POST response saying this:

301 Moved Permanently
share|improve this question
    
Something to read: Very closely related Question A. Something about prepare() and like_escape() in queries. --- Then there're the questions where, how and when you use the code you showed above. Could be that you're too early and $wpdb; isn't yet initialized. –  kaiser Jul 31 '12 at 18:46

1 Answer 1

up vote 2 down vote accepted

Then "autoSearch.php" has this code:

If that's all there is, no wonder you get an error - WP isn't even loaded!

Add this to your functions.php

isset( $_POST['autoSearch'] ) && add_action( 'after_setup_theme', 'wpse_60353_autosearch' );
function wpse_60353_autosearch()
{
    // The autoSearch.php code you posted in your question

    exit; // All done, stop WP continuing
}

Now just use the main URL for your AJAX request. The function will intercept the default WordPress runtime & return your data as expected.

$.post( "<?php echo esc_js( site_url() ) ?>" ...

Using this technique means you'll have access to all of WP inside wpse_60353_autosearch, without having to point to an external file & dirtily loading WP with something like require '../../../wp-load.php (or similar).


Update: Firstly, I would strongly advise to use something like typewatch - using onkeyup will fire a request far too often for what you need; it'll annoy the user not to mention overload the server.

Secondly, I've noticed an error in your query:

$args = array( 'post__in='.$mypostids ); // This concats your IDs array to a string
$args = array( 'post__in' => $mypostids ); // See the difference?

In fact, I would rewrite it to use the initial result - saves querying & should lighten things up:

isset( $_POST['autoSearch'] ) && add_action( 'after_setup_theme', 'wpse_60353_autosearch' );
function wpse_60353_autosearch()
{
    global $wpdb;

    $query = like_escape( $_POST['autoSearch'] );
    $posts = $wpdb->get_results( $wpdb->prepare( "
        SELECT * FROM $wpdb->posts
        WHERE
            post_status = 'publish' AND
            post_title LIKE %s AND
            post_type IN ( 'post', 'page' )
        ORDER BY
            post_date DESC
        LIMIT 5",

        "%$query%"
    ));

    // update_post_caches( &$posts, $post_type, $update_term_cache, $update_meta_cache )
    update_post_caches( $posts, 'post', false, true );

    $titles = array();
    foreach ( $posts as $post )
        $titles[] = get_the_title( $post->ID );

    header( 'Content-Type: application/json; charset=UTF-8' );
    echo json_encode( array( 'everything' => implode( '<br />', $titles ) ) );
    exit;
}

And for your JS:

function autoSearch( link )
{
    var $results = $( "#searchResults" ).width( $( "#searchArea" ).width() ), s = $( "#searchField" ).val();
    if ( s != "" ) {
        $.post( link, { autoSearch: s }, function ( data ) {
            $results.show().html( data.everything );
        }, "json" );
    } else {
        $results.hide();
    }
}

Note that I have tested this code on my own install & can confirm it functions as expected: typing a search term displays a maximum of 5 found titles, otherwise the results div is hidden if no results.

share|improve this answer
    
Thanks for the help, but I'm trying to see if I have this right:$.post("<?php echo esc_js( site_url() ) ?>" + "autoSearch.php",{autoSearch:"yeah", value:$("#searchField").val()},function(data){ $("#searchResults").show(); $("#searchResults").html(data.everything); },"json"); –  Majed Aug 1 '12 at 3:53
    
No no, you don't need to append autoSearch.php, just need the site URL - the PHP code will intercept the default request & echo your data. –  TheDeadMedic Aug 1 '12 at 9:49
    
I did that, but it didn't give me a return. I got two messages. A 200 on a GET request and a 301 on a POST request with a "Permanently Moved" error. –  Majed Aug 1 '12 at 15:20
    
Update your question with the code you're now currently using. –  TheDeadMedic Aug 1 '12 at 15:22
    
Ok. I seriously appreciate this help! –  Majed Aug 1 '12 at 15:23

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.