有没有一种简单的AJAX方式--保存帖子?

时间:2012-08-04 作者:jilseego

我们有一个插件,允许我们管理自定义帖子类型,我们希望在保存、编辑和删除帖子时添加AJAX功能。我在互联网上找不到类似的问题,所以我想知道这是否很容易做到?

3 个回复
最合适的回答,由SO网友:Brian Fegter 整理而成

从技术上讲,您可以制作一个XHR来发布。php通过JavaScript。以下是仅用于保存/编辑帖子的概念证明。我还没有测试它,所以我相信你需要调整它。我想给你一个基本的工作流程来完成这样的事情。如果需要扩展,您可以使用它并运行它。

Step 1: Add AJAX handler to admin_head for new and existing posts.

function my_post_type_xhr(){
    global $post;
    if(\'my_post_type\' === $post->post_type){
        $post_url = admin_url(\'post.php\'); #In case we\'re on post-new.php
        echo "
        <script>
            jQuery(document).ready(function($){
                //Click handler - you might have to bind this click event another way
                $(\'input#publish, input#save-post\').click(function(){
                    //Post to post.php
                    var postURL = \'$post_url\';

                    //Collate all post form data
                    var data = $(\'form#post\').serializeArray();

                    //Set a trigger for our save_post action
                    data.push({foo_doing_ajax: true});

                    //The XHR Goodness
                    $.post(postURL, data, function(response){
                        var obj = $.parseJSON(response);
                        if(obj.success)
                            alert(\'Successfully saved post!\');
                        else
                            alert(\'Something went wrong. \' + response);
                    });
                    return false;
                });
            });
        </script>";
    }
}
add_action(\'admin_head-post.php\', \'my_post_type_xhr\');
add_action(\'admin_head-post-new.php\', \'my_post_type_xhr\');

Step 2: Hook into the save_post action.

这将在帖子保存到数据库后运行,因此您可以保存所需的任何postmeta并停止页面呈现。

add_action(\'save_post\', \'save_my_post_type\');
function save_my_post_type($post_id){
    if (defined(\'DOING_AUTOSAVE\') && DOING_AUTOSAVE) return;

    #If this is your post type
    if(\'my_post_type\' === $_POST[\'post_type\']){
        //Save any post meta here

        #We conditionally exit so we don\'t return the full wp-admin load if foo_doing_ajax is true
        if(isset($_POST[\'foo_doing_ajax\']) && $_POST[\'foo_doing_ajax\'] === true){
            header(\'Content-type: application/json\');
            #Send a response
            echo json_encode(array(\'success\' => true));
            exit;
            #You should keep this conditional to degrade gracefully for no JS
        }
    }
}
我能看到的唯一主要警告是,您需要通过XHR以某种方式刷新页面上的nonce。

对于删除帖子,我不知道你为什么要使用AJAX,而只需简单地点击一个链接就可以了。在任何情况下删除一个页面都会将您发送到另一个页面,即编辑。php。这违背了使用AJAX的目的,AJAX的目的是在一个页面加载上保持所有内容的异步。

希望这对你有所帮助。

SO网友:Jess Mann

Brian Fegter的回答是正确的,但也有一些错误。这里有一个基于相同原理的更完善的解决方案。

Step 1: PHP Logic.

放入函数。php(或插件文件)

// Saving the post via AJAX
add_action(\'save_post\', \'save_post_ajax\');
function save_post_ajax( $post_id )
{
        # Ignore autosaves
        if (defined(\'DOING_AUTOSAVE\') && DOING_AUTOSAVE)
                return;

        # Only enabled for one post type
        # Remove this if statement if you want to enable for all post types
        if ($_POST[\'post_type\'] == \'my_custom_post_type\')
        {
                # Send JSON response
                # NOTE: We use ==, not ===, because the value may be String("true")
                if (isset($_POST[\'save_post_ajax\']) && $_POST[\'save_post_ajax\'] == TRUE)
                {
                        header(\'Content-type: application/json\');
                        echo json_encode(array(\'success\' => true));

                        # Don\'t return full wp-admin
                        exit;
                }
        }
}

Step 2: Create javascript in an external file

Brian将js直接回传到页面上的解决方案也很有效。

// Avoid collisions with other libraries
(function($) {
        // Make sure the document is ready
        $(document).ready(function() {
                // This is the post.php url we localized (via php) above
                var url = ajax_object.post_url;
                // Serialize form data
                var data = $(\'form#post\').serializeArray();
                // Tell PHP what we\'re doing
                // NOTE: "name" and "value" are the array keys. This is important. I use int(1) for the value to make sure we don\'t get a string server-side.
                data.push({name: \'save_post_ajax\', value: 1});

                // Replaces wp.autosave.initialCompareString
                var ajax_updated = false;

                /**
                 * Supercede the WP beforeunload function to remove
                 * the confirm dialog when leaving the page (if we saved via ajax)
                 * 
                 * The following line of code SHOULD work in $.post.done(), but 
                 *     for some reason, wp.autosave.initialCompareString isn\'t changed 
                 *     when called from wp-includes/js/autosave.js
                 * wp.autosave.initialCompareString = wp.autosave.getCompareString();
                 */
                $(window).unbind(\'beforeunload.edit-post\');
                $(window).on( \'beforeunload.edit-post\', function() {
                        var editor = typeof tinymce !== \'undefined\' && tinymce.get(\'content\');

                        // Use our "ajax_updated" var instead of wp.autosave.initialCompareString
                        if ( ( editor && !editor.isHidden() && editor.isDirty() ) ||
                                ( wp.autosave && wp.autosave.getCompareString() != ajax_updated) ) { 
                                return postL10n.saveAlert;
                        }   
                });


                // Post it
                $.post(url, data, function(response) {
                        // Validate response
                        if (response.success) {
                                // Mark TinyMCE as saved
                                if (typeof tinyMCE !== \'undefined\') {
                                        for (id in tinyMCE.editors) {
                                                var editor = tinyMCE.get(id);
                                                editor.isNotDirty = true;
                                        }   
                                }
                                // Update the saved content for the beforeunload check
                                ajax_updated = wp.autosave.getCompareString();

                                console.log(\'Saved post successfully\');
                        } else {
                                console.log(\'ERROR: Server returned false. \',response);
                        }
                }).fail(function(response) {
                        console.log(\'ERROR: Could not contact server. \',response);
                });
        });     
})(jQuery);

Step 3: Enqueue your javascript file

如果你(像Brian一样)附和出来,你就不必这样做。我更喜欢这种方法,因为它允许我们将脚本出列,本地化变量,并轻松调整脚本加载顺序。

function my_post_type_xhr()
{
        global $post;
        # Only for one post type. 
        if ($post->post_type == \'custom_post_type\')
        {
                # The url for the js file we created above
                $url = \'/url/to/my/javascript.js\';

                # Register and enqueue the script, dependent on jquery
                wp_register_script( \'my_script\', $url, array(\'jquery\') );
                wp_enqueue_script( \'my_script\' );

                # Localize our variables for use in our js script
                wp_localize_script( \'my_script\', \'ajax_object\', array(
                                \'post_id\' => $post_id,
                                \'post_url\' => admin_url(\'post.php\'),
                ) );
        }
}

add_action(\'admin_head-post.php\', \'my_post_type_xhr\');
add_action(\'admin_head-post-new.php\', \'my_post_type_xhr\');
此代码段不处理nonce。不管怎样,我希望这能帮助别人。

SO网友:Mahdi Akrami

这里有一个更完美的解决方案;)

修复TinyMce错误添加表单提交事件侦听器另外,为了便于使用,我将其缩短:)只需将此代码放入函数中即可。php:

<?php

// Saving the post via AJAX
add_action( \'save_post\', function ( $post_id ) {
    # Ignore autosaves
    if ( defined( \'DOING_AUTOSAVE\' ) && DOING_AUTOSAVE ) {
        return;
    }

    # Only enabled for one post type
    # Remove this if statement if you want to enable for all post types
    if ( $_POST[\'post_type\'] === \'post\' ) {
        # Send JSON response
        # NOTE: We use ==, not ===, because the value may be String("true")
        if ( isset( $_POST[\'save_post_ajax\'] ) && $_POST[\'save_post_ajax\'] == true ) {
            wp_send_json_success();
        }
    }
} );


function my_post_type_xhr() {
    # Only for one post type.
    if ( get_post_type() === \'post\' ) {

        ?>
        <script>
            // Avoid collisions with other libraries
            (function ($) {
                // Make sure the document is ready
                $(document).ready(function () {

                    $(document).on(\'submit\', \'form#post\', function (e) {
                        e.preventDefault()

                        // This is the post.php url we localized (via php) above
                        var url = \'<?= admin_url( \'post.php\' ) ?>\'
                        // Serialize form data
                        var data = $(\'form#post\').serializeArray()
                        // Tell PHP what we\'re doing
                        // NOTE: "name" and "value" are the array keys. This is important. I use int(1) for the value to make sure we don\'t get a string server-side.
                        data.push({name: \'save_post_ajax\', value: 1})

                        // Replaces wp.autosave.initialCompareString
                        var ajax_updated = false

                        /**
                         * Supercede the WP beforeunload function to remove
                         * the confirm dialog when leaving the page (if we saved via ajax)
                         *
                         * The following line of code SHOULD work in $.post.done(), but
                         *     for some reason, wp.autosave.initialCompareString isn\'t changed
                         *     when called from wp-includes/js/autosave.js
                         * wp.autosave.initialCompareString = wp.autosave.getCompareString();
                         */
                        $(window).unbind(\'beforeunload.edit-post\')
                        $(window).on(\'beforeunload.edit-post\', function () {
                            var editor = typeof tinymce !== \'undefined\' && tinymce.get(\'content\')

                            // Use our "ajax_updated" var instead of wp.autosave.initialCompareString
                            if ((editor && !editor.isHidden() && editor.isDirty()) ||
                                (wp.autosave && wp.autosave.getCompareString() !== ajax_updated)) {
                                return postL10n.saveAlert
                            }
                        })


                        // Post it
                        $.post(url, data, function (response) {
                            // Validate response
                            if (response.success) {
                                // Mark TinyMCE as saved
                                if (typeof tinyMCE !== \'undefined\') {
                                    for (id in tinyMCE.editors) {
                                        if (tinyMCE.get(id))
                                            tinyMCE.get(id).setDirty(false)
                                    }
                                }
                                // Update the saved content for the beforeunload check
                                ajax_updated = wp.autosave.getCompareString()

                                console.log(\'Saved post successfully\')
                            } else {
                                console.log(\'ERROR: Server returned false. \', response)
                            }
                        }).fail(function (response) {
                            console.log(\'ERROR: Could not contact server. \', response)
                        }).done(function (){
                            if ( wp.autosave ) {
                                wp.autosave.enableButtons();
                            }

                            $( \'#publishing-action .spinner\' ).removeClass( \'is-active\' );
                        })

                        return false
                    })
                })
            })(jQuery)
        </script>
        <?php
    }
}

add_action( \'admin_footer-post.php\', \'my_post_type_xhr\', 999 );
add_action( \'admin_footer-post-new.php\', \'my_post_type_xhr\', 999 );

结束

相关推荐

url - ajax loaded but no JS

我有这个url来调用分类法。php,通过按下面的代码按钮显示过滤后的帖子:http://myurl/?meta_key=post_views_count&orderby=meta_value&order=ASC 这是我正在使用的JS: $(document).ready(function(){ $.ajaxSetup({cache:false}); $(\"#hot a\").click(function(){ var post_i