An intercooler.js powered search

A simple WordPress search using wp-routes and intercooler.js.

The requirements

I’m building on two required WordPress plugins.
The first one is wp-routes to have an easier route registration and handling in WordPress.
The second one is wp-intercooler to be able to use the intercooler.js JavaScript library on the page.

A template tag

I will output a search form on the page using a template tag and some parameters.

function mytheme_search(array $post_types = array('post','page')){
    //the form markup
    ?>
    <form role="search" method="get" class="search-form" ic-src="/search" ic-target="#content">
        <label>
            <span class="screen-reader-text"><?php echo _x( 'Search for:', 'label') ?></span>
            <input type="search" class="search-field" placeholder="<?php echo esc_attr_x( 'Search …', 'placeholder') ?>" value="<?php echo get_search_query() ?>" name="s" title="<?php echo esc_attr_x( 'Search for:', 'label') ?>" />
        </label>
        <input type="submit" class="search-submit" value="<?php echo esc_attr_x( 'Search', 'submit button' ) ?>" />
        <?php wp_nonce_field('mytheme-search', 'auth') ?>
        <?php foreach ($post_types as $post_type): ?>
            <input type="hidden" name="post_type[]" value="<?php echo $post_type ?>">
        <?php endforeach ?>
    </form>
    <?php
}

The form has no action attribute as intercooler.js is replacing the usual request flow with an AJAX based one.
I’m telling intercooler.js to send GET requests to the /search address using the ic-src attribute and that it will have to replace the content of the div#content element with whatever HTML it gets back using the ic-target attribute.

A loop rendering function

In my theme I will have a function responsible for the loop rendering, taken straight from the codex exmaple, that will render both the initial state and the response to later search queries

// file functions.php

function my_theme_the_loop(){
 if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>

    <div class="<?php post_class() ?>">

    <h2><a href="<?php the_permalink(); ?>" rel="bookmark" title="Permanent Link to <?php the_title_attribute(); ?>"><?php the_title(); ?></a></h2>

    <small><?php the_time('F jS, Y'); ?> by <?php the_author_posts_link(); ?></small>

    <div class="entry">
        <?php the_content(); ?>
    </div>

    <p class="postmetadata"><?php _e( 'Posted in' ); ?> <?php the_category( ', ' ); ?></p>
    </div> <!-- closes the first div box -->

 <?php endwhile; else : ?>

    <p><?php _e( 'Sorry, no posts matched your criteria.' ); ?></p>

 <?php endif;
}

and will be used, as an example, in the main index.php theme file

// file index.php

get_header();

<div id="#content">
    <?php mytheme_search() ?>
    <?php my_theme_the_loop() ?>
</div>


get_footer();

Of note here is that I’m rendering the search and the content area inside a div marked with the content id: this is the part that intercooler.js will replace on request.

Search route

Leveraging wp-routes I’m registering the /search route mentioned above in the theme functions.php file.

// functions.php file

add_action('wp-routes/register_routes', function (){
    respond('GET', '/search', function(){

        // verify the nonce
        if(!wp_verify_nonce($_GET['auth'], 'my_theme-search')){
            // bail
            return;
        }

        // default the post types
        if(empty($_GET['post_type'])){
            $_GET['post_type'] = array('post', 'page');
        }

        $args = array(
            'post_type' => $_GET['post_type'];
        );

        // maybe search args
        if(!empty($_GET['s'])){
            $args['s'] = $_GET['s'];
        }

        query_posts($args);

        my_theme_the_loop();
    });
});

The intercooler.js library expects some valid HTML; I’m using the same function I’ve used in the index to render the loop to render the search results and echo them.
The wp-routes plugin will buffer that output to return it as the the request result.
Whether there are posts matching the search or not a valid loop HTML will be placed by intercooler in the content part of the page.
The same principle can be applied to almost any interaction and the upcoming version will make interaction with WordPress a breeze.

I appreciate your input