mwtsn
7/22/2016 - 8:26 PM

Link Picker for CMB2 - Tutorial

Link Picker for CMB2 - Tutorial

<?php
function mkdo_create_meta_boxes() {
  $prefix = '_profile_';
	/**
 	 * Initiate the metabox
	 */
	$cmb = new_cmb2_box(
		array(
			'id'            => 'cta',
			'title'         => __( 'Call to Action', 'cmb2' ),
			'object_types'  => array( 'profile' ),
			'context'       => 'normal',
			'priority'      => 'low',
			'show_names'    => true,
		)
	);
	/**
 	 * Add the control
	 */
	$field1 = $cmb->add_field( 
		array(
			'name' => __( 'Link Picker', 'cmb2' ),
			'id'   => $prefix . 'cta_link',
			'type' => 'link_picker', // Here is where we add our control
		) 
	);
}
add_action( 'cmb2_admin_init', 'mkdo_create_meta_boxes' );
jQuery(document).ready(function($) {

	/* Set Defaults */
	var url   = $('body');
	var text = $('body');
	var blank = $('body');
	
	/* Open the Link Window on button click */
	$('body').on('click', '.js-insert-link', function(event) {
		
		/* Stop the defalut event from happening */
		event.preventDefault ? event.preventDefault() : event.returnValue = false;
		event.stopPropagation();
		
		/* Set the variables to related to the chosen control */
		url            = $(this).closest('.link-picker').find('input.cmb_text_url ');
		text           = $(this).closest('.link-picker').find('input.cmb_text ');
		blank          = $(this).closest('.link-picker').find('input.cmb_checkbox ');
		
		/* Open the link picker */
		wpActiveEditor = true;
		wpLink.open();
		wpLink.textarea = url;

		return false;
	});

	/* If the action is canceled, close the link picker pop-up */
	$('body').on('click', '#wp-link-cancel, #wp-link-backdrop, #wp-link-close', function(event) {

		wpLink.textarea = url;
		wpLink.close();
		event.preventDefault ? event.preventDefault() : event.returnValue = false;
		event.stopPropagation();
		return false;
	});

	/* Once the link is chosen, populate the control */
	$('body').on('click', '#wp-link-submit', function(event) {
		console.log(text)
		var linkAtts = wpLink.getAttrs();

		linkAtts.text = $('#wp-link-text').val();

		url.val(linkAtts.href);

		if( linkAtts.text != '' ) {
			text.val(linkAtts.text);
		}

		if (linkAtts.target == '_blank') {
			blank.prop('checked', true);
		} else {
			blank.prop('checked', false);
		}

		wpLink.textarea = url;
		wpLink.close();
		event.preventDefault ? event.preventDefault() : event.returnValue = false;
		event.stopPropagation();
		return false;
	});
});
<?php
global $post_id;
/* Media */
if ( isset( $post_id ) ) {
	wp_enqueue_media( array( 'post' => $post_id ) );
}
/* JS */
$plugin_js_url  = plugins_url( 'js/plugin.js', MKDO_LPFC_ROOT );
wp_enqueue_script( MKDO_LPFC_TEXT_DOMAIN, $plugin_js_url, array( 'jquery', 'jquery-ui-core', 'jquery-ui-draggable', 'jquery-ui-droppable', 'thickbox', 'wpdialogs' ), '1.0.0', true );
<?php
/**
 * The following snippets are required for allowing the link_picker field
 * to work as a repeatable field, or in a repeatable group
 */
public function cmb2_sanitize_link_picker( $check, $meta_value, $object_id, $field_args, $sanitize_object ) {
	// if not repeatable, bail out.
	if ( ! is_array( $meta_value ) || ! $field_args['repeatable'] ) {
		return $check;
	}
	foreach ( $meta_value as $key => $val ) {
		$meta_value[ $key ] =  null;
		if( ! empty( $val['url'] ) ) {
			$meta_value[ $key ] = array_map( 'sanitize_text_field', $val );
		}
	}
	return $meta_value;
}
public function cmb2_types_esc_link_picker( $check, $meta_value, $field_args, $field_object ) {
	// if not repeatable, bail out.
	if ( ! is_array( $meta_value ) || ! $field_args['repeatable'] ) {
		return $check;
	}
	foreach ( $meta_value as $key => $val ) {
		$meta_value[ $key ] =  null;
		if( ! empty( $val['url'] ) ) {
			$meta_value[ $key ] = array_map( 'esc_attr', $val );
		}
	}
	return $meta_value;
}
<?php
public function cmb2_render_link_picker( $field, $value, $object_id, $object_type, $field_type_object ) {
	$value = wp_parse_args( $value, array(
		'text'  => '',
		'url'   => '',
		'blank' => 'false',
	) );
	$blank_options = '';
	$blank_options .= '<option value="false" '. selected( $value['blank'], 'false', false ) .'>Opens in same</option>';
	$blank_options .= '<option value="true" '. selected( $value['blank'], 'true', false ) .'>Opens in new</option>';
	?>
	<div class="link-picker">
		<div class="text">
			<p>
				<label for="<?php echo $field_type_object->_id( '_text' ); ?>'">
					<?php echo esc_html( $field_type_object->_text( 'link_picker_text', 'Text' ) ); ?>
				</label>
			</p>
			<?php 
				echo $field_type_object->input( 
					array(
						'class' => 'cmb_text',
						'name'  => $field_type_object->_name( '[text]' ),
						'id'    => $field_type_object->_id( '_text' ),
						'value' => $value['text'],
						'desc'  => '',
					) 
				); 
			?>
		</div>
		<div class="url">
			<p>
				<label for="<?php echo $field_type_object->_id( '_url' ); ?>'">
					<?php echo esc_html( $field_type_object->_text( 'link_picker_url', 'URL' ) ); ?>
				</label>
			</p>
			<?php 
				echo $field_type_object->input( 
					array(
						'class' => 'cmb_text_url',
						'name'  => $field_type_object->_name( '[url]' ),
						'id'    => $field_type_object->_id( '_url' ),
						'value' => $value['url'],
						'type'  => 'url',
						'desc'  => '',
					) 
				); 
			?>
		</div>
		<div class="blank">
			<p>
				<label for="<?php echo $field_type_object->_id( '_blank' ); ?>'">
					<?php echo esc_html( $field_type_object->_text( 'link_picker_blank', 'Window' ) ); ?>
				</label>
			</p>
			<?php 
				echo $field_type_object->select( 
					array(
						'class'   => 'cmb_checkbox',
						'name'    => $field_type_object->_name( '[blank]' ),
						'id'      => $field_type_object->_id( '_blank' ),
						'options' => $blank_options,
						'desc'    => '',
					)
				); 
			?>
		</div>
		<div class="choose">
			<p>
				<label>Choose</label>
			</p>
			<button class="dashicons dashicons-admin-links js-insert-link button button-primary" title="<?php esc_html_e( 'Insert Link', 'cmb' ); ?>">
	 			<span class="screen-reader-text"><?php esc_html_e( 'Choose Link', 'cmb' ); ?></span>
	 		</button>
		</div>
	</div>
	<p class="clear">
		<?php echo $field_type_object->_desc();?>
	</p>
<?php
}
<?php 
$blank_options = '';
$blank_options .= '<option value="false" '. selected( $value['blank'], 'false', false ) .'>Opens in same</option>';
$blank_options .= '<option value="true" '. selected( $value['blank'], 'true', false ) .'>Opens in new</option>';
<?php
echo $field_type_object->select( 
	array(
		'class'   => 'cmb_dropdown',
		'name'    => $field_type_object->_name( '[blank]' ),
		'id'      => $field_type_object->_id( '_blank' ),
		'options' => $blank_options,
	) 
);
<p>
	<label for="<?php echo $field_type_object->_id( '_text' ); ?>'">
		<?php echo esc_html( $field_type_object->_text( 'link_picker_text', 'Text' ) ); ?>
	</label>
</p>
<?php 
	echo $field_type_object->input( 
    		array(
			'class' => 'cmb_text',
			'name'  => $field_type_object->_name( '[text]' ),
			'id'    => $field_type_object->_id( '_text' ),
			'value' => $value['text'],
		) 
  	); 
?>
<?php
$value = wp_parse_args( 
	$value, 
	array(
		'text'  => '',
		'url'   => '',
		'blank' => 'false',
	) 
);
<?php
/**
* Render 'link_picker' custom field type
*
* @param array $field The passed in `CMB2_Field` object
* @param mixed $value The value of this field escaped.
* It defaults to `sanitize_text_field`.
* If you need the unescaped value, you can access it
* via `$field->value()`
* @param int $object_id The ID of the current object
* @param string $object_type The type of object you are working with.
* Most commonly, `post` (this applies to all post-types),
* but could also be `comment`, `user` or `options-page`.
* @param object $field_type_object The `CMB2_Types` object
*/
public function cmb2_render_link_picker( $field, $value, $object_id, $object_type, $field_type_object ) {
…
}
<?php
add_action( 'cmb2_render_link_picker', array( $this, 'cmb2_render_link_picker' ), 10, 5 );