Custom featured image

Adding multiple custom featured image metaboxes to custom post type

https://codex.wordpress.org/Function_Reference/wp_enqueue_media

add_action( 'add_meta_boxes', 'cd_meta_box_add_products' );
function cd_meta_box_add_products(){
	add_meta_box( 'my-meta-box-posts', 'Custom fields', 'cd_meta_box_products', 'products', 'normal', 'high' );
	add_meta_box( 'products_details' , 'Quote', 'cd_meta_box_products_quote', 'products', 'normal', 'high' );
}

function cd_meta_box_products_quote(){
	$values = get_post_custom( $post->ID );
	$image_meta = 'quote_image';
	$image_id = $values[$image_meta][0];
	$image_src = wp_get_attachment_image_src($image_id, array(300,300));
	?>
	<br />
	<label>Quote image</label><br />
	<script type='text/javascript' src='<?php echo get_stylesheet_directory_uri(); ?>/js/image_handler.js'></script>
	<div class="custom_uploader">
		<img class="custom_media_image" src="<?php echo $image_src[0]; ?>" alt="" /><br />
		<a href="#" class="custom_media_add" style="<?php echo ( ! $image_id ? '' : 'display:none;' ) ?>">Set image</a>
		<a href="#" class="custom_media_remove" style="<?php echo ( ! $image_id ? 'display:none;' : '' ) ?>">Remove</a>
		<input class="custom_media_id" type="hidden" name="<?php echo $image_meta; ?>" value="<?php echo $image_id; ?>">
	</div>
	<?php
}

add_action( 'save_post', 'ks_meta_box_save_product' );
function ks_meta_box_save_product( $post_id ){
	...

	if( isset( $_POST['quote_image'] ) )
		update_post_meta( $post_id, 'quote_image', esc_attr( $_POST['quote_image'] ) );
}

image_handler.js

jQuery(document).ready(function ($) {
	var customMediaSelector = {
		init: function() {
			$('.custom_media_add').on('click', function (e) {
				var $el;
 
				e.preventDefault();
 
				$el = customMediaSelector.el = $(this).closest('div');
				$el.image = $el.find('.custom_media_image');
				$el.id = $el.find('.custom_media_id');
 
				customMediaSelector.frame().open();
			});
 
			$('.custom_media_remove').on('click', function (e) {
				var $el = $(this).closest('div');
 
				e.preventDefault();
 
				$el.find('.custom_media_image').attr('src', '').hide();
				$el.find('.custom_media_id').val('');
				$el.find('.custom_media_add, .custom_media_remove').toggle();
			});
		},
 
		// Update the selected image in the media library based on the attachment ID in the field.
		open: function() {
			var selection = this.get('library').get('selection'),
				attachment, selected;
 
			selected = customMediaSelector.el.id.val();
 
			if ( selected && '' !== selected && -1 !== selected && '0' !== selected ) {
				attachment = wp.media.model.Attachment.get( selected );
				attachment.fetch();
			}
 
			selection.reset( attachment ? [ attachment ] : [] );
		},
 
		// Update the control when an image is selected from the media library.
		select: function() {
			var $el = customMediaSelector.el,
				selection = this.get('selection'),
				sizes = selection.first().get('sizes'),
				size;
 
			// Insert the selected attachment id into the target element.
			$el.id.val( selection.first().get( 'id' ) );
 
			// Update the image preview tag.
			if ( sizes ) {
				// The image size to show for the preview.
				size = sizes['thumbnail'] || sizes.medium;
			}
 
			size = size || selection.first().toJSON();
 
			$el.image.attr( 'src', size.url ).show();
			$el.find('.custom_media_add, .custom_media_remove').toggle();
 
			selection.reset();
		},
 
		// Initialize a new frame or return an existing frame.
		frame: function() {
			if ( this._frame )
				return this._frame;
 
			this._frame = wp.media({
				title: 'Set Image',
				library: {
					type: 'image'
				},
				button: {
					text: 'Set image'
				},
				multiple: false
			});
 
			this._frame.on( 'open', this.open ).state('library').on( 'select', this.select );
 
			return this._frame;
		}
	};
 
	customMediaSelector.init();
});