Last active
September 27, 2016 06:12
-
-
Save westonruter/ed4ae3f8b6f6d653e0c6 to your computer and use it in GitHub Desktop.
Depends on https://github.com/xwp/wp-customize-partial-refresh/pull/17 • Demo video: https://www.youtube.com/watch?v=hb3uezGTzFc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* WP_Customize_Rich_Text_Control class | |
* | |
* @package WelcomeMessage | |
*/ | |
namespace WelcomeMessage; | |
/** | |
* Customize Rich Text Control class. | |
* | |
* @see \WP_Customize_Control | |
*/ | |
class WP_Customize_Rich_Text_Control extends \WP_Customize_Control { | |
/** | |
* Control type. | |
* | |
* @since 4.2.0 | |
* @access public | |
* @var string | |
*/ | |
public $type = 'rich_text'; | |
/** | |
* Editor arguments. | |
* | |
* @see \_WP_Editors::parse_settings() | |
* @var array | |
*/ | |
public $editor_arguments = array(); | |
/** | |
* Constructor. | |
* | |
* @since 4.1.0 | |
* @since 4.2.0 Moved from WP_Customize_Upload_Control. | |
* | |
* @param \WP_Customize_Manager $manager Customizer bootstrap instance. | |
* @param string $id Control ID. | |
* @param array $args Optional. Arguments to override class property defaults. | |
*/ | |
public function __construct( $manager, $id, $args = array() ) { | |
if ( ! isset( $args['editor_arguments'] ) ) { | |
$args['editor_arguments'] = array(); | |
} | |
$args['editor_arguments'] = wp_parse_args( $args['editor_arguments'], array( | |
'teeny' => true, | |
) ); | |
parent::__construct( $manager, $id, $args ); | |
} | |
/** | |
* Enqueue control related scripts/styles. | |
*/ | |
public function enqueue() { | |
$handle = 'customize-rich-text-control'; | |
$src = plugin_dir_url( __FILE__ ) . '/customize-rich-text-control.js'; | |
$deps = array( 'customize-controls', 'editor' ); | |
$ver = false; | |
$in_footer = true; | |
wp_enqueue_script( $handle, $src, $deps, $ver, $in_footer ); | |
add_action( 'customize_controls_print_footer_scripts', array( $this, 'render_editor' ), 0 ); | |
// @todo These should be included in \_WP_Editors::editor_settings() | |
if ( false === has_action( 'customize_controls_print_footer_scripts', array( '_WP_Editors', 'enqueue_scripts' ) ) ) { | |
add_action( 'customize_controls_print_footer_scripts', array( '_WP_Editors', 'enqueue_scripts' ) ); | |
} | |
} | |
/** | |
* Render rich text editor. | |
*/ | |
public function render_editor() { | |
echo '<div hidden>'; | |
wp_editor( '', "$this->id-customize-rich-text-control", $this->editor_arguments ); | |
echo '</div>'; | |
} | |
/** | |
* Refresh the parameters passed to the JavaScript via JSON. | |
* | |
* @since 3.4.0 | |
* @since 4.2.0 Moved from WP_Customize_Upload_Control. | |
* | |
* @see WP_Customize_Control::to_json() | |
* @return array Exported data. | |
*/ | |
public function json() { | |
$exported = parent::json(); | |
$exported['editor_arguments'] = $this->editor_arguments; | |
return $exported; | |
} | |
/** | |
* Override render_content to be no-op since content is exported via to_json for deferred embedding. | |
*/ | |
public function render_content() {} | |
/** | |
* An Underscore (JS) template for this control's content (but not its container). | |
* | |
* Class variables for this control class are available in the `data` JS object; | |
* export custom variables by overriding {@see WP_Customize_Control::to_json()}. | |
* | |
* @see WP_Customize_Control::print_template() | |
*/ | |
protected function content_template() { | |
?> | |
<label for="{{ data.settings['default'] }}-button"> | |
<# if ( data.label ) { #> | |
<span class="customize-control-title">{{ data.label }}</span> | |
<# } #> | |
<# if ( data.description ) { #> | |
<span class="description customize-control-description">{{{ data.description }}}</span> | |
<# } #> | |
</label> | |
<div class="wp-editor-placeholder"></div> | |
<?php | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* global wp, jQuery, tinyMCE */ | |
(function( api, $ ) { | |
// @todo Is there a better way to listen for when TinyMCE has finished initializing the editors? | |
var windowLoaded = $.Deferred(); | |
$( window ).on( 'load', function() { | |
tinyMCE.on( '' ); | |
windowLoaded.resolve(); | |
} ); | |
/** | |
* @class | |
* | |
* @todo Populate with initial content | |
* @todo Update setting when rich text editor changes. | |
*/ | |
api.controlConstructor.rich_text = api.Control.extend({ | |
/** | |
* Render the content and inject the TinyMCE editor into the control. | |
*/ | |
renderContent: function() { | |
var control = this; | |
api.Control.prototype.renderContent.call( control ); | |
control.container.find( '.wp-editor-placeholder' ).replaceWith( $( '#wp-' + control.id + '-customize-rich-text-control-wrap' ) ); | |
}, | |
/** | |
* Embed the control into the page. | |
*/ | |
embed: function() { | |
var control = this, | |
inject; | |
// Watch for changes to the section state | |
inject = function( sectionId ) { | |
var parentContainer; | |
if ( ! sectionId ) { // @todo allow a control to be embedded without a section, for instance a control embedded in the frontend | |
return; | |
} | |
// Wait for the section to be registered | |
api.section( sectionId, function( section ) { | |
var deferredDependencies = [ windowLoaded, section.deferred.embedded ]; | |
// Wait for the window to load (and thus the Tiny MCE editor) and the section to be ready/initialized | |
$.when( deferredDependencies ).then( function() { | |
parentContainer = section.container.find( 'ul:first' ); | |
if ( ! control.container.parent().is( parentContainer ) ) { | |
parentContainer.append( control.container ); | |
control.renderContent(); | |
} | |
// @todo tinyMCE.onAddEditor? | |
setTimeout( function() { | |
control.deferred.embedded.resolve(); | |
}, 1000 ); | |
}); | |
}); | |
}; | |
control.section.bind( inject ); | |
inject( control.section.get() ); | |
}, | |
/** | |
* Ready. | |
*/ | |
ready: function() { | |
var control = this, editor = control.getEditor(), element, suspendRecursion; | |
element = new api.Element( $( '#' + control.id + '-customize-rich-text-control' ) ); | |
control.elements.push( element ); | |
element.set( control.setting() ); | |
element.sync( control.setting ); | |
control.setting.bind( function( value ) { | |
if ( ! suspendRecursion ) { | |
editor.setContent( value ); | |
} | |
} ); | |
if ( editor ) { | |
editor.setContent( control.setting() ); | |
editor.on( 'input change keyup', function() { | |
var value = wp.editor.removep( editor.getContent() ); | |
suspendRecursion = true; | |
control.setting.set( value ); | |
suspendRecursion = false; | |
} ); | |
} else { | |
// @todo Initialize when the editor gets added. | |
} | |
}, | |
/** | |
* Get the tinyMCE editor for this control. | |
* | |
* @returns {tinyMCE.Editor|null} | |
*/ | |
getEditor: function() { | |
var control = this; | |
return tinyMCE.get( control.id + '-customize-rich-text-control' ); | |
}, | |
/** | |
* Focus on editor content. | |
* | |
* @param {Object} [params] | |
* @param {Function} [params.completeCallback] | |
*/ | |
focus: function( params ) { | |
var control, completeCallback, focus; | |
control = this; | |
params = params || {}; | |
focus = function() { | |
var editor = control.getEditor(); | |
if ( editor ) { | |
control.container[0].scrollIntoView(); | |
editor.focus(); | |
} else { | |
// Fallback in case the editor hasn't been initialized yet. | |
control.container.find( 'input, select, textarea, button, object, a[href], [tabindex]' ).filter( ':visible' ).first().focus(); | |
} | |
}; | |
if ( params.completeCallback ) { | |
completeCallback = params.completeCallback; | |
params.completeCallback = function() { | |
focus(); | |
completeCallback(); | |
}; | |
} else { | |
params.completeCallback = focus; | |
} | |
if ( control.expand ) { | |
control.expand( params ); | |
} else { | |
params.completeCallback(); | |
} | |
} | |
}); | |
}( wp.customize, jQuery ) ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* global wp */ | |
(function( api ) { | |
api.bind( 'preview-ready', function() { | |
// @todo We can initialize a TinyMCE editor in the preview. | |
} ); | |
}( wp.customize ) ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Plugin name: Welcome Message | |
* Description: Demonstration of selective refresh in the Customizer. | |
* Author: Weston Ruter, XWP | |
* Plugin URL: | |
* | |
* @todo Let this be FooterText instead | |
* | |
* @package WelcomeMessage | |
*/ | |
namespace WelcomeMessage; | |
/** | |
* Render the welcome message. | |
* | |
* This function can be used in the template directly. | |
* This function is called after the associated Customizer setting has already | |
* been previewed, so we can call it just as if we were in the template normally. | |
* | |
* @see \get_template_part() | |
*/ | |
function the_welcome_message() { | |
// @todo What about the before/after container? | |
echo apply_filters( 'the_content', get_option( 'welcome_message' ) ); | |
} | |
/** | |
* Add welcome message container to document before sidebar. | |
*/ | |
function add_welcome_message_container() { | |
echo '<div class="welcome-message">'; | |
the_welcome_message(); | |
echo '</div>'; | |
} | |
add_action( 'get_sidebar', __NAMESPACE__ . '\add_welcome_message_container' ); | |
/** | |
* Enqueue preview scripts. | |
*/ | |
function enqueue_preview_scripts() { | |
$handle = 'welcome-message-preview'; | |
$src = plugin_dir_url( __FILE__ ) . '/welcome-message-preview.js'; | |
$deps = array( 'customize-preview' ); | |
$ver = false; | |
$in_footer = true; | |
wp_enqueue_script( $handle, $src, $deps, $ver, $in_footer ); | |
} | |
add_action( 'customize_preview_init', function() { | |
add_action( 'wp_enqueue_scripts', __NAMESPACE__ . '\enqueue_preview_scripts' ); | |
} ); | |
/** | |
* Register selective refresh partial. | |
* | |
* @param \WP_Customize_Manager $wp_customize Manager. | |
*/ | |
function register_selective_refresh_partial( \WP_Customize_Manager $wp_customize ) { | |
require_once __DIR__ . '/class-wp-customize-rich-text-control.php'; | |
$wp_customize->register_control_type( __NAMESPACE__ . '\WP_Customize_Rich_Text_Control' ); | |
$customize_id = 'welcome_message'; | |
$wp_customize->add_setting( $customize_id, array( | |
'type' => 'option', | |
'transport' => 'postMessage', | |
) ); | |
$wp_customize->add_control( new WP_Customize_Rich_Text_Control( $wp_customize, $customize_id, array( | |
'label' => __( 'Welcome Message' ), | |
'settings' => $customize_id, | |
'section' => 'title_tagline', | |
) ) ); | |
if ( isset( $wp_customize->selective_refresh ) ) { | |
$wp_customize->selective_refresh->add_partial( 'welcome_message', array( | |
'selector' => '.welcome-message', | |
'settings' => array( $customize_id ), | |
'render_callback' => __NAMESPACE__ . '\the_welcome_message', | |
) ); | |
} | |
} | |
add_action( 'customize_register', __NAMESPACE__ . '\register_selective_refresh_partial', 100 ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment