Skip to content

Instantly share code, notes, and snippets.

@coreymcollins
Created March 20, 2014 15:17
Show Gist options
  • Save coreymcollins/9666104 to your computer and use it in GitHub Desktop.
Save coreymcollins/9666104 to your computer and use it in GitHub Desktop.
Custom field for Custom Metaboxes and Fields for WordPress (https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress). This requires jQuery UI for drag & drop and sort functionality (http://jqueryui.com/download/#!version=1.10.4&components=1110111110000000000000000000000000). The post IDs are saved in an array, which can be rea…
table.cmb_metabox #posts-wrap {
background: url(../images/tiered-arrow.png) 50% 50% no-repeat;
display: inline-block;
width: 100%;
}
table.cmb_metabox .connected {
border: 1px solid #ddd;
cursor: pointer;
float: left;
height: 300px;
overflow-y: scroll;
padding: 0;
width: 45%;
}
#attached {
float: right;
}
table.cmb_metabox .connected li {
border-bottom: 1px solid #f1f1f1;
margin: 0;
padding: 10px 40px 10px 10px;
position: relative;
}
table.cmb_metabox .connected li:hover {
background: #e6e6e6;
}
#retrieved li.added {
opacity: .5;
}
#retrieved li.added:hover {
background: #fff;
cursor: initial;
}
#retrieved li.added:hover .add-remove {
background-position: 0 -22px;
}
.connected li .sprite {
background: url(../images/tiered-sprite.png);
}
.connected li .add-remove {
display: block;
height: 22px;
position: absolute;
right: 10px;
top: 5px;
width: 22px;
}
#retrieved li .add-remove {
background-position: 0 -22px;
}
#retrieved li:hover .add-remove {
background-position: -22px -22px;
}
#attached li:hover .add-remove {
background-position: -22px 0;
}
/**
* Add the drag and drop and sort functionality to the Tiered Template admin
*/
(function(window, document, $, undefined) {
$(function() {
// Allow the user to drag items from the left list
$('#retrieved li').draggable({
helper: 'clone',
revert: 'invalid',
stack: '#retrieved li'
});
// Allow the right list to be droppable and sortable
$('#attached').droppable({
accept: '#retrieved li',
drop: function(event, ui) {
buildItem( ui.draggable );
},
over: function(event, ui){
attachedAddHiddenField( ui.draggable );
}
}).sortable().disableSelection();
// Clone our dragged item
function buildItem($item) {
// Get the ID of the item being dragged
$itemID = $item[0].attributes[0].value;
// Start our array
$itemArray = [];
// Don't add the item if an item with this ID exists already
$('#attached li').each(function() {
// Get our list item ID
$listItemID = $(this).attr('id');
// Add the ID to our array
$itemArray.push($listItemID);
});
// If our item is not in our post ID array, stop everything
if($.inArray($itemID, $itemArray) !== -1)
return;
// If we can continue, do so
$item.clone().appendTo('#attached');
}
// Add the items when the plus icon is clicked
$('body').on('click', '#retrieved .add-remove', function(){
if ($(this).parent().hasClass('added'))
return;
// Add the 'added' class when clicked
$(this).parent().addClass('added');
// Get the clicked item's ID
$itemID = $(this).parent().attr('id');
// Start our array
$itemArray = [];
// Don't add the item if an item with this ID exists already
$('#attached li').each(function() {
// Get our list item ID
$listItemID = $(this).attr('id');
// Add the ID to our array
$itemArray.push($listItemID);
});
// If our item is not in our post ID array, stop everything
if($.inArray($itemID, $itemArray) !== -1)
return;
// Add the item to the right list
$(this).parent().clone().appendTo($('#attached').not($(this).closest('ul')));
// Add our hidden input field
$('<input type="hidden" name="_attached_posts[]" value="' + $itemID + '">').appendTo('#attached #' + $itemID );
});
// Remove items from our attached list when the minus icon is clicked
$('body').on('click', '#attached .add-remove', function(){
// Get the clicked item's ID
$itemID = $(this).parent().attr('id');
// Remove the list item
$(this).parent().remove();
// Remove the 'added' class from the retrieved column
$('#retrieved #' + $itemID).removeClass('added');
});
// Add a hidden field when our posts are added.
// This saves the ID as post meta
function attachedAddHiddenField($item){
// Get our dragged item ID
$itemID = $item['context'].id;
// Add the 'added' class to our retrieved column when clicked
$('#retrieved #' + $itemID).addClass('added');
// Add our hidden input
setTimeout(function(){
$('<input type="hidden" name="_attached_posts[]" value="' + $itemID + '">').appendTo('#attached #' + $itemID );
},1000);
}
});
})(window, document, jQuery);
<?php
/**
* Add a CMB custom field to allow for the selection of multiple posts
* attached to a single page
*/
add_action( 'cmb_render_custom_attached_posts', 'cmb_render_custom_attached_posts_callback', 10, 2 );
function cmb_render_custom_attached_posts_callback( $field, $meta ) {
// Grab our attached posts meta
$attached = get_post_meta( get_the_ID(), '_attached_posts', true );
// Setup our args
$args = array(
'post_type' => 'post',
'posts_per_page' => -1,
'orderby' => 'name',
'order' => 'ASC',
);
// Get our posts
$posts = get_posts( $args );
// Build our dropdown
if( empty( $meta ) && ! empty( $field['std'] ) )
$meta = $field['std'];
elseif ( empty( $meta ) && empty ( $field['std'] ) )
$meta = array();
// If there are no posts found, just stop
if ( ! $posts )
return;
// Set our count class
$count = 0;
// Wrap our lists
echo '<div id="posts-wrap">';
// Open our retrieved, or found posts, list
echo '<ul id="retrieved" class="connected">';
// Loop through our posts as list items
foreach ( $posts as $post ) {
// Increase our count
$count++;
// Set our zebra stripes
$zebra = $count % 2 == 0 ? 'even' : 'odd';
// Set a class if our post is in our attached post meta
$added = in_array( $post->ID, $attached ) ? ' added' : '';
// Build our list item
echo '<li id="', $post->ID ,'" class="' . $zebra . $added . '">', $post->post_title ,'<span class="sprite add-remove"></span></li>';
}
// Close our retrieved, or found, posts
echo '</ul><!-- #retrieved -->';
// Open our attached posts list
echo '<ul id="attached" class="connected">';
// If we have any posts saved already, display them
echo custom_check_for_attached_posts( $field );
// Close up shop
echo '</ul><!-- #attached -->';
echo '</div><!-- #posts-wrap -->';
// Display our description if one exists
echo '<p class="cmb_metabox_description">', $field['desc'], '</p>';
}
/**
* Helper function to grab and filter our post meta
*/
function custom_check_for_attached_posts( $field ) {
// Start with nothing
$output = '';
// Check to see if we have any meta values saved yet
$attached = get_post_meta( get_the_ID(), $field['id'], true );
// If we do, then we need to display them as items in our attached list
if ( ! $attached ) {
$output .= '<input type="hidden" name="' . $field['id'] . '">';
} else {
// Set our count to zero
$count = 0;
// Remove any empty values
$attached = array_filter( $attached );
// Loop through and build our existing display items
foreach ( $attached as $post ) {
// Increase our count
$count++;
// Set our zebra stripes
$zebra = $count % 2 == 0 ? 'even' : 'odd';
// Build our list item
$output .= '<li id="' . $post . '" class="' . $zebra . '">' . get_the_title( $post ) . '<input type="hidden" value="' . $post . '" name="' . $field['id'] . '[]"><span class="sprite add-remove"></span></li>';
}
}
return $output;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment