Use meta box drag and drop to order items independently

I am using one meta box for each image in a custom post type, and I would like to use the drag and drop functionality to allow the client to easily reorder them, the problem is when one custom post is reordered, the others are reordered as well… Is there any way that each post has it’s own order?

Where is the order of the meta boxes saved?

Are there any filters I could use to modify the behavior for a particular post type?

Thanks a lot in advance!
Gioia

1 Answer
1

As suggested by sri, I will answer my own question 🙂

The drag and drop of the meta boxes is for remembering the order of the meta boxes for each user, so if user A like to have meta box 5 on top because he uses that feature more, he doesn’t have to do move the meta box every time. I decided that changing that behaviour was not a good idea, as users who know of that behaviour could get confused. Also would mean messing around with the database.

So I instead used the already built in jquery ui sortable to make my custom fields sortable. I created a container div for the sortable fields area, with an id “sortable”, then added a table for each field group (I wanted a group of fields to be sortable, not individual fields). Then a tr for each field. One of the custom fields in each table I used to save the order as a post meta.

<div id="sortable">
    <table>
        <tr><th class="title">My title</td></tr>
        <tr><td>Code postfield 1 - 1</td></tr>
        <tr><td>Code postfield 1 - 2</td></tr>
        <tr><td><input name="ordering_1" type="hidden" class="ordering" value="$meta"></td></tr>
    </table>
    <table>
        <tr><th class="title">My title</td></tr>
        <tr><td>Code postfield 2 -1 </td></tr>
        <tr><td>Code postfield 2 -2</td></tr>
        <tr><td><input name="ordering_2" type="hidden" class="ordering" value="$meta"></td></tr>
    </table>
</div>

Of course this is a over-simplification, as I use arrays to generate the postfields codes, but just to show the structure.

Then I added the javascript:

To add a value to the order custom fields based on their position:

$("#sortable > table").each(function(index) {
    console.log(index+1);
    var count = index+1;
    $(this).find(".ordering").val(count);
}) 

To make the tables sortable. I had to add the handle to the title, otherwise, trying to upload a file started the dragging mode:

$("#sortable").sortable({ 
    cursor: "move", 
    containment: "parent",
    cursorAt: { left: -5,top:-5 },
    distance: 10,
    handle:"th.title"
});

Then to update the order as I drag and dropped:

$('#sortable').on("sortstop", function( event, ui ) {
    $("#sortable > table").each(function(index) {
        console.log(index+1);
        var count = index+1;
        $(this).find(".ordering").val(count);
    }) 
} );

The final thing was to order the tables based on my custom order. I modified the code:

<div id="sortable" style="float:left">
    <? $field_groups = array();
    if (get_post_meta($post->ID,"order_eng_1_1",true)) {
        for ($i = 1; $i <= 20; $i++){
            $field_groups[get_post_meta($post->ID,"order_eng_".$i."_1",true)] = $i;
        }
        ksort($field_groups);
        foreach ($field_groups as $field_order => $field_id) {?>
            <table class="form-table dropable">
                <tr>
                    <th class="title">My Title <?= $field_order?></th>
                </tr>
                <tr><td>Code postfield 1 - 1</td></tr>
                <tr><td>Code postfield 1 - 2</td></tr>
                <tr><td><input name="ordering_1" type="hidden" class="ordering" value="$meta"></td></tr>
            </table>
         <? }
    } else {
        for ($i = 1; $i <= 20; $i++) {?>
            <table class="form-table dropable">
                <tr><th class="title">My title <?=$i?></th></tr>
                <tr><td>Code postfield 1 - 1</td></tr>
                <tr><td>Code postfield 1 - 2</td></tr>
                <tr><td><input name="ordering_2" type="hidden" class="ordering" value="$meta"></td></tr>
            </table>
         <? }
     }?>
</div>

This is my first time trying to explain my code, it’s probably not comprehensive at all, so anything I can do to make it more clear, suggestions are very welcome 😉

Leave a Comment