Solution to ajax post on widget save breaking Iris color picker in WordPress

Of course we want to use Iris colorpicker in our WordPress widgets. There are tutorials online for how to do this but none of the ones I found included a solution/explanation for why Iris doesn’t work when you initiate a new instance of a widget and stops working when you save a widget. The reason it breaks: Widgets are created and saved with an ajax post. When elements are reloaded in a page (with ajax or other methods) jQuery loses track of them. So starting with the code we have been recommended to use by several tutorials out there


jQuery(document).ready(function($) {  
	$('.my-color-picker').wpColorPicker();  
});

This will trigger Iris on form elements with class “.my-color-picker” that are already active when the page loads. But when ajax reloads your form elements, jQuery will see them as new elements and won’t remember what it did when the page loaded. To fix this we should be able to add a trigger and rebind wpColorPicker() to our form fields when/if ajax is triggered. Like so


// Don't actually do this it doesnt work
jQuery(document).ready(function($) {  
    $("body").bind("ajaxComplete", function(){
          $('.my-color-picker').wpColorPicker();  
    });
});

Unfortunately, it’s not that simple. When you drag a new widget to a sidebar that’s also done with ajax. But something funky happens here. Attempting to bind wpColorPicker to onload and ajaxComplete will leave you with a duplicate color picker that is broken. I’m not sure about the details but it has something to do with the picker being applied to the widget both before and after it is moved to a sidebar.

Now then for the solution. I found a few bug reports on this issue. Only since a few weeks back it’s considered solved. Some new jQuery hooks have been added that enables us to target our color-picker form fields more precisely. Personally, I think it would make more sense if Iris/WordPress handled this on it’s own. Maybe it will at some point in the future! For now though, we have to target our form fields directly and trigger the picker only on particular events.

I’ll be looking in to this during the next couple of days but for now, this is the javascript demo provided in the bug report.


( 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 ) );