Skip to content

Instantly share code, notes, and snippets.

@westonruter
Last active April 30, 2022 15:20
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save westonruter/731e3106177ce2b067290ddbe602ce05 to your computer and use it in GitHub Desktop.
Save westonruter/731e3106177ce2b067290ddbe602ce05 to your computer and use it in GitHub Desktop.
/* Make sure edit shortcut for nab body class doesn't conflict with nav menu edit shortcut */
.customize-partial-edit-shortcut-nav_body_class > .customize-partial-edit-shortcut-button {
top: -30px;
}
/* Example styles */
body.foo nav {
border: solid 2px red !important;
}
body.bar nav {
border: solid 2px green !important;
}
body.baz nav {
border: solid 2px blue !important;
}
(function ( api, $ ) {
'use strict';
api.selectiveRefresh.partialConstructor.body_class = api.selectiveRefresh.Partial.extend({
/**
* Class name choices.
*
* This is populated in PHP via `wp_add_inline_script()`.
*
* @type {Array}
*/
choices: [],
/**
* Refresh partial.
*
* Override refresh behavior to bypass partial refresh request in favor of direct DOM manipulation.
*
* @returns {jQuery.Promise} Resolved promise.
*/
refresh: function() {
var partial = this, setting, body, deferred, className;
setting = api( partial.params.primarySetting );
className = setting.get();
body = $( document.body );
body.removeClass( partial.choices.join( ' ' ) );
body.addClass( className );
// Do good diligence and return an expected value from the function.
deferred = new $.Deferred();
deferred.resolveWith( partial, _.map( partial.placements(), function() {
return '';
} ) );
return deferred.promise();
}
});
}) ( wp.customize, jQuery );
<?php
/**
* Plugin Name: WPSE 272991: Toggle body class using partials.
* Description: Demonstration of implementing custom selective refresh partial for toggling body classes.
* Version: 0.1.0
* Plugin URI: https://wordpress.stackexchange.com/questions/272991/add-or-remove-html-class-with-selective-refresh
* Author: Weston Ruter, XWP
* Author URI: https://make.xwp.co/
* License: GPLv2+
* Text Domain: wpse-272991
*
* Copyright (c) 2017 XWP (https://xwp.co/)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2 or, at
* your discretion, any later version, as published by the Free
* Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
class WPSE_272991_Plugin {
const PARTIAL_TYPE = 'body_class';
/**
* Choices.
*
* @var array
*/
public $choices;
/**
* Plugin constructor.
*/
function __construct() {
$this->choices = array(
'foo' => __( 'Foo', 'wpse-272991' ),
'bar' => __( 'Bar', 'wpse-272991' ),
'baz' => __( 'Baz', 'wpse-272991' ),
);
}
/**
* Add hooks.
*/
function add_hooks() {
add_action( 'customize_register', array( $this, 'register' ) );
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
add_action( 'body_class', array( $this, 'filter_body_class' ) );
}
/**
* Add selected body class on the frontend.
*
* @param array $body_classes Body classes.
* @return array Amended body classes.
*/
function filter_body_class( $body_classes ) {
$body_class = get_theme_mod( 'nav_body_class' );
if ( $body_class ) {
$body_classes[] = $body_class;
}
return $body_classes;
}
/**
* Register customizer objects.
*
* @param WP_Customize_Manager $wp_customize
*/
function register( WP_Customize_Manager $wp_customize ) {
$section = $wp_customize->add_section( 'wpse-272991', array(
'title' => __( 'WPSE 272991', 'wpse-272991' ),
) );
$choices = $this->choices; // For sake of closures in PHP 5.3.
$setting = $wp_customize->add_setting( 'nav_body_class', array(
'type' => 'theme_mod',
'transport' => 'postMessage',
'validate_callback' => function( WP_Error $validity, $value ) use ( $choices ) {
if ( ! array_key_exists( $value, $choices ) ) {
$validity->add( 'invalid_choice', __( 'Bad choice', 'wpse-272991' ) );
}
return $validity;
},
) );
$wp_customize->add_control( 'nav_body_class_selector', array(
'type' => 'select',
'label' => __( 'Body Class', 'wpse-272991' ),
'section' => $section->id,
'settings' => $setting->id,
'choices' => $choices,
) );
$wp_customize->selective_refresh->add_partial( 'nav_body_class', array(
'selector' => 'nav',
'type' => self::PARTIAL_TYPE,
'settings' => $setting->id,
) );
}
/**
* Enqueue scripts.
*/
function enqueue_scripts() {
if ( ! is_customize_preview() ) {
return;
}
$handle = 'wpse-272991-customize-preview';
$src = plugin_dir_url( __FILE__ ) . '/wpse-272991-customize-preview.css';
$deps = array( 'customize-preview' );
wp_enqueue_style( $handle, $src, $deps );
$handle = 'wpse-272991-customize-preview';
$src = plugin_dir_url( __FILE__ ) . '/wpse-272991-customize-preview.js';
$deps = array( 'customize-selective-refresh' );
wp_enqueue_script( $handle, $src, $deps );
// Export the choices to JS.
wp_add_inline_script(
$handle,
sprintf(
'wp.customize.selectiveRefresh.partialConstructor[ %s ].prototype.choices = %s;',
wp_json_encode( self::PARTIAL_TYPE ),
wp_json_encode( array_keys( $this->choices ) )
)
);
}
}
$wpse_272991_plugin = new WPSE_272991_Plugin();
add_action( 'plugins_loaded', array( $wpse_272991_plugin, 'add_hooks' ) );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment