Skip to content

Instantly share code, notes, and snippets.

@westonruter
Last active November 26, 2018 21:17
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save westonruter/9676069 to your computer and use it in GitHub Desktop.
Save westonruter/9676069 to your computer and use it in GitHub Desktop.
Test widget plugin for WordPress issue #27491: Widget Customizer: Dynamically-created inputs cause from to replace itself without event to trigger re-initialization https://core.trac.wordpress.org/ticket/27491
[submodule "chosen"]
path = chosen
url = git@github.com:harvesthq/chosen.git
/*global jQuery */
jQuery( function ( $ ) {
function init( widget_el, is_cloned ) {
// Clean up from the clone which lost all events and data
if ( is_cloned ) {
widget_el.find( '.chosen-container' ).remove();
}
widget_el.find( 'select.dynamic-field-chosen-select' ).chosen( { width: '100%' } );
}
/**
* @param {jQuery.Event} e
* @param {jQuery} widget_el
*/
function on_form_update( e, widget_el ) {
if ( 'dynamic_fields_test' === widget_el.find( 'input[name="id_base"]' ).val() ) {
init( widget_el, 'widget-added' === e.type );
}
}
$( document ).on( 'widget-updated', on_form_update );
$( document ).on( 'widget-added', on_form_update );
$( '.widget:has(.dynamic-field-chosen-select)' ).each( function () {
init( $( this ) );
} );
} );
<?php
/**
* Plugin Name: Customize Widget Dynamic Fields Test
* Description: For testing purposes.
* Author: Weston Ruter, X-Team
* Author URI: http://x-team.com/profile/weston-ruter/
*/
class Dynamic_Fields_Test_Widget extends WP_Widget {
public $chosen_options;
function __construct() {
parent::__construct(
'dynamic_fields_test',
'Dynamic Fields test',
array(
'description' => 'Test customizing widgets with dynamic fields.',
)
);
$this->chosen_options = array(
'' => __( '(None)' ),
'red' => __( 'Red' ),
'green' => __( 'Green' ),
'blue' => __( 'Blue' ),
);
}
/**
* Front-end display of widget.
*
* @param array $args Widget arguments.
* @param array $instance Saved values from database.
*/
public function widget( $args, $instance ) {
$instance = wp_parse_args( $instance, $this->default_instance() );
$title = apply_filters( 'widget_title', $instance['title'] );
echo $args['before_widget']; // xss ok
if ( ! empty( $title ) ) {
echo $args['before_title'] . $title . $args['after_title']; // xss ok
}
echo '<pre>';
echo esc_html( print_r( $instance, true ) );
echo '</pre>';
echo $args['after_widget']; // xss ok
}
/**
* Back-end widget form.
*
* @param array $instance Previously saved values from database.
* @return void
*/
public function form( $instance ) {
wp_enqueue_style(
'chosen',
plugin_dir_url( __FILE__ ) . '/chosen/chosen.css'
);
wp_enqueue_script(
'chosen',
plugin_dir_url( __FILE__ ) . '/chosen/chosen.jquery.js',
array( 'jquery' )
);
wp_enqueue_script(
'dynamic-fields-test-widget',
plugin_dir_url( __FILE__ ) . '/' . basename( __FILE__, '.php' ) . '.js',
array( 'jquery', 'chosen' )
);
$instance = wp_parse_args( $instance, $this->default_instance() );
?>
<p>
<label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e( 'Title:' ); ?></label>
<input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo esc_attr( $instance['title'] ); ?>">
</p>
<p>
<label for="<?php echo $this->get_field_id( 'chosen' ); ?>"><?php _e( 'Chosen:' ); ?></label>
<select id="<?php echo $this->get_field_id( 'chosen' ); ?>" class="dynamic-field-chosen-select" name="<?php echo $this->get_field_name( 'chosen' ); ?>">
<?php foreach ( $this->chosen_options as $value => $text ): ?>
<option value="<?php echo esc_attr( $value ) ?>" <?php selected( $value, $instance['chosen'] ) ?>><?php echo esc_html( $text ) ?></option>
<?php endforeach; ?>
</select>
</p>
<p>
<?php _e( 'Form loaded at: ' ) ?><?php echo date( 'H:m:s' ) ?>
</p>
<?php
}
/**
* @return array
*/
public function default_instance() {
return array(
'title' => '',
'chosen' => '',
);
}
/**
* Sanitize widget form values as they are saved.
*
* @see WP_Widget::update()
*
* @param array $new_instance Values just sent to be saved.
* @param array $old_instance Previously saved values from database.
*
* @return array Updated safe values to be saved.
*/
public function update( $new_instance = array(), $old_instance = array() ) {
$instance = wp_parse_args( $new_instance, $this->default_instance() );
$instance['title'] = strip_tags( $new_instance['title'] );
if ( ! isset( $this->chosen_options[ $instance['chosen'] ] ) ) {
$instance['chosen'] = '';
}
return $instance;
}
}
add_action( 'widgets_init', function () {
register_widget( 'Dynamic_Fields_Test_Widget' );
} );
@dashaluna
Copy link

Hello,
Thank you for sharing this. I'm trying to get it working. I'm new to widget development and js, please bear with me.

I'm using the following code as example:

jQuery(document).on('widget-added widget-updated change', '#my-element-id', function() { //code });

However, it doesn't seem to work. Do events "widget-added" and "widget-updated" have to be attached separately, one per line?

Many thanks,
Dasha

@danbrown1235813
Copy link

Hi, I'm having a similar problem, I can't seem to get the widget updated event to fire. My code is the same as this. Does the updated event actually fires?

If it doesn't fire it might be actually unnecessary, since when the form updates it doesn't actually reset the javascript in my specific code, that may be a universal thing....

@iLenTheme
Copy link

I have the same problem but found this https://core.trac.wordpress.org/ticket/19675 yet still can not load the script then to drag the widget

@iLenTheme
Copy link

add a new field in all widget but in the event you add it to a sidebar do not load me the script, specifically a "WpColorPicker' but I do not load, I only load when save but when dragging no longer works for me.

http://i.imgur.com/fv3xTcD.png

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment