certainlyakey
2/27/2016 - 5:37 PM

Add metabox with key-value custom fields dynamically added by user

Add metabox with key-value custom fields dynamically added by user

<?php
//usage
$tribe_events_miscinfo = get_post_meta(get_the_ID(), 'tribe_events_miscinfo', true);
if ($tribe_events_miscinfo) {
	foreach ($tribe_events_miscinfo as $k => $v) {
		echo '<dt>'.$v['title'].'</dt>';
		echo '<dd';
		if ($v['tooltip']) {
			echo ' title="'.$v['tooltip'].'"';
		}
		echo '>'.$v['content'];
		echo '</dd>';
	}
}
<?php
//Add metabox with dynamically added key-value (with more values possible) custom fields
//Based on http://wordpress.stackexchange.com/questions/19838/create-more-meta-boxes-as-needed/19852#19852

// Caution, there're 2 set of options below
//Variables used in the following functions should be mentioned in the 'global' statement of each of them appropriately
//=======Options 1=======
$dmb_post_type = 'tribe_events';
$dmb_metabox_label = 'Other information';
$dmb_cf_name = 'tribe_events_miscinfo';

// Add actions, initialise functions
add_action( 'add_meta_boxes', 'dynamic_add_custom_box' );
add_action( 'save_post', 'dynamic_save_postdata' );

//Function to add a meta box 
function dynamic_add_custom_box() {
	global $dmb_post_type, $dmb_metabox_label;

	add_meta_box('dynamic_sectionid', $dmb_metabox_label, 'dynamic_inner_custom_box', $dmb_post_type);
}

//Function that defines metabox contents
function dynamic_inner_custom_box() {

	//=======Options 2=======
	$dmb_label_addnew = 'Add more';
	$dmb_label_remove = 'Remove';

	$dmb_key_name = 'title';
	$dmb_value_name = 'content';
	$dmb_value2_name = 'tooltip';
	
	$dmb_key_label = 'Title of element';
	$dmb_value_label = 'Content of element';
	$dmb_value2_label = 'Tooltip on element';

	global $post;
	global $dmb_cf_name;

	// Use nonce for verification
	wp_nonce_field( plugin_basename( __FILE__ ), 'dynamicMeta_noncename' );

	//OPTIONAL - if using a date field
	//Load admin scripts & styles for JS datepicker via the class from Meta Box plugin. This requires Meta Box plugin by Rilwis installed http://x.co/1YgqA
	// $loadJqUIfromMetaboxPlugin = new RWMB_Date_Field();
	// $loadJqUIfromMetaboxPlugin->admin_enqueue_scripts();

	?>
	<div id="dynamic_inner_custom_box">
	<?php
	$dmb_items = get_post_meta($post->ID,$dmb_cf_name,true);
	$c = 0;
	if ( is_array($dmb_items) && count( $dmb_items ) > 0 ) {
		foreach( $dmb_items as $dmb_item ) {
			if ( isset( $dmb_item[$dmb_key_name] ) || isset( $dmb_item[$dmb_value_name] ) ) {
				printf( '<p class="dmb_parent"><label for=""%6$s[%1$s][%4$s]">%8$s</label> <input type="text" name="%6$s[%1$s][%4$s]" id="%6$s[%1$s][%4$s]" value="%2$s"> <label for="%6$s[%1$s][%5$s]">%9$s</label> <input id="%6$s[%1$s][%5$s]" type="text" name="%6$s[%1$s][%5$s]" value="%3$s"> <label for="%6$s[%1$s][%10$s]">%11$s</label> <input type="text" id="%6$s[%1$s][%10$s]" name="%6$s[%1$s][%10$s]" value="%12$s"> <a href="#" class="remove">%7$s</a></p>', 
			/*1*/   $c, 
			/*2*/   $dmb_item[$dmb_key_name], 
			/*3*/   $dmb_item[$dmb_value_name], 
			/*4*/   $dmb_key_name, 
			/*5*/   $dmb_value_name, 
			/*6*/   $dmb_cf_name, 
			/*7*/   $dmb_label_remove,
			/*8*/   $dmb_key_label,
			/*9*/   $dmb_value_label,
			/*10*/   $dmb_value2_name,
			/*11*/   $dmb_value2_label,
			/*12*/   $dmb_item[$dmb_value2_name]
				);
				$c = $c + 1;
			}
		}
	}
	?>
	<span id="here"></span>
	<a href="#" class="add button-secondary"><?php echo $dmb_label_addnew; ?></a>
	<style type="text/css">
		.dmb_parent {display: flex;}
		.dmb_parent > * {flex:1 1 auto;}
		.dmb_parent label {padding-right:5px; text-align: right;}
		.dmb_parent .remove {padding-left: 5px;}
	</style>
	<script>
		var $ =jQuery.noConflict();
		$(document).ready(function() {
			
			//OPTIONAL
			//Add datepicker to an input
			//$('body').on('focus',".choosedate", function(){ //Allows to init datepicker on non existing yet elements
			//	$(this).datepicker({ dateFormat: "dd.mm.yy" });
			//});

			var count = <?php echo $c; ?>;
			$(".add").on('click',function(e) {
				e.preventDefault();
				count = count + 1;
				$('#here').append('<p class="dmb_parent"><label for="<?php echo $dmb_cf_name; ?>['+count+'][<?php echo $dmb_key_name; ?>]"><?php echo $dmb_key_label; ?></label> <input type="text" id="<?php echo $dmb_cf_name; ?>['+count+'][<?php echo $dmb_key_name; ?>]" name="<?php echo $dmb_cf_name; ?>['+count+'][<?php echo $dmb_key_name; ?>]" value="">  <label for="<?php echo $dmb_cf_name; ?>['+count+'][<?php echo $dmb_value_name; ?>]"><?php echo $dmb_value_label; ?></label> <input type="text" name="<?php echo $dmb_cf_name; ?>['+count+'][<?php echo $dmb_value_name; ?>]" id="<?php echo $dmb_cf_name; ?>['+count+'][<?php echo $dmb_value_name; ?>]" value=""> <label for="<?php echo $dmb_cf_name; ?>['+count+'][<?php echo $dmb_value2_name; ?>]"><?php echo $dmb_value2_label; ?></label> <input type="text" name="<?php echo $dmb_cf_name; ?>['+count+'][<?php echo $dmb_value2_name; ?>]" id="<?php echo $dmb_cf_name; ?>['+count+'][<?php echo $dmb_value2_name; ?>]" value=""> <a href="#" class="remove"><?php echo $dmb_label_remove; ?></a></p>');
				return false;
			});
			$("#dynamic_inner_custom_box").on('click', '.remove', function(e) {
				e.preventDefault();
				$(this).parent().remove();
			});
		});
		</script>
	</div><?php
}

/* When the post is saved, saves our custom data */
function dynamic_save_postdata( $post_id ) {
global $dmb_cf_name;

	if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) 
		return;
	if ( !isset( $_POST['dynamicMeta_noncename'] ) )
		return;
	if ( !wp_verify_nonce( $_POST['dynamicMeta_noncename'], plugin_basename( __FILE__ ) ) )
		return;
	$data2post = $_POST[$dmb_cf_name];
	update_post_meta($post_id,$dmb_cf_name,$data2post);
}