Polylang > Blog > Switching WordPress admin action to AJAX

Switching WordPress admin action to AJAX

Sylvain Schellenberger

Tips and tricks

1 January 1970

How WordPress handles ajax for quick edit

Triggering the event

The inlineEditPost object is registered as global. It contains an init() method, which is called when the document is loaded. This method attach a 'click' event listener to elements with the .editinline CSS class, it also attach a 'click' event listener and a 'keydown' event listener to the inline edit form.

The first event will open this inline edit form, while the two others will call the inlineEditPost.save(id). This method calls jQuery’s $.post() method, with the following arguments :

params = {
    action: 'inline-save',
    post_type: typenow,
    post_ID: id,
    edit_date: 'true',
    post_status: page
};

fields = $('#edit-'+id).find(':input').serialize();
params = fields + '&' + $.param(params);

// Make ajax request.
$.post( ajaxurl, params,
    function(r) {
        // ... code executed upon AJAX response
    },
'html');

Where id is passed has parameter to the f inlineEditPost.save() method, and page is retrieved in the form.

Then an AJAX request is sent to the server, to the /wp-admin/admin-ajax.php URL, which is registered in the ajaxurl global variable.

Handling the request

This script triggers the wp_ajax_{$action} dynamic hook, where {$action} is replaced by the value used in the action parameter of the AJAX request (in this case, 'inline-save').

The AJAX action of the WordPress Core are registered in the file /wp-admin/includes/ajax-actions.php, their names corresponding to the syntax : wp_ajax_{$action_name}. Because this structure matches the hook name (with only the - replaced by _), the function wp_ajax_inline_save() will be called here.

This function, as well as every WordPress AJAX functions, starts by calling an ajax_check_referer() in order to verify both the WordPress nonce1 and the HTTP REFERER2. It then uses the parameters of the request from PHP’s $_POST superglobal. If these parameters are validated, it then executes the business logic, which is updating the post matching the given post_ID parameter.

When this is done, the function processes the new HTML to be rendered. It does so by instantiating a WP_Posts_List_Table, which takes a WP_Screen as parameter. This WP_Screen corresponds to the user’s admin panel before triggering the request, and it’s identifier is passed in the $_POST['screen'] parameter. It allows WP_Posts_List_Table to access WP_Screen::$post_type property, containing the name of the Post Type3 being edited. The wp_ajax_inline_save() function can then call the WP_List_Table::display_rows() method that will directly outputs HTML.

Processing the response

The previous $.post() method passed an anonymous function as third argument, this is the code that will be executed asynchronously4, when the server will respond to the AJAX request. This is what it looks like:

function(r) {
    var $errorNotice = $( '#edit-' + id + ' .inline-edit-save .notice-error' ),
        $error = $errorNotice.find( '.error' );
        
    $( 'table.widefat .spinner' ).removeClass( 'is-active' );
    $( '.ac_results' ).hide();
    
    if (r) {
        if ( -1 !== r.indexOf( '<tr' ) ) {
            $(inlineEditPost.what+id).siblings('tr.hidden').addBack().remove();
            $('#edit-'+id).before(r).remove();
            $( inlineEditPost.what + id ).hide().fadeIn( 400, function() {
                // Move focus back to the Quick Edit button. $( this ) is the row being animated.
                $( this ).find( '.editinline' )
                    .attr( 'aria-expanded', 'false' )
                    .focus();
                wp.a11y.speak( inlineEditL10n.saved );
            });
        } else {
            r = r.replace( /<.[^<>]*?>/g, '' );
            $errorNotice.removeClass( 'hidden' );
            $error.html( r );
            wp.a11y.speak( $error.text() );
        }
    } else {
        $errorNotice.removeClass( 'hidden' );
        $error.html( inlineEditL10n.error );
        wp.a11y.speak( inlineEditL10n.error );
    }
}

The r argument is the response from WordPress admin-ajax.php script, that has executed the wp_ajax_inline_save() function. As we’ve seen, this function has outputted HTML, so the fourth argument passed to the inlindeEditPost.save() method is the string 'html', which indicates to jQuery the expected datatype for this response.

There is three possibilities here:

  1. the PHP script succeeded, and the response will effectively be a valid HTML formatted string
  2. the PHP script failed, and the response is empty (?).
  3. the PHP script respond with an HTML formatted error report.

In this last case, this error report will be inserted into the HTML element dedicated to notifying AJAX errors.

In the second case, the script will get the error message stored in the inlineEditL10njavascript object instead. This error string is registered on the server side by the WP_Scripts::localize() method in /wp-includes/script-loader.php, this allows it to be translated with the other WordPress strings.

In the first case, it will find the HTML element corresponding to the item that has been edited, and replace it with the HTML contained in the AJAX response. Then it closes the “quick edit” menu.

In both cases, the script will also outputs the error or success message in a special section of the HTML dedicated to screen readers. This happens through WordPress wp.a11y component’s speak() method.

Going further

Author

Sylvain Schellenberger