I am building a front end post layout editor using jQuery UI Sortable.

The posts are laid out in 300px by 250px boxes over a background image. The posts are created and edited using the WordPress admin but I want to allow the sites administrator to adjust the order of the boxes using a drag and drop interface on the front end.

I've got the drag and drop sortable part working but need to come up with a way to save the state (order) of the boxes. Ideally I would like to be able to save the state as an option and build it into the query.

The query for the posts is a simple WP_Query that also gets data from custom meta boxes to determine the individual box layout.:

$args= array(
      'meta_key' => 'c3m_shown_on',
       'meta_value'=> 'home' );
    $box_query = new WP_Query($args);  ?>
        <ul id="sortable">
    while ($box_query->have_posts()) : $box_query->the_post(); global $post; global $prefix;           
    $box_size = c3m_get_field($prefix.'box_size', FALSE);
    $box_image = c3m_get_field($prefix.'post_box_image', FALSE);
    $overlay_class = c3m_get_field($prefix.'overlay_class', FALSE);
    if ( c3m_get_field($prefix.'external_link', FALSE) ) {
    $post_link = c3m_get_field($prefix.'external_link', FALSE);
    } else
            { $post_link = post_permalink(); 
    } ?>     
     <li class="<?php echo $box_size;?>  ui-state-default">
        <article <?php post_class() ?> id="post-<?php the_ID(); ?>">
            <?php echo  '<a href="'.$post_link.'" ><img src="'.esc_url($box_image).'" alt="Image via xxxxx.com" /></a>'; ?>
                <div class="post-box <?php echo $overlay_class;?>">
                <?php if ( c3m_get_field( $prefix.'text_display', FALSE) ) { ?>     
                <h2><a href="<?php echo $post_link?>"><?php the_title();?></a></h2> 
                <p><?php echo substr($post->post_excerpt, 0, 90) . '...'; ?></p>            
                <?php } ?>               
    <?php endwhile; ?>

The javascript is just the basic default sortable instructions

