Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
WPSE 286268: Demonstration of adding controls which are contextual to device previews. https://wordpress.stackexchange.com/a/286294/8521
<?xml version="1.0"?>
<ruleset name="WPSE 286268 Plugin">
<rule ref="WordPress-Core" />
<rule ref="WordPress.WP.I18n">
<properties>
<property name="text_domain" value="wpse-286268" />
</properties>
</rule>
<rule ref="WordPress-Docs" />
<rule ref="WordPress.Arrays.MultipleStatementAlignment.DoubleArrowNotAligned">
<severity>0</severity>
</rule>
<rule ref="Generic.Formatting.MultipleStatementAlignment.NotSameWarning">
<severity>0</severity>
</rule>
<rule ref="WordPress.Arrays.ArrayDeclarationSpacing.AssociativeKeyFound">
<severity>0</severity>
</rule>
<rule ref="WordPress.Files.FileName.InvalidClassFileName">
<exclude-pattern>wpse-286268.php</exclude-pattern>
</rule>
<arg name="extensions" value="php"/>
<arg value="s"/>
<file>.</file>
<exclude-pattern>*/node_modules/*</exclude-pattern>
<exclude-pattern>*/vendor/*</exclude-pattern>
<exclude-pattern>*/dev-lib/*</exclude-pattern>
</ruleset>
/* globals wp */
/* exported wpse286268controls */
var wpse286268controls = ( function( api ) {
'use strict';
var component = {
deviceControls: {}
};
/**
* Init.
*
* @param {object} args - Args.
* @param {object} args.deviceControls - Device controls.
* @returns {void}
*/
component.init = function( args ) {
component.deviceControls = args.deviceControls;
api.bind( 'ready', component.setControlActiveStates );
};
/**
* Set the active states for the device controls.
*
* @returns {void}
*/
component.setControlActiveStates = function() {
_.each( component.deviceControls, function( controlId, deviceSlug ) {
api.control( controlId, function( control ) {
function isActive() {
return deviceSlug === api.state( 'previewedDevice' ).get();
}
// Set initial active state.
control.active.set( isActive );
// Update active state whenever previewd device changes.
api.state( 'previewedDevice' ).bind( function() {
control.active.set( isActive );
} );
// Override whatever the active_callback may send from server when preview loads.
control.active.validate = isActive;
} );
} );
};
return component;
} )( wp.customize );
/* globals wp, jQuery */
/* exported wpse286268preview */
var wpse286268preview = ( function( api, $ ) {
'use strict';
var component = {
deviceSettings: {},
stylesheetTemplate: ''
};
/**
* Init.
*
* @param {object} args - Args.
* @param {Array} args.deviceSettings - List of settings IDs to preview.
* @param {string} args.stylesheetTemplate - Stylesheet template.
* @returns {void}
*/
component.init = function( args ) {
component.style = $( '#wpse-286268' );
component.stylesheetTemplate = args.stylesheetTemplate;
// After all settings are defined, start previewing changes to all of them.
api.apply( api, _.values( args.deviceSettings ).concat( function onceSettingsRegistered() {
_.each( arguments, function( setting ) {
component.deviceSettings[ setting.id ] = setting;
setting.bind( component.updatePreview );
} );
} ) );
};
/**
* Update preview.
*
* @returns {void}
*/
component.updatePreview = function updatePreview() {
var css = component.stylesheetTemplate;
_.each( component.deviceSettings, function( setting ) {
css = css.replace( '{{' + setting.id + '}}', setting.get() );
} );
component.style.text( css );
};
return component;
} )( wp.customize, jQuery );
<?php
/**
* Plugin Name: WPSE 286268
* Description: Demonstration of adding controls which are contextual to device previews.
* Plugin URI: https://wordpress.stackexchange.com/q/286268/8521
* Version: 0.1.0
* Author: Weston Ruter, XWP
* Author URI: https://weston.ruter.net/
* License: GPLv2+
*
* @package WPSE_286268
*/
/**
* Class WPSE_286268_Plugin
*/
class WPSE_286268_Plugin {
/**
* Device configs.
*
* @var array
*/
public $device_configs = array();
/**
* Stylesheet template.
*
* @var string
*/
public $stylesheet_template;
/**
* Registered device settings.
*
* @var array
*/
public $registered_settings = array();
/**
* Registered device controls.
*
* @var array
*/
public $registered_controls = array();
/**
* Init.
*/
public function init() {
$this->device_configs = array(
'desktop' => array(
'label' => __( 'Desktop element outline', 'wpse-286268' ),
'default' => '#ff0000',
),
'tablet' => array(
'label' => __( 'Tablet element outline', 'wpse-286268' ),
'default' => '#00ff00',
),
'mobile' => array(
'label' => __( 'Mobile element outline', 'wpse-286268' ),
'default' => '#0000ff',
),
);
$this->stylesheet_template = '
* {
outline: solid 1px {{outline_color_desktop}};
}
@media screen and ( max-width: 720px ) {
* {
outline: solid 1px {{outline_color_tablet}};
}
}
@media screen and ( max-width: 320px ) {
* {
outline: solid 1px {{outline_color_mobile}};
}
}
';
add_action( 'customize_register', array( $this, 'customize_register' ), 20 );
add_action( 'customize_controls_enqueue_scripts', array( $this, 'enqueue_controls_scripts' ) );
add_action( 'customize_preview_init', function() {
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_preview_scripts' ) );
} );
add_action( 'wp_print_styles', array( $this, 'print_styles' ), 20 );
}
/**
* Print styles.
*/
public function print_styles() {
echo '<style id="wpse-286268" type="text/css">';
$css = $this->stylesheet_template;
$tpl_vars = array();
foreach ( $this->device_configs as $slug => $params ) {
$tpl_vars[ '{{outline_color_' . $slug . '}}' ] = get_theme_mod( "outline_color_{$slug}", $params['default'] );
}
echo esc_html( str_replace(
array_keys( $tpl_vars ),
array_values( $tpl_vars ),
$css
) );
echo '</style>';
}
/**
* Customize register.
*
* @param WP_Customize_Manager $wp_customize Manager.
*/
public function customize_register( WP_Customize_Manager $wp_customize ) {
$section = $wp_customize->get_section( 'colors' );
if ( ! $section ) {
$section = $wp_customize->add_section( 'colors', array(
'title' => __( 'Colors', 'wpse-286268' ),
) );
}
foreach ( array_keys( $wp_customize->get_previewable_devices() ) as $device_slug ) {
if ( ! isset( $this->device_configs[ $device_slug ] ) ) {
continue;
}
$setting = $wp_customize->add_setting( "outline_color_{$device_slug}", array(
'transport' => 'postMessage',
'sanitize_callback' => 'sanitize_hex_color',
'default' => $this->device_configs[ $device_slug ]['default'],
) );
$this->registered_settings[ $device_slug ] = $setting;
$control_arg = array_merge(
$this->device_configs[ $device_slug ],
array(
'settings' => array( $setting->id ),
'section' => $section->id,
)
);
$control = new WP_Customize_Color_Control( $wp_customize, "outline_color_{$device_slug}", $control_arg );
$wp_customize->add_control( $control );
$this->registered_controls[ $device_slug ] = $control;
}
}
/**
* Enqueue controls scripts.
*/
public function enqueue_controls_scripts() {
$handle = 'wpse-286268-controls';
wp_enqueue_script( $handle, plugin_dir_url( __FILE__ ) . 'wpse-286268-controls.js', array( 'customize-controls' ) );
$exports = array(
'deviceControls' => wp_list_pluck( $this->registered_controls, 'id' ),
);
wp_add_inline_script( $handle, sprintf( 'wpse286268controls.init( %s );', wp_json_encode( $exports ) ) );
}
/**
* Enqueue preview scripts.
*/
public function enqueue_preview_scripts() {
$handle = 'wpse-286268-preview';
wp_enqueue_script( $handle, plugin_dir_url( __FILE__ ) . 'wpse-286268-preview.js', array( 'customize-preview' ), false, true );
$exports = array(
'stylesheetTemplate' => $this->stylesheet_template,
'deviceSettings' => wp_list_pluck( $this->registered_settings, 'id' ),
);
wp_add_inline_script( $handle, sprintf( 'wpse286268preview.init( %s );', wp_json_encode( $exports ) ) );
}
}
if ( version_compare( strtok( get_bloginfo( 'version' ), '-' ), '4.9', '>=' ) ) {
$wpse_286268 = new WPSE_286268_Plugin();
$wpse_286268->init();
}
@seothemes

This comment has been minimized.

Copy link

seothemes commented Jul 30, 2018

Line 135 of the PHP causes an error. Should be changed to:

'settings' => $setting->id,
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.