-
-
Save fencermonir/8d987820f9c38076f7e87dbd5e5b8ace to your computer and use it in GitHub Desktop.
Extending WordPress Customizer Panels and Sections to allow nesting
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
.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%); | |
} |
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
( 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 ); |
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 | |
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 ▸ %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