WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'm trying to create a plugin that is basically just a WordPress widget. I'm having great difficulty getting the WordPress color picker to function correctly when my widget is first added to the sidebar. I've followed these instructions for integrating the picker. However, this causes two color pickers to show in the sidebar when the widget is first added, only one of which is functional. Once the settings are saved, the second color picker is removed and everything works as expected.

I've also tried adding the color picker after the ajaxComplete event fires instead of ready, but that produces the same result - two color pickers.

I then uncovered this WordPress bug that has been marked as being invalid. When I tried the recommended approach of using the sortstop event, I had even worse results - duplicate color pickers, none of which actually functioned.

I'm looking for solutions to this problem as I've reached a dead-end and can't release this plugin with a known bug. Is there perhaps a way to force a save when the widget is first added? Or is there some other way that I haven't considered in which to address this problem?


Update - Here's the relevant code related to the color picker:

function load_color_picker_style() {
function load_color_picker_script() {
add_action('admin_print_scripts-widgets.php', 'load_color_picker_script');
add_action('admin_print_styles-widgets.php', 'load_color_picker_style');

function form( $instance ) {
    $defaults = array(
        'text_color' => '#000',
    $instance = wp_parse_args( (array) $instance, $defaults ); ?>

        //This shows two color pickers. So does using ajaxComplete or sortstop.
        jQuery(document).ready(function($) {

        <label for="<?php echo $this->get_field_id( 'text_color' ); ?>"><?php _e( 'Text Color', 'date-time' ) ?>:</label>
        <input id="<?php echo $this->get_field_id( 'text_color' ); ?>"  name="<?php echo $this->get_field_name( 'text_color' ); ?>" type="text" value="<?php echo esc_attr( $instance[ 'text_color' ] ); ?>" class="color-picker" />
share|improve this question
Post your code please. – s_ha_dum Oct 27 '13 at 16:11
@s_ha_dum Posted the relevant parts. Thx! – donnapep Oct 29 '13 at 10:12
use this info : stackoverflow.com/questions/18318537/… – ravi patel Jan 7 '14 at 10:41

I added code from this example and it works! (wp 9 still has same issue with color picker)

( function( $ ){
        function initColorPicker( widget ) {
                widget.find( '.color-picker' ).wpColorPicker( {
                        change: _.throttle( function() { // For Customizer
                                $(this).trigger( 'change' );
                        }, 3000 )
            function onFormUpdate( event, widget ) {
                initColorPicker( widget );
        $( document ).on( 'widget-added widget-updated', onFormUpdate );

        $( document ).ready( function() {
                $( '#widgets-right .widget:has(.color-picker)' ).each( function () {
                        initColorPicker( $( this ) );                                                   
                } );
        } );
}( jQuery ) );

share|improve this answer

I struggled with this same issue, and found a solution.

The first issue, is that you need to target only the color picker fields that are in the widgets in the sidebars (and also the inactive widgets to make that function properly as well), that is what's causing the duplicate as it was targeting the class in the available widgets.

$('#widgets-right .color-picker, .inactive-sidebar .color-picker').wpColorPicker();

Second you have to use the ajaxComplete function as this will apply the color picker:

1) When you first add the widget to a sidebar (WP does perform an ajax request when it's first added).

2) When you click save and it performs that ajax request as well.

This only applies the color picker to newly added widgets and when you save a widget, so if you leave the widgets page and then return again, there is no initial ajax request, so the widgets that you have added will not automatically have the color picker applied.

To handle this you do need to ALSO have the ready function that applies the color picker as well.

You could also put this in a separate js file so it doesn't get duplicated if you add multiple widgets.

I went a little farther and made it only apply to elements on widget-save and if it's my widget.

        var elems = jQuery('#widgets-right .color-picker, .inactive-sidebar .color-picker');
        var widget_id = 'my-widget-id';
        jQuery(document).ready(function($) {
        }).ajaxComplete(function(e, xhr, settings) {
            if( settings.data.search('action=save-widget') != -1 && settings.data.search('id_base=' + widget_id) != -1 ) {  
share|improve this answer
Thanks for your reply. I copied your code and substituted my Widget ID, but the duplicate color picker is still there when the Widget is first added. The ready event fires first, followed by ajaxComplete (twice). When I save, ready fires again, followed by ajaxComplete three more times and then the duplicate color pickers disappear. I am using WordPress 3.8. – donnapep Dec 21 '13 at 15:48
Can you post your entire code? The above works for me fine in 3.8. – skywalker14 Dec 31 '13 at 22:40

I just wrote this in another post, but it might be useful here too :)

Mixing what I had and the solution posted by @skywalker14, I arrived to the following:

jQuery(document).ready(function($) {

    $('#widgets-right .color-picker, .inactive-sidebar .color-picker').wpColorPicker();

    // Executes wpColorPicker function after AJAX is fired on saving the widget
    $(document).ajaxComplete(function() {
        $('#widgets-right .color-picker, .inactive-sidebar .color-picker').wpColorPicker();

That did the trick in a much simpler way. I tested it and it seems to be working fine. Hope this can still be helpful to you :)

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.