Custom Ajax Search filter for WordPress Search
我想给出一个完整的分解,以便您可以轻松地分析问题,并发现问题不在其他地方,而是JavaScript。如果您不是新手,请滚动到javaScript自定义搜索。JS部分。
I found an article on how to add ajax search filters.
searchform.php
(标准搜索表单)
标准搜索表单
在筛选之前,我编辑了搜索表单,以便用户可以根据帖子类型(opone、optwo、opthree)进行搜索。
<form role="search" method="get" class="search-form" action="<?php echo esc_url( home_url( \'/\' ) ); ?>">
<select id="drpdwn_search">
<option value="any" selected>Choose Type</option>
<option value="opone">Option 1</option>
<option value="optwo">Option 2</option>
<option value="opthree">Option 3</option>
</select>
<input type="search" class="search-field form-control" name="s" placeholder="Search" value="<?php echo esc_attr( get_search_query() ); ?>" title="<?php _ex( \'Search for:\', \'label\', \'wp-bootstrap-starter\' ); ?>">
<input type="hidden" name="post_type" value="any" />
<input type="submit" class="search-submit btn btn-default" value="<?php echo esc_attr_x( \'Search\', \'submit button\', \'wp-bootstrap-starter\' ); ?>">
</form>
该网站在显示搜索结果并使用InfiniteScroll分页的地方工作正常,但我希望能够过滤搜索结果,所以我尝试创建一个ajax搜索过滤表单。
search.php
(AJAX筛选表单/搜索结果模板)
忽视$actual_link
- 因为我使用的是没有SSL的临时服务器$actual_link
变量支持HTTP和HTTPS,但如果使用该变量,将在生产中更改。
Query Moved
我根据实现ajax过滤器的说明将查询移动到一个函数中,这样它就不再处于搜索中了。php。
Ajax Filter Form
对于AJAX过滤器表单,我使用
get_search_query() 在URL中查询字符串的搜索字段输入和发布类型(opone、optwo、opthree)中的函数(
http://somedomain.com/?s={SEARCH 术语}&;post\\u type={post type})和
stored it as a variable ($param). 根据所选的帖子类型,只有其
custom taxonomy "categories" (\'opone\\u cat\',\'optwo\\u cat\',\'opthree\\u cat\')将是AJAX过滤器表单中的一个选项。然后在AJAX过滤器表单中创建单选按钮,以便用户可以升序或降序显示结果。
Ajax搜索筛选器表单和响应div(.scroll-content
) 在搜索结果模板(search.php)中:
<?php
$actual_link = (isset($_SERVER[\'HTTPS\']) && $_SERVER[\'HTTPS\'] === \'on\' ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
$param = filter_input(INPUT_GET, \'post_type\', FILTER_SANITIZE_URL);
?>
<form action="<?php echo site_url() ?>/wp-admin/admin-ajax.php" method="POST" id="filter">
<input type="search" class="search-field form-control" name="s" placeholder="Search" value="<?php echo esc_attr( get_search_query() ); ?>" title="<?php _ex( \'Search for:\', \'label\', \'wp-bootstrap-starter\' ); ?>">
<input type="hidden" class="form-control" name="post_type" value="<?php echo $param; ?>" />
<?php
if(\'opone\' == $param) {
if( $terms = get_terms( array(
\'taxonomy\' => \'opone_cat\',
\'orderby\' => \'name\'
) ) ) :
// if categories exist, display the dropdown
echo \'<select name="categoryfilter" class="form-select" aria-label="Default select example"><option value="">Select category...</option>\';
foreach ( $terms as $term ) :
echo \'<option value="\' . $term->term_id . \'">\' . $term->name . \'</option>\'; // ID of the category as an option value
endforeach;
echo \'</select>\';
endif;
} else if(\'optwo\' == $param) {
if( $terms = get_terms( array(
\'taxonomy\' => \'optwo_cat\',
\'orderby\' => \'name\'
) ) ) :
// if categories exist, display the dropdown
echo \'<select name="categoryfilter" class="form-select" aria-label="Default select example"><option value="">Select category...</option>\';
foreach ( $terms as $term ) :
echo \'<option value="\' . $term->term_id . \'">\' . $term->name . \'</option>\'; // ID of the category as an option value
endforeach;
echo \'</select>\';
endif;
} else if(\'opthree\' == $param) {
if( $terms = get_terms( array(
\'taxonomy\' => \'opthree_cat\',
\'orderby\' => \'name\'
) ) ) :
// if categories exist, display the dropdown
echo \'<select name="categoryfilter" class="form-select" aria-label="Default select example"><option value="">Select category...</option>\';
foreach ( $terms as $term ) :
echo \'<option value="\' . $term->term_id . \'">\' . $term->name . \'</option>\'; // ID of the category as an option value
endforeach;
echo \'</select>\';
endif;
} else {
if( $terms = get_terms( array(
\'taxonomy\' => array(\'opone_cat\',\'optwo_cat\',\'opthree_cat\'),
\'orderby\' => \'date\'
) ) ) :
// if categories exist, display the dropdown
echo \'<select name="categoryfilter" class="form-select" aria-label="Default select example"><option value="">Select category...</option>\';
foreach ( $terms as $term ) :
echo \'<option value="\' . $term->term_id . \'">\' . $term->name . \'</option>\'; // ID of the category as an option value
endforeach;
echo \'</select>\';
endif;
}
?>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" id="asc" name="date" value="ASC" />
<label class="form-check-label" for="asc">Date: Ascending</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" id="dsc" name="date" value="DESC" selected="selected" />
<label class="form-check-label" for="dsc">Date: Descending</label>
</div>
<button class="btn btn-primary btn-filter btn-lg">Apply filter</button>
<input type="hidden" name="action" value="myfilter">
</form>
</div>
<div class="scroll-content col-sm-12 col-md-9"></div>
如果您在搜索中查看上面的ajax搜索过滤器表单。php(搜索结果模板),我们有一个值为myfilter的隐藏操作输入。
<input type="hidden" name="action" value="myfilter">
functions.php
myfilter
- 正在激发的AJAX操作回调的名称。
在实现Ajax搜索过滤器的说明中,我们将把查询放在一个函数中,并添加这些Ajax操作挂钩来处理请求。一个挂钩用于登录(wp_ajax_myfilter
) 用户和其他未登录用户(wp_ajax_nopriv_myfilter
) 用户。
add_action(\'wp_ajax_myfilter\', \'search_filter_function\');
add_action(\'wp_ajax_nopriv_myfilter\', \'search_filter_function\');
下面的函数具有搜索查询循环。从ajax过滤器表单中,我们可以获得搜索词
$_POST[\'s\']
, 岗位类型
$_POST[\'post_type\']
, 日期
$_POST[\'date\']
, 和后类型分类法
$_POST[\'categoryfilter\']
作为搜索查询循环的参数。
其他参数($args)包括standard paging variable 要用于分页参数(分页),请设置post_status
确保结果中只包含已发布的帖子,而posts\\u per\\u page则每页仅显示六篇帖子。
如你所见,我正在使用get_template_part()
添加内容(帖子)和分页。
add_action(\'wp_ajax_myfilter\', \'search_filter_function\');
add_action(\'wp_ajax_nopriv_myfilter\', \'search_filter_function\');
function search_filter_function(){
global $wp_post_types, $wp_query;
$wp_post_types[\'page\']->exclude_from_search = true;
$paged = ( get_query_var( \'paged\' ) ) ? get_query_var( \'paged\' ) : 1;
$args = array(
\'s\' => $_POST[\'s\'],
\'post_type\' => $_POST[\'post_type\'],
\'post_status\' => \'publish\',
\'posts_per_page\' => 6,
\'orderby\' => \'date\', // we will sort posts by date
\'order\' => $_POST[\'date\'], // ASC or DESC
\'paged\' => $paged
);
// for taxonomies / categories
if( isset( $_POST[\'categoryfilter\'] ) )
$args[\'tax_query\'] = array(
\'relation\' => \'OR\',
array(
\'taxonomy\' => \'opone\',
\'field\' => \'id\',
\'terms\' => $_POST[\'categoryfilter\'],
),
array(
\'taxonomy\' => \'optwo\',
\'field\' => \'id\',
\'terms\' => $_POST[\'categoryfilter\'],
),
array(
\'taxonomy\' => \'opthree\',
\'field\' => \'id\',
\'terms\' => $_POST[\'categoryfilter\'],
),
);
$search = new WP_Query( $args );
if ( $search->have_posts() ) : while ( $search->have_posts() ) : $search->the_post();
get_template_part( \'template-parts/content\', \'search\' );
endwhile;
get_template_part( \'template-parts/pagination\', \'notabs\' );
else :
get_template_part( \'template-parts/content\', \'none\' );
endif;
die();
}
/TEMPLATE-PARTS/CONTENT-SEARCH.PHP
模板部分在添加ajax过滤器之前就已经工作了,如您所见,我知道最好不要向这些特定文件添加任何自定义脚本。
我还排除了page
职位类型。
以下是内容模板:
<article id="post-<?php the_ID(); ?>" <?php post_class(\'scroll-post\'); ?> data-category="<?php echo get_post_type(); ?>">
<div class="post-thumbnail">
<?php the_post_thumbnail(); ?>
</div>
<header class="entry-header">
<?php
the_title( \'<h2 class="entry-title"><a href="\' . esc_url( get_permalink() ) . \'" rel="bookmark">\', \'</a></h2>\' );
?>
<div class="entry-meta">
<?php wp_bootstrap_starter_posted_on(); ?>
</div><!-- .entry-meta -->
</header><!-- .entry-header -->
<!-- <div class="entry-content">excerpt</div> -->
<footer class="entry-footer">
<?php wp_bootstrap_starter_entry_footer(); ?>
</footer><!-- .entry-footer -->
</article><!-- #post-## -->
/TEMPLATE-PARTS/PAGINATION-NOTABS.PHP
以下是分页模板:
<?php if(wp_script_is( \'infinite\', \'enqueued\' )) : ?>
<div class="page-load-status">
<div class="loader-ellips infinite-scroll-request">
<span class="loader-ellips__dot"></span>
<span class="loader-ellips__dot"></span>
<span class="loader-ellips__dot"></span>
<span class="loader-ellips__dot"></span>
</div>
<p class="infinite-scroll-last">End of content</p>
<p class="infinite-scroll-error">No more pages to load</p>
</div>
<p>
<button class="btn btn-primary btn-scroll btn-lg">View more</button>
</p>
<div id="nav-below infinite" class="pagination">
<div class="next-post"><?php next_posts_link() ?></div>
</div>
<?php endif; ?>
FUNCTIONS.PHP
(JavaScript)
我已经把同位素脚本和它的布局排好了队。还添加了InfiniteScroll脚本并注册/本地化了自定义javaScript文件(custom-search.js
) so I can pass a PHP variable ($search_param
) with the search term since it will be needed in the custom-search.js
file.
Versions:
<同位素封装v3.0.6版无限卷轴封装v3.0.6版
wp_enqueue_script(\'isotope\', get_template_directory_uri() . \'/inc/assets/js/isotope/isotope.pkgd.min.js\', array(\'jquery\'), \'\', false);
wp_enqueue_script(\'fitrows\', get_template_directory_uri() . \'/inc/assets/js/isotope/layout-modes/fit-rows.js\', array(\'isotope\'), \'\', false);
if( is_search() ) {
wp_register_script( \'custom-search\', get_template_directory_uri() . \'/inc/assets/js/isotope/archive-search.js\', array(\'infinite\'), \'\', true );
$search_query = get_search_query();
$search_param = array(\'search_term\' => $search_query);
wp_enqueue_script(\'infinite\', get_template_directory_uri() . \'/inc/assets/js/isotope/infinitescroll.pkgd.min.js\', array(\'jquery\'), \'\', false);
wp_enqueue_script(\'custom-search\', get_template_directory_uri() . \'/inc/assets/js/isotope/custom-search.js\', array(\'infinite\'), \'\', true);
wp_localize_script( \'custom-search\', \'searchParam\', $search_param );
}
CUSTOM-SEARCH.JS
(JavaScript)
Great news! 过滤器工作正常,但。。。
关键问题-Isotope and InfiniteScroll does not work on the filtered posts and posts do not show without the filter being applied.
同位素和InfiniteScroll在搜索结果模板中添加AJAX过滤器表单后停止工作(search.php
) 在将查询移动到函数之后(functions.php
). 我从说明中复制了Ajax调用,并在之前工作的InfiniteScroll和同位素上添加了custom-search.js
.
**据我所知,我需要应用同位素fitRows布局appending posts. 我认为用于分页的InfiniteScroll是一个问题,因为它只在这里根据URL查询字符串中的post类型进行初始化。
我还需要在默认情况下显示初始搜索结果(在应用过滤器之前),并在显示过滤后的帖子之前隐藏(淡出)初始搜索结果**
这就是我需要帮助的地方。
jQuery(window).on(\'load\', function () {
jQuery(\'#filter\').submit(function () {
var filter = jQuery(\'#filter\');
jQuery.ajax({
url: filter.attr(\'action\'),
data: filter.serialize(),
type: filter.attr(\'method\'), // POST
beforeSend: function (xhr) {
filter.find(\'.btn-filter\').text(\'Processing...\');
},
success: function (data) {
filter.find(\'.btn-filter\').text(\'Apply filter\');
jQuery(\'.scroll-content\').html(data); // insert data
} //success
}); // jQuery ajax
return false;
}); //submit function
let currentLocation = window.location.href;
const ptParams = new Proxy(new URLSearchParams(window.location.search), {get: (searchParams, prop) => searchParams.get(prop),});
let post_type_value = ptParams.post_type;
let $scroll_container = jQuery(\'.scroll-content\');
let fhsFit = $scroll_container.data(\'isotope\');
$scroll_container.isotope({
layoutMode: \'fitRows\',
itemSelector: \'.scroll-post\'
}); //isotope
if ( post_type_value === \'opone\' || post_type_value === \'optwo\' || post_type_value === \'opthree\' ) {
$scroll_container.infiniteScroll({
path: \'page/{{#}}/?s=\' + searchParam.search_term + \'&post_type=\' + post_type_value,
append: \'.scroll-post\',
button: \'.btn-scroll\',
outlayer: fhsFit,
loadOnScroll: false,
scrollThreshold: 300,
status: \'.page-load-status\',
hideNav: \'.pagination\'
}); //infinite scroll
} else {
$scroll_container.infiniteScroll({
path: \'page/{{#}}/?s=\' + searchParam.search_term + \'&post_type=any\',
append: \'.scroll-post\',
button: \'.btn-scroll\',
outlayer: fhsFit,
loadOnScroll: false,
scrollThreshold: 300,
status: \'.page-load-status\',
hideNav: \'.pagination\'
}); //infinite scroll
} //if statement
jQuery(\'.btn-scroll\').on(\'click\', function () {
$scroll_container.on(\'load.infiniteScroll\', function (event) {
$scroll_container.isotope(\'layout\');
jQuery(\'.page-load-status\').detach().appendTo(jQuery(\'.scroll-content\'));
}); //on load function
}); // on click function
}); // window on load