Skip to content

Instantly share code, notes, and snippets.

@westonruter
Last active December 31, 2021 11:47
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save westonruter/7965203 to your computer and use it in GitHub Desktop.
Save westonruter/7965203 to your computer and use it in GitHub Desktop.
Demonstrate how to add support to Widget Customizer for sidebars and widgets which have JavaScript initialization http://wordpress.org/plugins/widget-customizer/
<?php
/**
* The functions.php for a theme, adding theme support for widget-customizer,
* and registering a sidebar whose widgets maintain equal heights even when
* widgets in the sidebar are updated via Customizer. This is for demonstration
* purposes, and normally JS wouldn't be embedded in PHP.
* @see http://wordpress.org/plugins/widget-customizer/
*/
/**
* Without this, all changes to sidebars and widgets in the customizer cause a
* full refresh of the preview. By opting-in to widget-customizer support, the
* Widget Customizer plugin then knows that the theme is prepared for updating
* the sidebars and widgets via the postMessage transport, dynamically updating
* the elements via the DOM and not doing a full refresh.
*/
add_theme_support( 'widget-customizer' );
/**
* Register a new sidebar which has dynamic layout
*/
register_sidebar( array(
'name' => __( 'Equal Heights' ),
'id' => 'equal-heights',
) );
/**
* Note: This is not necessary because the 'widget-customizer' theme support by
* default makes all sidebars live-previewable; if you need to prevent an entire
* sidebar from being live-previewed (i.e. postMessage update transport), then
* you can have this filter __return_false
*/
// add_filter( 'customizer_sidebar_widgets_live_previewable_masonry-layout', '__return_true' );
/**
* Render a sidebar in the footer which we'll use to contain widgets that get
* equal heights applied to them at initialization.
*/
add_action( 'wp_footer', function () {
?>
<?php if ( is_active_sidebar( 'equal-heights' ) ): ?>
<div id="equal-heights" class="sidebar">
<?php dynamic_sidebar( 'equal-heights' ); ?>
</div>
<?php endif; ?>
<?php
} );
/**
* Inject the JavaScript which runs the equal-heights logic on the sidebar,
* and which will re-equalize the sidebar when it is updated.
*/
add_action( 'wp_footer', function () {
wp_print_scripts( array( 'jquery' ) );
?>
<script>
jQuery( function ( $ ) {
/**
* Courtesy of http://jsfiddle.net/xBZjG/23/
*/
$.fn.equalHeights = function(base_height) {
var itemsbatch = this;
if (base_height === 0) {
base_height = Math.max.apply(null, this.map(function() {
return $(this).height();
}).get());
}
itemsbatch.height(base_height);
itemsbatch.each(function() {
var elemToResize = this;
$(elemToResize).find('img').load(function() {
if (elemToResize.height > base_height) {
itemsbatch.equalHeights(elemToResize.height);
}
});
});
return base_height;
};
/**
* Set up the button to be able to open the lightbox. This is just
* for a simple example for demonstration purposes. A smarter
* widget would rely on event delegation to not have to re-bind the
* event handlers whenever the widget is updated.
* @param widget_el
*/
var initialize_sidebar = function () {
$( '#equal-heights > .widget' ).equalHeights( 0 );
};
// Invoke now at DOM ready
initialize_sidebar();
/**
* Now, if we're also in the customizer preview, add support for
* Widget Customizer to re-initialize sidebar when it is updated.
*/
if ( typeof wp !== 'undefined' && typeof wp.customize !== 'undefined' ) {
wp.customize.bind( 'sidebar-updated', function ( sidebar_id ) {
if ( 'equal-heights' === sidebar_id ) {
initialize_sidebar();
}
} );
}
} );
</script>
<?php
} );
<?php
/**
* Plugin Name: Lightbox Widget
* Description: Demonstrate how to add live-previewability to Widget Customizer for JS-powered widgets
* Author: Weston Ruter, X-Team
* Author URI: http://x-team.com/profile/weston-ruter/
*/
class Lightbox_Widget extends WP_Widget {
function __construct() {
parent::__construct(
'lightbox',
__( 'Lightbox', 'lightbox-widget' ),
array(
'description' => __( 'Displays a button which opens a lightbox to show the supplied content.', 'lightbox-widget' ),
/**
* Opt-in widget for Widget Customizer live previews via postMessage
* transport. This indicates that live previews are supported.
*/
'customizer_support' => true,
)
);
add_action( 'wp_enqueue_scripts', function () {
wp_enqueue_script( 'colorbox', '//cdnjs.cloudflare.com/ajax/libs/jquery.colorbox/1.4.3/jquery.colorbox-min.js', array( 'jquery' ), false );
wp_enqueue_style( 'colorbox', '//cdnjs.cloudflare.com/ajax/libs/jquery.colorbox/1.4.3/example1/colorbox.css', array(), false );
} );
/**
* Alternative method to the customizer_support widget option above to
* opt-in to customizer support.
*/
// add_filter( 'customizer_widget_live_previewable_lightbox', '__return_true' );
/**
* Prepare to add support for the widget to be live-previewable
*/
add_action( 'wp_footer', array( $this, 'add_widget_behaviors' ) );
}
/**
* Inject the JavaScript for initializing the widget and re-initializing it
* when the widget is updated. Here the JS is rendered out to the page, but
* normally should be enqueued in a separate file.
* @action wp_footer
*/
public function add_widget_behaviors() {
wp_print_scripts( array( 'jquery' ) )
?>
<script>
jQuery( function ( $ ) {
/**
* Set up the button to be able to open the lightbox. This is just
* for a simple example for demonstration purposes. A smarter
* widget would rely on event delegation to not have to re-bind the
* event handlers whenever the widget is updated.
* @param widget_el
*/
var initialize_widget = function ( widget_el ) {
$( widget_el ).find( 'button' ).click( function (e) {
e.stopPropagation();
$.colorbox( {
html: $( this ).data( 'content' ),
width: '50%'
} );
} );
};
/**
* Initialize widgets upon DOM ready
*/
$( '.widget_lightbox' ).each( function () {
initialize_widget( this );
} );
/**
* Now, if we're also in the customizer preview, add support for
* Widget Customizer to re-initialize widget when it is updated.
*/
if ( typeof wp !== 'undefined' && typeof wp.customize !== 'undefined' ) {
wp.customize.bind( 'widget-updated', function ( widget_id ) {
// We only care about the lightbox widget being updated here
if ( ! /^lightbox-\d+/.test( widget_id ) ) {
return;
}
// Re-initialize the widget
var widget_el = $( '#' + widget_id );
initialize_widget( widget_el );
// Update the lightbox content if the lightbox is currently shown
if ( $( '#colorbox' ).is( ':visible' ) ) {
widget_el.find( 'button' ).click();
}
} );
}
} );
</script>
<?php
}
/**
* Convenience method so we don't have to check isset() to prevent array index not defined notices
* @param array $instance
* @return array
*/
public function instance_with_defaults( array $instance ) {
return array_merge(
array(
'title' => __( 'Lightbox Widget', 'lightbox-widget' ),
'content' => __( '(Empty)', 'lightbox-widget' ),
),
array_filter( $instance )
);
}
/**
* @param array $instance
* @return void
*/
public function form( $instance ) {
$instance = $this->instance_with_defaults( $instance );
?>
<p>
<label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php esc_html_e( 'Title:', 'lightbox-widget' ) ?></label>
<input id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" value="<?php echo esc_attr( $instance["title"] ) ?>">
</p>
<p>
<label for="<?php echo $this->get_field_id( 'content' ); ?>"><?php esc_html_e( 'Content:', 'lightbox-widget' ) ?></label><br>
<textarea id="<?php echo $this->get_field_id( 'content' ); ?>" name="<?php echo $this->get_field_name( 'content' ); ?>"><?php echo esc_textarea( $instance["content"] ) ?></textarea>
</p>
<?php
}
/**
* @param array $args
* @param array $instance
*/
public function widget( $args, $instance ) {
$instance = $this->instance_with_defaults( $instance );
extract( $args );
echo $before_widget;
echo $before_title;
echo apply_filters( 'widget_title', $instance['title'] );
echo $after_title;
$content = apply_filters( 'the_content', $instance['content'] );
?>
<p>
<button type="button" type="button" data-content="<?php echo esc_attr( $content ) ?>"><?php esc_html_e( 'Open Lightbox', 'lightbox-widget' ) ?></button>
</p>
<?php
echo $after_widget;
}
}
add_action( 'widgets_init', function () {
register_widget( 'Lightbox_Widget' );
} );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment