Skip to content

Instantly share code, notes, and snippets.

@stephanieland352
Created October 2, 2018 14:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stephanieland352/142c9704265e6a41ecd395702c8b1fb9 to your computer and use it in GitHub Desktop.
Save stephanieland352/142c9704265e6a41ecd395702c8b1fb9 to your computer and use it in GitHub Desktop.
Woocommerce Ajax Typeahead Search
<!-- search -->
<form class="search" method="get" action="<?php echo get_permalink(get_option('woocommerce_shop_page_id')); ?>" role="search">
<input type="hidden" name="ts" value="true" />
<input class="search-input" type="search" name="s" placeholder="<?php _e( 'Search Our Products', 'html5blank' ); ?>" autocomplete="off" data-ajaxurl="<?php echo admin_url('admin-ajax.php'); ?>">
<div class="search-results"></div>
<button class="search-submit" type="submit" role="button"><i class="fa fa-search" aria-hidden="true"></i></button>
</form>
function html5blank_header_scripts()
{
wp_register_script( 'typeahead', get_template_directory_uri() . '/js/lib/typeahead/jquery.typeahead.min.js', array( 'jquery' ), '2.6.1', true );
wp_enqueue_script( 'typeahead' );
}
add_action('init', 'html5blank_header_scripts');
//fancy search
add_action( 'wp_ajax_typeahead', 'get_typeahead_results' );
add_action( 'wp_ajax_nopriv_typeahead', 'get_typeahead_results' );
/**
* Action for handling cached Typeahead AJAX requests
*/
function get_typeahead_results() {
if ( ! DOING_AJAX ) {
die;
}
$results = rebuild_typeahead_cache();
echo $results;
die();
}
/**
* Rebuild typeahead caches for categories / taxonomy search terms
*
* @return array|mixed|string|void
*/
function rebuild_typeahead_cache(){
$results = get_transient( 'typeahead_cache' );
if ( $results ) { // Return if cached
return $results;
}
$results = array();
$types = array(
'pa_brand',
'pa_hair-type',
'pa_skin-type',
'product'
);
foreach ( $types as $type ) {
if ( $type == 'product' ) {
$query = new WP_Query( array(
'nopaging' => true,
'post_type' => 'product',
'meta_query' => array(
array(
'key' => '_visibility',
'value' => 'visible'
)
)
) );
foreach ( $query->get_posts() as $product ) {
$meta = array();
$terms = wp_get_post_terms( $product->ID, 'pa_brand' );
foreach ( $terms as $term ) {
$meta[] = $term->name;
}
$results[] = get_group_array( $product->post_title, get_the_permalink( $product->ID ), 'Product', $product->ID, get_the_post_thumbnail_url( $product->ID, 'thumbnail' ), implode( ',', $meta ) );
}
} else {
$taxonomy = get_taxonomy( $type );
$terms = get_terms( array(
'taxonomy' => $type
) );
foreach ( $terms as $term ) {
$results[] = get_group_array( $term->name, get_term_link($term, $term->taxonomy), $taxonomy->label, $term->term_id );
}
}
}
$results = json_encode($results);
set_transient( 'typeahead_cache', $results, 60 * 60 * 24 * 7 );
return $results;
}
/**
* Assemble search query URL for products page - useful if we link to this search term in other locations
*
* @param $term
*
* @return string
*/
function get_taxonomy_search_url_skin( $term, $taxonomy ) {
return add_query_arg( 'filters', $term->taxonomy.'['.$term->term_id.']', get_permalink( get_option('woocommerce_shop_page_id') ) );
}
/**
* Format passed arguments into proper JSON array for Typeahead
*
* @param $name
* @param $href
* @param $type
* @param $image_url
* @param $meta
*
* @return array
*/
function get_group_array($name, $href, $type, $id, $image_url = FALSE, $meta = FALSE){
$group = array(
'name' => $name,
'href' => $href,
'type' => $type,
'id' => $id
);
if ( $image_url !== FALSE ) {
$group['image_url'] = $image_url;
}
if ( $meta !== false ) {
$group['meta'] = $meta;
}
return $group;
}
add_action('admin_notices',function(){
if(user_can(get_current_user_id(),'manage_options') && isset($_GET['action']) && $_GET['action'] == 'recreate_caches'){
delete_transient( 'typeahead_cache' );
rebuild_typeahead_cache();
?>
<div class="updated">
<p><?php _e( 'Search caches rebuilt.', 'my-text-domain' ); ?></p>
</div>
<?php
}
});
// Add recreate cache menu for manual cache creation
add_action('admin_bar_menu',function($menu){
/* @var $menu WP_Admin_Bar */
$menu->add_node(array(
'id'=>'typeahead-caches',
'parent'=>'site-name',
'recreate-typeahead-caches',
'title'=>'Recreate Caches',
'href'=>get_admin_url().'?action=recreate_caches'
));
});
(function ($, root, undefined) {
$(function () {
// Search Bar
setupTypeahead();
});
function setupTypeahead(){
var searchbox = $('.search-input');
$.ajax(searchbox.data('ajaxurl'), {
method: 'GET',
dataType: 'json',
cache: true,
data: {
action: 'typeahead'
},
success: function(data){
searchbox.typeahead({
minLength: 1,
group: 'type',
maxItem: 20,
maxItemPerGroup: 10,
emptyTemplate: function(query){
return '<div class="typeahead__display"><div class="typeahead__info">No results Found for "'+query+'"</div></div>';
},
compress: true,
highlight: 'any',
resultContainer: '.search-results',
display: ['name', 'meta'],
callback: {
onClick: function(event){
return false;
},
onNavigateBefore: function (node, query, event) {
if (~[38,40].indexOf(event.keyCode)) {
event.preventInputChange = true;
}
}
},
template: function (query, item) {
var template = "";
if (item.image_url != undefined) {
template += '<div class="typeahead__display typeahead__display--has-image"><img class="typeahead__image" src="{{image_url}}"/>';
} else {
template += '<div class="typeahead__display">';
}
template += '<div class="typeahead__info">{{name}}';
template += '</div></div>';
return template;
},
href: function(item){
return item.href;
},
source: data
});
}
});
}
function escapeRegExp(str) {
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
}
})(jQuery, this);
.header-search {
float:right;
margin-top:10px;
position:relative;
width:50%;
z-index: 400;
.search {
input[type="submit"], input[type="search"], button {
background: $primaryLight;
border:1px solid $primaryLight;
padding:5px;
}
&-input {
width: 80%;
float:left;
&:focus + .search-results {
display: block;
}
}
.search-submit, input[type="submit"], button {
float:right;
width:16%;
}
&-results {
display:none;
position: absolute;
z-index: 500;
top:100%;
right:0;
width: 100%;
background: $white;
@include boxShadow(0 0 5px rgba(black, .5));
overflow: hidden;
overflow-y: scroll;
max-height: 400px;
&:hover {
display:block;
}
ul {
@include ulReset;
}
.typeahead {
&__list {
padding: $fieldPadding;
}
&__group {
color: $primary;
font-style: italic;
border-bottom: 1px solid darken($white, 14);
}
&__item {
@include clear;
cursor: pointer;
margin: $fieldPadding 0;
&:hover, &.active {
background: darken($white, 12);
}
}
&__display--has-image {
$imageSize: 50px;
.typeahead__image {
float: left;
width: $imageSize;
height: $imageSize;
margin-right: $fieldPadding;
}
.typeahead__info {
position: absolute;
width: 100%;
padding: 0 20px 0 ($imageSize + $fieldPadding);
&__meta {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment