One way to do it (which is probably evil) is to select the control by adding a block of javascript using the tr
field of $form_fields
:
function set_image_data( $form_fields, $post ) {
$form_fields['text_color'] = array(
'label' => 'Text Color',
'input' => 'text',
'value' => get_post_meta( $post->ID, '_text_color', true )
);
ob_start();
?>
<script type="text/javascript">
jQuery('[name$="[text_color]"]').myColorPicker();
</script>
<?php
$text_color_js = ob_get_clean();
$form_fields['text_color_js'] = array(
'tr' => $text_color_js, // Adds free-form stuff to table.
);
return $form_fields;
}
add_filter( 'attachment_fields_to_edit', 'set_image_data', 10, 2 );
The javascript is using a customized version of wpColorPicker
that overrides the close
to trigger a change
event (needed since the hidden text_color
field never gets/loses focus so doesn't do it itself):
add_action( 'admin_print_footer_scripts', function () {
?>
<script type="text/javascript">
jQuery(function ($) {
// Extend wpColorPicker to trigger change on close.
$.widget('custom.myColorPicker', $.wp.wpColorPicker, {
close: function () {
this._super();
if (this.initialValue !== this.element.val()) {
this.element.change();
}
}
});
});
</script>
<?php
}, 50 );
You could optionally wrap the above in a conditional so that it only includes the script on upload but it may not fire in some cases.
if ( get_current_screen()->base == 'upload' ) {}
Then there's standard stuff to load wp-color-picker
and save the data:
add_action( 'admin_enqueue_scripts', function () {
if ( get_current_screen()->base == 'upload' ) {
wp_enqueue_style( 'wp-color-picker' );
wp_enqueue_script( 'wp-color-picker' );
}
});
add_filter( 'attachment_fields_to_save', function ( $post, $attachment ) {
if ( isset( $attachment['text_color'] ) ) {
update_post_meta( $post['ID'], '_text_color', $attachment['text_color'] );
}
return $post;
}, 10, 2 );
Update
This usage threw up a bug in wpColorPicker
(see trac https://core.trac.wordpress.org/ticket/32856) in that if the color picker is left open and the Attachment Details modal is closed, an exception is thrown which puts things into a funny state. The workaround is not to call this._super();
in the (very conveniently overridden) close but to replicate the code instead, with the fix:
add_action( 'admin_print_footer_scripts', function () {
?>
<script type="text/javascript">
jQuery(function ($) {
// Extend wpColorPicker to trigger change on close.
$.widget('custom.myColorPicker', $.wp.wpColorPicker, {
close: function () {
this.element.hide();
if ( this.element.iris( 'instance' ) ) {
this.element.iris( 'toggle' );
}
this.button.addClass( 'hidden' );
this.toggler.removeClass( 'wp-picker-open' );
$( 'body' ).off( 'click.wpcolorpicker', this.close );
if (this.initialValue !== this.element.val()) {
this.element.change();
}
}
});
});
</script>
<?php
}, 50 );