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">
<?php
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 } ?>
</div>
</article>
</li>
<?php endwhile; ?>
</ul>
</section>
The javascript is just the basic default sortable instructions
jQuery(document).ready(function() {
jQuery("#sortable").sortable();
});
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.
Update:
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.
Brady is correct that the best way to handle saving and displaying of custom post type orders is by using the
menu_order
propertyHere’s the jquery to make the list sortable and to pass the data via ajax to wordpress:
Here’s the wordpress function that listens for the ajax callback and performs the changes on the DB:
The key to displaying the posts in the order you have saved is to add the
menu_order
property to the 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)
Code inspired by soulsizzle’s excellent tutorial.
http://jsfiddle.net/TbR69/1/
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 yourWP_Query
loop.I hope this gets you started. Anybody feel free to continue fiddling.
Javascript file order.js