jQuery(document).ready(function() {

There are methods available using cookies to save the state but I also need to disable the sortable drag and drop for non admin users so I really need to save to the database.

I'm looking for the most creative and usable method and will award a 100 point bounty to the best answer.


I got somatic's answer working with one minor change.

ajaxurl doesn't return the value on non admin pages so I used wp_localize_script( 'functions', 'MyAjax', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) ); to define the value and changed the javascript line under options to:
url: MyAjax.ajaxurl,

To limit access to arranging the order to only admins I added a conditional to my wp_enqueue_script function:

    function c3m_load_scripts() { 
    if ( current_user_can( 'edit_posts' ) ) {
        wp_enqueue_script( 'jquery-ui' );
        wp_enqueue_script( 'functions', get_bloginfo( 'stylesheet_directory' ) . '/_/js/functions.js', array( 'jquery', 'jquery-ui' ), false);
        wp_localize_script( 'functions', 'MyAjax', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) );

I'm going to do a little more testing and mark this question as solved and award the bounty.

  • 1
    Is it possible you could use menu_order on posts? I know you can use them on attachments so why not posts? if its possible this is where you could store the order of the posts...
    – Scott
    May 6, 2011 at 16:05
  • 1
    Looks like you can - 'menu_order' - Order by Page Order. Used most often for Pages (Order field in the Edit Page Attributes box) and for attachments (the integer fields in the Insert / Upload Media Gallery dialog), but could be used for any post type with distinct 'menu_order' values (they all default to 0).
    – Scott
    May 6, 2011 at 16:07
  • @Brady Great idea on using menu_order. @somatic expanded on it and it worked. Thanks!
    – Chris_O
    May 8, 2011 at 3:12

3 Answers 3


Brady is correct that the best way to handle saving and displaying of custom post type orders is by using the menu_order property

Here's the jquery to make the list sortable and to pass the data via ajax to wordpress:

jQuery(document).ready(function($) {        
    var itemList = $('#sortable');

        update: function(event, ui) {
            $('#loading-animation').show(); // Show the animate loading gif while waiting

            opts = {
                url: ajaxurl, // ajaxurl is defined by WordPress and points to /wp-admin/admin-ajax.php
                type: 'POST',
                async: true,
                cache: false,
                dataType: 'json',
                    action: 'item_sort', // Tell WordPress how to handle this ajax request
                    order: itemList.sortable('toArray').toString() // Passes ID's of list items in  1,3,2 format
                success: function(response) {
                    $('#loading-animation').hide(); // Hide the loading animation
                error: function(xhr,textStatus,e) {  // This can be expanded to provide more information
                    // alert('There was an error saving the updates');
                    $('#loading-animation').hide(); // Hide the loading animation

Here's the wordpress function that listens for the ajax callback and performs the changes on the DB:

function my_save_item_order() {
    global $wpdb;

    $order = explode(',', $_POST['order']);
    $counter = 0;
    foreach ($order as $item_id) {
        $wpdb->update($wpdb->posts, array( 'menu_order' => $counter ), array( 'ID' => $item_id) );
add_action('wp_ajax_item_sort', 'my_save_item_order');
add_action('wp_ajax_nopriv_item_sort', 'my_save_item_order');

The key to displaying the posts in the order you have saved is to add the menu_order property to the query args:

$args= array(
    'meta_key' => 'c3m_shown_on',
    'meta_value'=> 'home'
    'orderby' => 'menu_order',
    'order' => 'ASC'

$box_query = new WP_Query($args);

Then run your loop and output each item... (first line is the core wp loading animation - you'll want to hide it initially via css, and then the jquery function will display when processing)

<img src="<?php bloginfo('url'); ?>/wp-admin/images/loading.gif" id="loading-animation" />
<ul id="sortable">
    <li id="{echo post ID here}">{echo title or other name here}</li>

Code inspired by soulsizzle's excellent tutorial.

  • Excellent answer. I will give it a shot.
    – Chris_O
    May 6, 2011 at 21:30
  • Thank you so much for this - totally helped on something I was working on too. One problem I bumped up against was that each item in the sortable list needs to have an ID that matches the post ID. This was in soulsizzle's tutorial but not in the OP's post. Aug 17, 2011 at 20:51
  • Absolutely right, Dalton, I was too brief in my example. Code updated.
    – somatic
    Aug 29, 2011 at 1:11


Far from finished, but the idea is to send an ajax request on drag and drop. You may also want to trigger the ajax request only after clicking a "save" button or something. An array containing post IDs and new order would be sent.

Then you'd have to update the posts in the database on the server end. Finally, add an order parameter to your WP_Query loop.

I hope this gets you started. Anybody feel free to continue fiddling.

 *  Enqueue javascript and css files
function uc_enqueue_my_assets() {
    wp_enqueue_script( 'jquery-ui-sortable');
    wp_register_script( 'order', plugins_url( '/js/order.js', __FILE__ ), array( 'jquery' ) );
    wp_enqueue_script( 'order' );

function uc_is_user_logged_in()
    if ( is_user_logged_in()) {
        add_action( 'wp_enqueue_scripts', 'uc_enqueue_my_assets' );
        add_action( 'admin_enqueue_scripts', 'uc_enqueue_my_assets' );
add_action('init', 'uc_is_user_logged_in');

 *  Update order of posts by ajax on trigger of drag and drop event
function uc_sort_post_items() {

    $order = wp_parse_id_list(explode(',', $_POST['order']));

    global $wpdb;
    $list = join(', ', $order);
    $wpdb->query('SELECT @i:=0');
        "UPDATE wp_posts SET menu_order = ( @i:= @i+1 )
        WHERE ID IN ( $list ) ORDER BY FIELD( ID, $list );"

add_action('wp_ajax_uc_sort_post_items', 'uc_sort_post_items');
add_action('wp_ajax_nopriv_uc_sort_post_items', 'uc_sort_post_items');

 *  Display sorted posts
function uc_pre_get_posts( $wp_query ) {
    $wp_query->set('orderby', 'menu_order');
    $wp_query->set('order', 'ASC');
add_action( 'pre_get_posts', 'uc_pre_get_posts', 1 );

Javascript file order.js

        update: function(event, ui) {


                url: '/wp-admin/admin-ajax.php',
                type: 'post',
                dataType: 'json',
                    action: 'uc_sort_post_items', // Tell WordPress how to handle this ajax request
                    order: '4567,4569,4565 ' // Passes ID's of list items in  1,3,2 format. Write your own js method to access the list of id from frontend.
                success: function(data, response) {
                error: function(xhr,textStatus,e) {


  • Please don't just dump code. You are requested to add some explanation, why think the above code will answer the question. May 28, 2019 at 5:50
  • @MayeenulIslam Description has been already added inside code snippets as comment line.
    – SkyRar
    May 28, 2019 at 20:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.