简体   繁体   English

更改内容 <div> 来自“按类别排序”菜单,没有页面加载

[英]Change content inside <div> from “sort posts by category” menu without page load

My first post here on this website and I am seeking some guidance for my first custom wordpress theme. 我在这个网站上的第一篇文章,我正在为我的第一个自定义wordpress主题寻求一些指导。 I am extremely new to jQuery/AJAX and it hurts my brain at this moment as this entire process has been one learning curve after the next. 我对jQuery / AJAX非常陌生,此时它对我的大脑造成了伤害,因为整个过程在下一个过程之后就是一个学习曲线。 So please forgive my inability to see between the lines and understand what is or could be already there. 所以请原谅我无法在线条之间看到并理解已经或可能已经存在的内容。 There are some results on this subject when I search however I am unable to translate these examples into working results for my situation... 当我搜索时,这个主题有一些结果但是我无法将这些例子转化为我的情况的工作结果......

I wish to sort my displayed posts by category on the "News" section...There is a submenu in the <div id="#container"> ... my intent is to have the sub menu links change the content specifically in my <div id="contentbox-news"> ... 我希望按类别在“新闻”部分对我显示的帖子进行排序... <div id="#container">中有一个子菜单...我的意图是让子菜单链接专门更改内容我的<div id="contentbox-news"> ...

ie "latest news" , "recent build projects", "press release announcments" etc... 即“最新消息”,“近期建设项目”,“新闻发布公告”等......

Here is some code from "page-news.php" and original link Cars & Coffee HFX 这是来自“page-news.php”和原始链接Cars&Coffee HFX的一些代码

<div id="news_submenu_container"><!-- begin submenu placement -->
            <ul id="news_submenu">
              <li>VIEW</li>
              <li><a href="#" onClick="get_posts_all();">ALL</a></li>
              <li><a href="#" onClick="get_posts_news();">NEWS</a></li>
              <li><a href="#" onClick="get_posts_builds();">BUILDS</a></li>
              <li><a href="#" onClick="get_posts_pr();">PR</a></li>
            </ul>
        </div><!-- end submenu placement -->

        <script>
            function get_posts_all() {
                var posts_all_var = '<?php echo "Insert Wordpress Loop here identified by Category-ID" ?>';
            document.getElementById("contentbox-news").innerHTML = posts_all_var;
            return false;
            }

            function get_posts_news() {
                var posts_news_var = '<?php echo "Huh?" ?>';
            document.getElementById("contentbox-news").innerHTML = posts_news_var;
            return false;
            }

            function get_posts_builds() {
                var posts_builds_var = '<?php echo "Cant get loop to work" ?>';
            document.getElementById("contentbox-news").innerHTML = posts_builds_var;
            return false;
            }

            function get_posts_pr() {
                var posts_pr_var = '<?php echo "DAMNIT!" ?>';
            document.getElementById("contentbox-news").innerHTML = posts_pr_var;
            return false;
            }
        </script>

I am understanding now that JavaScript and PHP do not work together in the way I thought... Apparently I need to use a method through AJAX... I found this article on PHP AJAX and MySQL however it is too advanced for me, I'm having trouble understanding it and creating a working example for myself... 我现在理解JavaScript和PHP不能以我想的方式一起工作......显然我需要通过AJAX使用一种方法...我在PHP AJAX和MySQL上找到了这篇文章但是它对我来说太先进了,我我无法理解它并为自己创造一个有效的例子......

But now, since yesturday I have made new code that gets me this far, I can PHP echo...thats about it. 但是现在,从星期六开始,我已经制作了新的代码,让我这么远,我可以用PHP回应......就此而言。

            function get_posts_builds() {
                var posts_builds_var = '<?php query_posts('cat=6'); 
                                              while (have_posts()):
                                              the_post(); 
                                              the_content(); 
                                              endwhile; ?>';
            document.getElementById("contentbox-news").innerHTML = posts_builds_var;
            return false;
            }

Once I replace the PHP echo with this PHP wordpress loop, it doesn't seem to do the trick for me and breaks. 一旦我用这个PHP wordpress循环替换PHP回声,它似乎没有为我做的技巧和休息。

You indeed need to use AJAX to achieve this. 你确实需要使用AJAX来实现这一目标。 Wordpress have its own way to handle ajax request that you can use for this by going through few steps detailed below. Wordpress有自己的方式处理ajax请求 ,您可以通过以下几个步骤来执行此操作。 I will try to show some WP best practices on this subject - so as there could be faster/easier/dirtier way to achieve this (probably even through a plugin), this will make a good introduction for Wordpress theme/plugin development for you. 我将尝试在这个主题上展示一些WP最佳实践 - 因为可能有更快/更容易/更脏的方式来实现这一点(可能甚至通过插件),这将为您提供Wordpress主题/插件开发的良好介绍。 Feel free to follow the docs links to understand better how this works. 请随意关注文档链接,以更好地了解其工作原理。


1. Building your categories menu 1.构建类别菜单

In your code sample the menu is static, though you should better use a dynamic menu. 在您的代码示例中,菜单是静态的,但您最好使用动态菜单。 One solution could be to use get_the_category_list , but it doesn't allow you to have full control on category links. 一种解决方案可能是使用get_the_category_list ,但它不允许您完全控制类别链接。 I would suggest to define a new navigation menu like this (the following code go into your theme functions.php ): 我建议像这样定义一个新的导航菜单 (以下代码进入你的主题functions.php ):

add_action('after_setup_theme', 'add_categories_menu');
function add_categories_menu() {
  register_nav_menu('categories_menu', __('Categories Menu', 'your-theme-slug'));
}

Then in your template, replace your static menu with the following in order to display your brand new menu: 然后在模板中,使用以下内容替换静态菜单,以显示全新菜单:

<?php wp_nav_menu(array('theme_location' => 'categories_menu')); ?>

Now to add the categories to your menu, log into your Wordpress administration, go into 现在要将类别添加到菜单中,登录到Wordpress管理,进入
Appearance > Menus , create a new menu, select the theme location "Categories Menu" for it, and add the categories to it. 外观 > 菜单 ,创建一个新菜单,为其选择主题位置“类别菜单”,并为其添加类别。

Last step for this, we'll add a filter in order to add onclick attribute on the menu links that will send the category slug to a js function called showPostsFromCategory() that we'll define later. 最后一步,我们将添加一个过滤器 ,以便在菜单链接上添加onclick属性,将类别slug发送到我们稍后定义的名为showPostsFromCategory()的js函数。

This go in your functions.php : 这进入你的functions.php

function add_onclick_attr_categories_menu($atts, $item, $args) {
    if($args->theme_location == 'categories_menu' && $item->object == 'category') {
        $category = get_category($item->object_id);
        if($category !== null) {
            $atts['onClick'] = 'showPostsFromCategory("' . $item->slug . '")';
        }
    }
    return $atts;
}
add_filter('nav_menu_link_attributes', 'add_onclick_attr_categories_menu', 10, 3);

You may want to ask, why we're keeping the category link on the menu item? 您可能想问, 为什么我们要在菜单项上保留类别链接? It's for SEO and accessibility purpose: for a browser without javascript (like a screen reader) or a search crawler, the categories pages will still be accessible. 它适用于SEO和可访问性目的:对于没有javascript的浏览器(如屏幕阅读器)或搜索爬虫,类别页面仍然可以访问。


2. Preparing your theme for AJAX 2.为AJAX准备主题

In Wordpress, all the AJAX requests need to be sent to wp-admin/admin-ajax.php with an action parameter that will identify the request in order to catch it in functions.php using the wp_ajax_nopriv_my_action (for non logged-in users) and wp_ajax_my_action (for logged in users) hooks. 在Wordpress中,需要将所有AJAX请求发送到wp-admin/admin-ajax.php其中包含一个动作参数,该参数将使用wp_ajax_nopriv_my_action (对于未登录的用户)识别请求以便在functions.php中捕获它和wp_ajax_my_action (对于登录用户)挂钩。

So one small step before going further is to make that path ( wp-admin/admin-ajax.php ) accessible in your JavaScript. 因此,在进一步推进之前的一小步是在JavaScript中访问该路径( wp-admin/admin-ajax.php )。 First, create a js file that we'll use for the AJAX process in your theme folder, let's say his name will be ./js/categories-ajax.js . 首先,创建一个我们将用于主题文件夹中的AJAX进程的js文件,假设他的名字是./js/categories-ajax.js Then, add the following in your functions.php in order to enqueue this new script and make the path accessible through script localization : 然后,在functions.php中添加以下内容,以便将此新脚本排入队列并通过脚本本地化访问该路径:

add_action('wp_enqueue_scripts', 'ajax_categories_enqueue_scripts');
function ajax_categories_enqueue_scripts() {
    wp_register_script('categories_ajax', get_stylesheet_directory_uri() . '/js/categories-ajax.js', array('jquery'), '', true);
    wp_localize_script('categories_ajax', 'ls', array(
        'ajax_url'                  => admin_url('admin-ajax.php')
    ));
    wp_enqueue_script('categories_ajax');
}

With this the admin-ajax.php path will be accessible in your JS with ls.ajax_url . 有了这个,你可以在你的JS中使用ls.ajax_url访问admin-ajax.php路径。


3. Trigger the ajax request 3.触发ajax请求

It's time to create the showPostsFromCategory() function. 是时候创建showPostsFromCategory()函数了。 So let's write in your new categories-ajax.js file. 所以让我们写一下你的新类别-ajax.js文件。 Personally, to avoid any possible conflict with jQuery in my plugin/theme developments I like to always encapsulate my jQuery code in a JavaScript closure and make the functions accessible through global vars like this: 就个人而言,为了避免在我的插件/主题开发中与jQuery发生任何可能的冲突,我喜欢总是将我的jQuery代码封装在JavaScript闭包中,并通过像这样的全局变量来访问函数:

