WordPress搜索AJAX+同位素+无限滚动

时间:2022-02-22 作者:jkcoding

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

1 个回复
SO网友:jkcoding

我能弄明白。。。只要jQuery和AJAX还活着并被WordPress使用(我知道使用WordPress REST API可能是最好的,但是……这很有效)!

GET STARTED

我确实需要编辑searchform。php,函数。php,搜索。php和自定义搜索。js。请确保分类法和帖子类型是可查询的(public),并且查询变量设置为true。如果使用CPT UI,可以在此处编辑它们:

http://domain.com/wp-admin/admin.php?page=cptui_manage_taxonomies&action=edit

将“Public Queryable”选项设置为“true”,将“Query Var”设置为“true”。

SEARCHFORM.PHP

如果用户使用后退按钮,我必须关闭搜索和ajax过滤器表单上的自动完成功能,因为历史记录的InfiniteScroll选项默认设置为true。

<form role="search" method="get" class="search-form" action="<?php echo esc_url( home_url( \'/\' ) ); ?>" autocomplete="off">
<select id="drpdwn_search">
    <option value="any" selected>All</option>
    <option value="opone">One</option>
    <option value="optwo">Two</option>
    <option value="opthree">Three</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>
如您所见,如果用户未选择帖子类型,则默认值为“any”post type。

<input type="hidden" name="post_type" value="any" />

SEARCH.PHP

ajax过滤器表单字段应该都是HTML所必需的。

Ajax Filter - Form Tag

我在表单标签上添加了autocomplete属性,并将其设置为off。

Ajax Filter Form - Taxonomies

仅供参考:我的分类法是使用CPT UI创建的自定义帖子类型类别-正如您在整个过程中所看到的,我没有使用WP核心类别。

在ajax过滤器表单中,我编辑了分类法过滤器,以在else语句中将post类型设置为any时获取所有术语。

Ajax Filter Form - Search Field

然后,我将搜索字段输入类型设置为隐藏,以便他们只能从searchform中的表单中筛选搜索项。php。我计划在标题(header.php)中显示搜索表单,这样它就可以随处可见,所以。。。ajax过滤器表单中的搜索字段可以保持隐藏状态,除非您想在搜索结果页面上使用它进行过滤)。

Default Search Results Query (Not in AJAX Callback Duh..)

对于非ajax过滤的结果,我使用默认的搜索查询循环($wp\\u query)我们不需要使用自定义搜索查询

Ajax Filter Search Results Query - Container DIV

我希望ajax调用有自己的容器,所以我添加了一个div,它只具有与默认搜索查询容器相同的引导类,但具有id(#ajax\\u container)。

<section class="row">
    <div id="secondary" class="content-area col-sm-12 col-md-2">
<?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" autocomplete="off">
<input type="hidden" 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 (\'font\' == $param) {
    if ($terms = get_terms(array(\'taxonomy\' => \'font_cat\', \'hide_empty\' => false, \'orderby\' => \'name\'))):
        // if categories exist, display the dropdown
        echo \'<select name="categoryfilter" class="form-select" aria-label="One categories"><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 (\'snipp\' == $param) {
    if ($terms = get_terms(array(\'taxonomy\' => \'snipp_cat\', \'hide_empty\' => false, \'orderby\' => \'name\'))):
        // if categories exist, display the dropdown
        echo \'<select name="categoryfilter" class="form-select" aria-label="Two categories"><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 (\'post\' == $param) {
    if ($terms = get_terms(array(\'taxonomy\' => \'blog_cat\', \'hide_empty\' => false, \'orderby\' => \'name\'))):
        // if categories exist, display the dropdown
        echo \'<select name="categoryfilter" class="form-select" aria-label="Three categories"><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 {
    $term_args = array(\'taxonomy\' => array(\'font_cat\', \'snipp_cat\', \'blog_cat\'), \'hide_empty\' => false, \'fields\' => \'all\', \'count\' => true,);
    $term_query = new WP_Term_Query($term_args);
    $term_taxs = $term_args["taxonomy"];
    echo \'<select name="categoryfilter" class="form-select" aria-label="All categories" required><option value="">Select category...</option>\';
    foreach ($term_taxs as $term_tax):
        if ($term_tax === \'font_cat\'):
            echo \'<option value="" disabled>Font Categories</option>\';
            foreach ($term_query->terms as $term):
                if ($term->taxonomy == \'font_cat\'):
                    echo \'<option value="\' . $term->term_id . \'">\' . $term->name . \'</option>\';
                endif;
            endforeach;
        endif;
        if ($term_tax === \'snipp_cat\'):
            echo \'<option value="" disabled>Snippet Categories</option>\';
            foreach ($term_query->terms as $term):
                if ($term->taxonomy == \'snipp_cat\'):
                    echo \'<option value="\' . $term->term_id . \'">\' . $term->name . \'</option>\';
                endif;
            endforeach;
        endif;
        if ($term_tax === \'blog_cat\'):
            echo \'<option value="" disabled>Blog Categories</option>\';
            foreach ($term_query->terms as $term):
                if ($term->taxonomy == \'blog_cat\'):
                    echo \'<option value="\' . $term->term_id . \'">\' . $term->name . \'</option>\';
                endif;
            endforeach;
        endif;
    endforeach;
    echo \'</select>\';
}
?>
<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="desc" name="date" value="desc" selected="selected" required />
    <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-10">
        
<?php
global $wp_post_types, $wp_query;
$wp_post_types[\'page\']->exclude_from_search = true;
if (have_posts()):
    while (have_posts()):
        the_post();
        get_template_part(\'template-parts/content\', \'archive\');
    endwhile;
    get_template_part(\'template-parts/pagination\', \'notabs\');
else:
    get_template_part(\'template-parts/content\', \'none\');
endif;
?>
        
        </div><!-- .scroll-content -->
<div id="ajax_container" class="col-sm-12 col-md-10"></div>
</section> <!-- row -->

FUNCTIONS.PHP

AJAX Callback Function - Protocol

由于HTTP和HTTPS对于我的域是灵活的,所以我必须specify the protocol for the ajax URL. 当然,HTTPS将仅在生产中使用,因此如果强制使用HTTPS,则可以将其删除。

AJAX Callback Function - Query Loop

如上所述,由于我决定修改搜索的主查询,所以在分页后我使用了query\\u posts()和wp\\u reset\\u query()。

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;
    $protocol = isset( $_SERVER[\'HTTPS\'] ) ? \'https://\' : \'http://\';
    $args = array(
        \'ajaxurl\' => admin_url( \'admin-ajax.php\', $protocol ),
        \'query\'   => $wp_query->query,
        \'s\' => $_POST[\'s\'],
        \'post_type\' => $_POST[\'post_type\'],
        \'post_status\' => \'publish\',
        \'posts_per_page\' => 6,
        \'orderby\' => \'date\',  
        \'order\' => $_POST[\'date\'], // ASC or DESC
        \'paged\' => $paged
    );
    
    
    // for taxonomies 
    if( isset( $_POST[\'categoryfilter\'] ) ) {
        $args[\'tax_query\'] = array(
            \'relation\' => \'OR\',
            array(
                \'taxonomy\' => \'font_cat\',
                \'field\'    => \'id\',
                \'terms\'    =>  $_POST[\'categoryfilter\'],
            ),
            array(
                \'taxonomy\' => \'snipp_cat\',
                \'field\'    => \'id\',
                \'terms\'    =>  $_POST[\'categoryfilter\'],
            ),
            array(
                \'taxonomy\' => \'blog_cat\',
                \'field\'    => \'id\',
                \'terms\'    => $_POST[\'categoryfilter\'],
            ),
        );
    }

    query_posts( $args );

    if ( have_posts() ) : while ( have_posts() ) : the_post();

            get_template_part( \'template-parts/content\', \'search\' );

        endwhile; 

            get_template_part( \'template-parts/pagination\', \'notabs\' );
            wp_reset_query();

        else :

            get_template_part( \'template-parts/content\', \'none\' ); 
            
        endif;

    
    die();
}

FUNCTIONS.PHP (Continued)

Next Link for Pagination

我需要向下一个分页链接添加一个类,所以我向next_post_link() 函数用于非ajax InfiniteScroll实例。

仅供参考:这对于非ajax InfiniteScroll实例路径选项很重要since I do not want a hard-coded URL.

add_filter(\'next_posts_link_attributes\', \'next_link_class_attribute\');
function next_link_class_attribute() {
  return \'class="next-post-link"\';
}
为了避免搜索字段为空,我添加了此功能,以便在没有输入搜索词的情况下将用户发送到404页面。

//if search is empty to display 404
add_action( \'pre_get_posts\', function ( $q )
{
    if($q->is_search() // Only target the search page
    ) {
        // Get the search terms
        $search_terms = $q->get( \'s\' );

        // Set a 404 if s is empty
        if ( !$search_terms ) {
            add_action( \'wp\', function () use ( $q )
            {
                $q->set_404();
                status_header(404);
                nocache_headers();
            });
        }
    }
});
我还设置404 if there are only one or more invalid query vars. 如果您尚未注册自定义查询变量,我不建议使用此函数。https://gist.github.com/carlodaniele/1ca4110fa06902123349a0651d454057

//set 404 only if one or more invalid query vars (invalid taxonomy names but not only) are in the query
add_action( \'template_redirect\', \'my_page_template_redirect\' );
function my_page_template_redirect() {
  global $wp_query, $wp;
  // this get an array of the query vars in the url
  parse_str( parse_url ( add_query_arg( array() ), PHP_URL_QUERY ), $qv);
  if ( ! empty( $qv ) ) { // if there are some query vars in the url
    $queried = array_keys( $qv ); // get the query vars name
    $valid = $wp->public_query_vars; // this are the valid query vars accepted by WP
    // intersect array to retrieve the queried vars tha are included in the valid vars
    $good = array_intersect($valid, $queried); 
    // if there are no good query vars or if there are at least one not valid var
    if ( empty($good) || count($good) !== count($queried)  ) {
     $wp_query->set_404();
     status_header(404);
     nocache_headers();
    }
  }
}
UPGRADE InfiniteScroll to v4我确实升级到了InfiniteScroll v4 because loadNextPage returns a Promise, 因此,基本上我可以使用then()以防每次加载帖子后都想做些什么Also, because of its backward compatibility with v3.

CUSTOM-SEARCH.JS

AJAX Filter - Submit without Reload

我必须将过滤器按钮绑定到click事件,这样我们就可以应用过滤器,而无需重新加载整个页面。

AJAX Filter - InfiniteScroll and Isotope Sessions

一旦用户单击过滤器上的提交,我会在两个容器上使用InfiniteScroll和同位素销毁方法($scroll\\u container和$ajax\\u container),以防同位素或无限滚动已经存在(destroy session on success to first create new).

FYI: .data(\'inifiniteScroll\') and InfiniteScroll.data( element ) does not work in v3 and v4 so I cannot check if InifinteScroll is initialized before using destroy method so error will show in console.

然后清空AJAX容器(#AJAX\\u container.empty()),以确保每次用户使用AJAX筛选表单进行筛选时都会显示新结果。

AJAX Filter - Isotope通过在插入同位素数据之前将响应(数据)转换为jQuery对象,我能够让同位素处理结果。

let $data = $(data); // store data in jQuery object
$ajax_container.append($data);
$ajax_container.isotope(\'insert\', $data ); 
AJAX Filter - InfiniteScroll我确实找到了通过正确设置路径来修复InfiniteScroll的解决方案-通过控制台记录数据来获得分页查询字符串(console.log(filter.serialize()))

如前所述,现在只有AJAX InfiniteScroll实例使用硬编码路径选项。我试着用public query vars 但是在为帖子类型和分类设置了漂亮的链接(定制slug-rewrites)之后,页面结果出现了问题。

这是通过CPT UI插件完成的:http://domain.com/wp-admin/admin.php?page=cptui_manage_taxonomies&action=edit

我将“Rewrite”设置为“true”,添加了“Custom Rewrite Slug”文本,并将“Rewrite With Front”设置为“true”。

如前所述,我仍然需要手动构建AJAX InfiniteScroll实例的路径URL。

好消息是,可以根据我的设置重写分页。

http://domain.com/[taxonomy 重写slug]/[分类术语]/页/{{{}}/?s=[搜索词]&;orderby=日期(&M);顺序=[asc或desc]

正如您所看到的,AJAX InfiniteScroll实例的路径选项现在设置正确。

jQuery(window).on(\'load\', function () {

    let $scroll_container = jQuery(\'.scroll-content\');
     
    $scroll_container.isotope({
        layoutMode: \'fitRows\',
        itemSelector: \'.scroll-post\'
    }); //isotope

    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 iso = $scroll_container.data(\'isotope\');
    
    if(iso) {
    $scroll_container.infiniteScroll({
        //path: \'page/{{#}}/?s=\' + searchParam.search_term + \'&post_type=\' + post_type_value,
        path: \'.next-post-link\',
        append: \'.scroll-post\',
        button: \'.btn-scroll\',
        outlayer: iso,
        loadOnScroll: false,
        scrollThreshold: 300,
        status: \'.page-load-status\',        
        hideNav: \'.pagination\'
    }); //infinite scroll
    
    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 
} //iso check
    
    /*
     * Filter
     */
    let $ajax_container = jQuery(\'#ajax_container\'); 
    let s_term = jQuery(\'.search-field\').val();
    let s_cat_text = jQuery(".form-select :selected").text(); //not needed for query string
    let s_cat_val = jQuery(".form-select :selected").val(); 
    let s_order = jQuery("input[type=\'radio\'][name=\'date\']:checked").val();
    let s_post_type = jQuery("input[type=\'hidden\'][name=\'post_type\']").val();
    
    
     //ajax call
    jQuery(\'#filter\').submit(function(e) { 
        //jQuery(\'.btn-filter\').on(\'click\', function () {
        e.preventDefault();
        let filter = jQuery(\'#filter\');
        jQuery.ajax({
            url: filter.attr(\'action\'),
            data: filter.serialize(), // form data
            type : filter.attr(\'method\'),
            beforeSend : function(xhr) {
                filter.find(\'.btn-filter\').text(\'Filtering...\');
                console.log(filter.serialize());
            },
            success : function( data ) {
                filter.find(\'.btn-filter\').text(\'Apply filter\');
                
                let iso = $scroll_container.data(\'isotope\');
                let inf = $scroll_container.data(\'infniteScroll\');
                
                //remove initial results infinite scroll and isotope for ajax call
                if(inf) {
                    $scroll_container.infiniteScroll(\'destroy\');
                }
                
                if(iso) {
                    $scroll_container.isotope(\'destroy\');
                }
                
                $scroll_container.remove(); //completely remove initial results


                let iso_ajax = $ajax_container.data(\'isotope\');
                //let inf_ajax = $ajax_container.data(\'infniteScroll\'); //does not work, reported to developer
                //InfiniteScroll.data( element ); Infinite Scroll instance via its element does not work either
                
                //if ajax infinite scroll and isotope exist already remove so reset     
                    $ajax_container.infiniteScroll(\'destroy\');  

                if(iso_ajax) {
                    $ajax_container.isotope(\'destroy\');
                    $ajax_container.empty();
                }
            
                //create "new" isotope instance
                $ajax_container.isotope({
                    layoutMode: \'fitRows\',
                    itemSelector: \'.scroll-post\'
                }); //isotope

                let $data = $(data); // store data in jQuery object
                $ajax_container.append($data);
                $ajax_container.isotope(\'insert\', $data );  

                let isoajax = $ajax_container.data(\'isotope\');          
                
                //create "new" infinite scroll instance
                $ajax_container.infiniteScroll({
                    path: \'/page/{{#}}/?s=\' + s_term + \'&post_type=\' + s_post_type + \'&categoryfilter=\' + s_cat_val + \'&date=\' + s_order,
                    append: \'.scroll-post\',
                    button: \'.btn-scroll\',
                    outlayer: isoajax, 
                    loadOnScroll: false,
                    scrollThreshold: 300,
                    checkLastPage: true,
                    history: false,
                    status: \'.page-load-status\',
                    hideNav: \'.pagination\',
                    debug: true
                }); //infinitescroll 

                    jQuery(\'.btn-scroll\').on(\'click\', function () {
                            console.log(\'click ajax inside\');
                        $ajax_container.on(\'load.infiniteScroll\', function (event) {
                            console.log(\'infinite ajax inside\');
                        $ajax_container.isotope(\'layout\');
                            jQuery(\'.page-load-status\').detach().appendTo(jQuery(\'#ajax_container\'));
                        }); //on load function
                    }); // on click function 
                // reset filter 
                //filter[0].reset();             
            } // success
        }); //ajax call
        //return false; //e.preventDefault is used
    }); //submit function
    
    //Bind click event listener to the submit button
    jQuery(document).on(\'click\', \'button[type="submit"]\', function() {
      jQuery(this).parents(\'form\').submit();
    }); 
}); // window on load
请原谅我的压痕,就这样!

如果您可以优化此代码以使其更好,或者想出一个更好的方法,我们将不胜感激。

相关推荐

WordPress:在Gutenberg插件迁移到lock.json后,在JavaScript中使用多语言的本地化/翻译不再有效

我做了a plugin with existing localization on WordPress.org 免费。我迁移到block。并通过将其与npx @wordpress/create-block todo-list. 我通读了一遍the Block Editor guide on internationalization 但在todo列表示例中,它的工作方式似乎有一些不同。结果是我所有的__ php函数工作并转换所有字符串。但是我的__ JavaScript函数不会在翻译时翻译任何翻译。word