I’m having some trouble with a custom thing I’m doing.
I’ve implented a custom image uploader into a metabox in a custom post type.
Now I’m trying to work out a way that will let me reorder the uploaded images. I found that jQuery Sortable would be a convenient way for the user to be able to just drag and drop in which order the images should appear (in the frontend I’m using a jQuery image slider to show the images and the order of the images are decided by the attachment data “menu_order”, so therefor I need some sort of functionality that saves the menu_order that I create with the jQuery Sortable.
Now, this is a simplified example of what I have:
http://jsfiddle.net/LN4sA/
Together with each attachment I have added hidden input fields with the attachment id and a field that will house the current position of the attachment in the menu order.
The ID of the attachment is easily fetched with basic WP PHP ($attachment->ID).
However, I have not yet found an easy way to populate the #att_order with the proper menu_order. So here I’d like some help/input if someone would be so kind.
To save the actual information I’m using ajax to pull the values from the input fields:
add_action('save_post', 'save_attachment_position');
function save_attachment_position(){
global $post;
if ($post->post_type == 'work') { ?>
<script type="text/javascript">
//<![CDATA[
jQuery.ajax({
type: 'post',
url: ajaxurl,
data: {
action: 'order_attachment',
att_ID: jQuery(this).parents('.attachment').find('#att_id').val(),
att_order: jQuery(this).parents('.attachment').find('#att_order').val(),
_ajax_nonce: jQuery('#ordernonce').val(),
post_type: 'attachment'
}
});
//]]>
</script><?php
}
}
And then use wp_update_post to update the attachment data:
add_action('wp_ajax_order_attachment', 'order_attachment');
function order_attachment($post) {
$attachmentdata = array();
$attachmentdata['ID'] = $_POST['att_ID'];
$attachmentdata['menu_order'] = $_POST['att_order'];
wp_update_post($attachmentdata);
}
I’m aware that I need some sort of loop here but I will work that out.
Any ideas?
Thanks
I’m not entirely sure what your intentions are for the code, and unfortunately i didn’t find what you provided worked very well, so i rewrote parts of the code supplied to make it into a more workable solution.
This code will work for saving the attachment order in the metabox on save
, not via ajax, but realistically there’s no reason to save those changes on every sort(is there?).
I refactored the code so you can adjust the post type at the top of the code. I’m not sure what you aiming for with the enqueue call, and pretty sure it can’t be called in the way you were doing, nor was it needed on the post editor page anyway(sortable and the necessary scripts are already available/loaded on the editor screen).
Give this a shot and see how you get on.. (note this is a working sample)..
// Not applicable to my testing, but left it in because i'm sure it's appropriate to your usage
add_theme_support( 'post-thumbnails' );
add_image_size( 'editor-thumb', 130, 72, true );
// Quicker to update one line than several, only reason it's defined here
$my_post_type="book";
// Add metabox on the proper metabox hook
add_action( 'add_meta_boxes_' . $my_post_type, 'add_image_sortable_box', 2000 );
// Fire jQuery only on the appliable pages
add_action( 'admin_footer-post.php', 'add_sortable_to_elements', 2000 );
add_action( 'admin_footer-post-new.php', 'add_sortable_to_elements', 2000 );
function add_image_sortable_box() {
global $my_post_type;
add_meta_box( 'test-image-thing', 'Sortable Attachments Test', 'do_image_metabox_thingy', $my_post_type, 'side', 'default' );
}
function add_sortable_to_elements() {
?>
<script type="text/javascript">
//<![CDATA[
jQuery(document).ready(function($) {
$('#attachmentcontainer').sortable();
});
//]]>
</script>
<?php
}
function do_image_metabox_thingy( $p ) {
// No global statement needed here, the hook this function is attached to gives you the post object
$args = array(
'order' => 'asc',
'orderby' => 'menu_order',
'post_type' => 'attachment',
'post_parent' => $p->ID,
'post_mime_type' => 'image',
'post_status' => null,
'numberposts' => -1,
);
$attachments = get_posts( $args );
if( $attachments ) :
// Only need 1 nonce to cover the lot
wp_nonce_field( 'my_attachment_sort', 'attachment_sort_nonce' );
?>
<div class="imageuploader">
<div id="attachmentcontainer">
<?php
foreach( $attachments as $attachment ) :
$attachmentid = $attachment->ID;
$editorimage = wp_get_attachment_image_src( $attachment->ID, 'editor-thumb', false, false);
?>
<div class="attachment" id="test-<?php echo $attachment->ID; ?>">
<div class="image">
<img width="100" height="auto" src="https://wordpress.stackexchange.com/questions/23843/<?php echo $editorimage[0]; ?>" />
<input type="hidden" name="att_id[]" id="att_id" value="<?php echo $attachment->ID; ?>" />
</div>
</div>
<?php
endforeach;
?>
<div style="clear: both;"></div>
</div>
</div>
<?php
endif;
}
// Updates the attachments when saving
add_filter( 'wp_insert_post_data', 'test_meta_save', 1000, 2 );
function test_meta_save( $data, $_post_vars ) {
global $my_post_type;
if( $my_post_type != $data['post_type'] || !isset( $_post_vars['attachment_sort_nonce'] ) )
return $data;
if( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE )
return $data;
if( !wp_verify_nonce( $_post_vars['attachment_sort_nonce'], 'my_attachment_sort' ) )
return $data;
global $post_ID;
if( !current_user_can( 'edit_post', $post_ID ) )
return $data;
if( isset( $_post_vars['att_id'] ) ) {
foreach( $_post_vars['att_id'] as $img_index => $img_id ) {
$a = array(
'ID' => $img_id,
'menu_order' => $img_index
);
wp_update_post( $a );
}
}
return $data;
}
Of course make sure to switch the post type value, book is my testing post type.. 🙂
Any questions, add them to your original question, then drop a comment onto this answer to let me know..