(function($){
  showPostsFromCategory = function(category_slug) {
    // code function...
  };
})(jQuery);
var showPostsFromCategory;

So I'll assume by now that the function code is inside a closure. 所以我现在假设功能代码在闭包内。
Basically, what we need to do now is to set up a $.post request to admin-ajax.php that will sent the following parameters: 基本上,我们现在需要做的是设置一个$.post请求给admin-ajax.php ,它将发送以下参数:

  • action : an identifier of the AJAX action that is being called, in order to make Wordpress know which function should be called later. action :正在调用的AJAX操作的标识符,以使Wordpress知道稍后应该调用哪个函数。 We'll name this dynamic_categories . 我们将这个dynamic_categories命名为。
  • category : the category slug that have being clicked in the menu. category :在菜单中单击的类别slug。

So the function code will look like this: 所以功能代码如下所示:

showPostsFromCategory = function(category_slug) {
    $.post(ls.ajax_url, {action: 'dynamic_categories', category: category_slug}, function success(data) {
        $('#your-post-content-wrapper').html(data); // Update the page with the new posts -- change this ID to the correct one
    });
    return false; // this is to cancel the link click, so the page isn't being redirected
}

This is very basic, you may want to add later some error handling and a loader. 这是非常基本的,您可能希望稍后添加一些错误处理和加载器。 Here we just replace the actual posts with the AJAX return, that we suppose to be HTML. 这里我们只用AJAX返回替换实际的帖子,我们假设是HTML。 Nothing more to be done on the JS side, so let's work on the PHP side now. 在JS方面没有更多的事情要做,所以现在让我们在PHP方面工作。


4. Get the posts for the requested categories 4.获取所请求类别的帖子

First, add the following lines in your functions.php in order to attach the function get_categories_posts() to the wp_ajax_dynamic_categories and wp_ajax_nopriv_dynamic_categories actions. 首先,在functions.php中添加以下行,以便将函数get_categories_posts()附加到wp_ajax_dynamic_categorieswp_ajax_nopriv_dynamic_categories操作。

add_action('wp_ajax_dynamic_categories', 'get_categories_posts');
add_action('wp_ajax_nopriv_dynamic_categories', 'get_categories_posts');

Now, we need to do the following in the function: 现在,我们需要在函数中执行以下操作:

  1. Check if the category slug is valid and it have posts associated, or display an error otherwise. 检查类别slug是否有效且是否有关联的帖子,否则显示错误。
  2. Get the posts associated to the category identified by the slug being sent by the JS script. 获取与 JS脚本发送的slug标识的类别相关联的帖子
  3. Loop through the posts and display each using a template part . 循环浏览帖子并使用模板部分显示每个帖子。 For this, create a template in your theme folder that will contain only the necessary HTML/PHP to display one post. 为此,在主题文件夹中创建一个模板,该模板仅包含显示一个帖子所需的HTML / PHP。 You can see an example of such template in the default wordpress theme (twentysixteen) in 您可以在默认的wordpress主题(twentysixteen)中查看此类模板的示例
    template-parts/content.php . template-parts/content.php Do the same kind of file in your theme - maybe there is already one. 在您的主题中执行相同类型的文件 - 可能已经有一个。

    You will need to update your archive template to make use of the template part too. 您还需要更新存档模板以使用模板部件。 This is very easy, remove the code used to display the post inside the loop and replace it with: 这很简单,删除用于在循环显示帖子的代码并将其替换为:

     <?php get_template_part('template-parts/content'); ?> 

So the whole function code will look like this: 所以整个功能代码如下所示:

function get_categories_posts() {
    // Check if the category slug provided is ok and if it have posts
    if(!isset($_POST['category'])) {
        die('<p class="error">' . __('No category parameter provided', 'your-theme-slug') . '</p>');
    }
    $category_slug = sanitize_text_field($_POST['category']);
    $category = get_category_by_slug($category_slug);
    if(!$category) {
        die('<p class="error">' . sprintf(__('Category %s not found', 'your-theme-slug'), $category_slug) . '</p>');
    }
    $posts = get_posts(array(
        'category' => $category->term_id,
        'posts_per_page' => -1 // get all posts
    ));
    if(empty($posts)) {
        die('<p class="error">' . sprintf(__('The category %s is empty', 'your-theme-slug'), $category->name) . '</p>');
    }

    // Loop through the posts and display them
    foreach ($posts as $post) {
        setup_postdata($post);
        get_template_part('template-parts/content');
    }
    die('');
}

And, that's all! 就这样! With this you now have a dynamic navigation for your posts categories. 有了这个,您现在可以为您的帖子类别进行动态导航。

For reference: sanitize_text_field , get_category_by_slug , get_posts , setup_postdata and get_template_part . 供参考: sanitize_text_fieldget_category_by_slugget_postssetup_postdataget_template_part


Please note that this does not support pagination. 请注意,这不支持分页。 If you need this, check this answer I made about this matter. 如果您需要,请查看我对此事所做的回答


Further readings 进一步阅读

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM