Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Extending WordPress Customizer Panels and Sections to allow nesting
.in-sub-panel #customize-theme-controls .customize-pane-child.current-panel-parent,
#customize-theme-controls .customize-pane-child.current-section-parent {
-webkit-transform: translateX(-100%);
-ms-transform: translateX(-100%);
transform: translateX(-100%);
}
( function( $ ) {
var api = wp.customize;
api.bind( 'pane-contents-reflowed', function() {
// Reflow sections
var sections = [];
api.section.each( function( section ) {
if (
'pe_section' !== section.params.type ||
'undefined' === typeof section.params.section
) {
return;
}
sections.push( section );
});
sections.sort( api.utils.prioritySort ).reverse();
$.each( sections, function( i, section ) {
var parentContainer = $( '#sub-accordion-section-' + section.params.section );
parentContainer.children( '.section-meta' ).after( section.headContainer );
});
// Reflow panels
var panels = [];
api.panel.each( function( panel ) {
if (
'pe_panel' !== panel.params.type ||
'undefined' === typeof panel.params.panel
) {
return;
}
panels.push( panel );
});
panels.sort( api.utils.prioritySort ).reverse();
$.each( panels, function( i, panel ) {
var parentContainer = $( '#sub-accordion-panel-' + panel.params.panel );
parentContainer.children( '.panel-meta' ).after( panel.headContainer );
});
});
// Extend Panel
var _panelEmbed = wp.customize.Panel.prototype.embed;
var _panelIsContextuallyActive = wp.customize.Panel.prototype.isContextuallyActive;
var _panelAttachEvents = wp.customize.Panel.prototype.attachEvents;
wp.customize.Panel = wp.customize.Panel.extend({
attachEvents: function() {
if (
'pe_panel' !== this.params.type ||
'undefined' === typeof this.params.panel
) {
_panelAttachEvents.call( this );
return;
}
_panelAttachEvents.call( this );
var panel = this;
panel.expanded.bind( function( expanded ) {
var parent = api.panel( panel.params.panel );
if ( expanded ) {
parent.contentContainer.addClass( 'current-panel-parent' );
} else {
parent.contentContainer.removeClass( 'current-panel-parent' );
}
});
panel.container.find( '.customize-panel-back' )
.off( 'click keydown' )
.on( 'click keydown', function( event ) {
if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
return;
}
event.preventDefault(); // Keep this AFTER the key filter above
if ( panel.expanded() ) {
api.panel( panel.params.panel ).expand();
}
});
},
embed: function() {
if (
'pe_panel' !== this.params.type ||
'undefined' === typeof this.params.panel
) {
_panelEmbed.call( this );
return;
}
_panelEmbed.call( this );
var panel = this;
var parentContainer = $( '#sub-accordion-panel-' + this.params.panel );
parentContainer.append( panel.headContainer );
},
isContextuallyActive: function() {
if (
'pe_panel' !== this.params.type
) {
return _panelIsContextuallyActive.call( this );
}
var panel = this;
var children = this._children( 'panel', 'section' );
api.panel.each( function( child ) {
if ( ! child.params.panel ) {
return;
}
if ( child.params.panel !== panel.id ) {
return;
}
children.push( child );
});
children.sort( api.utils.prioritySort );
var activeCount = 0;
_( children ).each( function ( child ) {
if ( child.active() && child.isContextuallyActive() ) {
activeCount += 1;
}
});
return ( activeCount !== 0 );
}
});
// Extend Section
var _sectionEmbed = wp.customize.Section.prototype.embed;
var _sectionIsContextuallyActive = wp.customize.Section.prototype.isContextuallyActive;
var _sectionAttachEvents = wp.customize.Section.prototype.attachEvents;
wp.customize.Section = wp.customize.Section.extend({
attachEvents: function() {
if (
'pe_section' !== this.params.type ||
'undefined' === typeof this.params.section
) {
_sectionAttachEvents.call( this );
return;
}
_sectionAttachEvents.call( this );
var section = this;
section.expanded.bind( function( expanded ) {
var parent = api.section( section.params.section );
if ( expanded ) {
parent.contentContainer.addClass( 'current-section-parent' );
} else {
parent.contentContainer.removeClass( 'current-section-parent' );
}
});
section.container.find( '.customize-section-back' )
.off( 'click keydown' )
.on( 'click keydown', function( event ) {
if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
return;
}
event.preventDefault(); // Keep this AFTER the key filter above
if ( section.expanded() ) {
api.section( section.params.section ).expand();
}
});
},
embed: function() {
if (
'pe_section' !== this.params.type ||
'undefined' === typeof this.params.section
) {
_sectionEmbed.call( this );
return;
}
_sectionEmbed.call( this );
var section = this;
var parentContainer = $( '#sub-accordion-section-' + this.params.section );
parentContainer.append( section.headContainer );
},
isContextuallyActive: function() {
if (
'pe_section' !== this.params.type
) {
return _sectionIsContextuallyActive.call( this );
}
var section = this;
var children = this._children( 'section', 'control' );
api.section.each( function( child ) {
if ( ! child.params.section ) {
return;
}
if ( child.params.section !== section.id ) {
return;
}
children.push( child );
});
children.sort( api.utils.prioritySort );
var activeCount = 0;
_( children ).each( function ( child ) {
if ( 'undefined' !== typeof child.isContextuallyActive ) {
if ( child.active() && child.isContextuallyActive() ) {
activeCount += 1;
}
} else {
if ( child.active() ) {
activeCount += 1;
}
}
});
return ( activeCount !== 0 );
}
});
})( jQuery );
<?php
if ( class_exists( 'WP_Customize_Panel' ) ) {
class PE_WP_Customize_Panel extends WP_Customize_Panel {
public $panel;
public $type = 'pe_panel';
public function json() {
$array = wp_array_slice_assoc( (array) $this, array( 'id', 'description', 'priority', 'type', 'panel', ) );
$array['title'] = html_entity_decode( $this->title, ENT_QUOTES, get_bloginfo( 'charset' ) );
$array['content'] = $this->get_content();
$array['active'] = $this->active();
$array['instanceNumber'] = $this->instance_number;
return $array;
}
}
}
if ( class_exists( 'WP_Customize_Section' ) ) {
class PE_WP_Customize_Section extends WP_Customize_Section {
public $section;
public $type = 'pe_section';
public function json() {
$array = wp_array_slice_assoc( (array) $this, array( 'id', 'description', 'priority', 'panel', 'type', 'description_hidden', 'section', ) );
$array['title'] = html_entity_decode( $this->title, ENT_QUOTES, get_bloginfo( 'charset' ) );
$array['content'] = $this->get_content();
$array['active'] = $this->active();
$array['instanceNumber'] = $this->instance_number;
if ( $this->panel ) {
$array['customizeAction'] = sprintf( 'Customizing &#9656; %s', esc_html( $this->manager->get_panel( $this->panel )->title ) );
} else {
$array['customizeAction'] = 'Customizing';
}
return $array;
}
}
}
// Enqueue our scripts and styles
function pe_customize_controls_scripts() {
wp_enqueue_script( 'pe-customize-controls', get_theme_file_uri( '/assets/js/pe-customize-controls.js' ), array(), '1.0', true );
}
add_action( 'customize_controls_enqueue_scripts', 'pe_customize_controls_scripts' );
function pe_customize_controls_styles() {
wp_enqueue_style( 'pe-customize-controls', get_theme_file_uri( '/assets/css/pe-customize-controls.css' ), array(), '1.0' );
}
add_action( 'customize_controls_print_styles', 'pe_customize_controls_styles' );
function pe_customize_register( $wp_customize ) {
// Has to be at the top
$wp_customize->register_panel_type( 'PE_WP_Customize_Panel' );
$wp_customize->register_section_type( 'PE_WP_Customize_Section' );
// Below this there is only demo code, safe to delete and add your own
// panels/sections/controls
// Add three levels on panels
$lvl1ParentPanel = new PE_WP_Customize_Panel( $wp_customize, 'lvl_1_parent_panel', array(
'title' => 'Level 1',
'priority' => 131,
));
$wp_customize->add_panel( $lvl1ParentPanel );
$lvl2ParentPanel = new PE_WP_Customize_Panel( $wp_customize, 'lvl_2_parent_panel', array(
'title' => 'Level 2',
'panel' => 'lvl_1_parent_panel',
));
$wp_customize->add_panel( $lvl2ParentPanel );
$lvl3ParentPanel = new PE_WP_Customize_Panel( $wp_customize, 'lvl_3_parent_panel', array(
'title' => 'Level 3',
'panel' => 'lvl_2_parent_panel',
'priority' => 1,
));
$wp_customize->add_panel( $lvl3ParentPanel );
// Add example section and controls to the final (third) panel
$wp_customize->add_section( 'pe_section', array(
'title' => 'Section Test',
'panel' => 'lvl_3_parent_panel',
));
$wp_customize->add_setting( 'pe_test', array(
'default' => 'default value here',
'sanitize_callback' => 'wp_kses_post',
'transport' => 'postMessage',
));
$wp_customize->add_control( 'pe_test', array(
'type' => 'text',
'label' => 'Some text control',
'section' => 'pe_section',
));
// Add example section and controls to the middle (second) panel
$wp_customize->add_section( 'pe_section_2', array(
'title' => 'Section 2 Test',
'panel' => 'lvl_2_parent_panel',
'priority' => 2,
));
$wp_customize->add_setting( 'pe_test_2', array(
'default' => 'default value here',
'sanitize_callback' => 'wp_kses_post',
'transport' => 'postMessage',
));
$wp_customize->add_control( 'pe_test_2', array(
'type' => 'text',
'label' => 'Some text control 2',
'section' => 'pe_section_2',
));
// Add example section and controls to another section
$lvl1ParentSection = new PE_WP_Customize_Section( $wp_customize, 'lvl_1_parent_section', array(
'title' => 'Level 1 Section',
'panel' => 'lvl_3_parent_panel',
));
$wp_customize->add_section( $lvl1ParentSection );
$lv21ParentSection = new PE_WP_Customize_Section( $wp_customize, 'lvl_2_parent_section', array(
'title' => 'Level 2 Section',
'section' => 'lvl_1_parent_section',
'panel' => 'lvl_3_parent_panel',
));
$wp_customize->add_section( $lv21ParentSection );
$wp_customize->add_setting( 'pe_test_3', array(
'default' => 'default value here',
'sanitize_callback' => 'wp_kses_post',
'transport' => 'postMessage',
));
$wp_customize->add_control( 'pe_test_3', array(
'type' => 'text',
'label' => 'Some text control 3',
'section' => 'lvl_2_parent_section',
));
}
add_action( 'customize_register', 'pe_customize_register' );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment