WordPress.org

Make WordPress Core

Changeset 28861


Ignore:
Timestamp:
06/26/2014 08:16:21 PM (4 years ago)
Author:
ocean90
Message:

Customizer: Introduce a "panel" API to organize multiple sections into a one section.

Create a panel via $GLOBALS['wp_customize']->add_panel( $panel_id, $args ) and use $panel_id for the panel argument in $GLOBALS['wp_customize']->add_section( $section_id, $args ). That's it.
As an example all widget area sections are now summarized into one panel. Feedback appreciated.

props celloexpressions.
see #27406.

Location:
trunk/src
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/src

    • Property svn:ignore
      •  

        old new  
        11.wp-tests-version
        22.htaccess
         3web-store-experiences
  • trunk/src/wp-admin/css/colors/_admin.scss

    r28127 r28861  
    473473}
    474474
     475.control-panel-back:focus,
     476.control-panel-back:hover {
     477    background-color: $menu-highlight-background;
     478    color: $menu-highlight-text;
     479}
    475480
    476481/* jQuery UI Slider */
  • trunk/src/wp-admin/css/customize-controls.css

    r28086 r28861  
    3131.saving #customize-header-actions .spinner {
    3232    display: block;
     33}
     34
     35#customize-controls .wp-full-overlay-sidebar-content {
     36    overflow-y: auto;
     37    overflow-x: hidden;
    3338}
    3439
     
    8489}
    8590
    86 #customize-theme-controls {
    87     -webkit-box-shadow: 0 1px 1px -1px rgba(0, 0, 0, 0.1);
    88     box-shadow: 0 1px 1px -1px rgba(0, 0, 0, 0.1);
    89 }
    90 
    9191#customize-theme-controls .control-section {
    9292    border: none;
     
    104104}
    105105
    106 #customize-theme-controls .control-section:hover .accordion-section-title,
     106#customize-theme-controls .control-section:hover > .accordion-section-title,
    107107#customize-theme-controls .control-section .accordion-section-title:hover,
    108108#customize-theme-controls .control-section.open .accordion-section-title,
     
    119119}
    120120
    121 #customize-theme-controls .control-section:hover .accordion-section-title::after,
     121#customize-theme-controls .control-section:hover > .accordion-section-title::after,
    122122#customize-theme-controls .control-section .accordion-section-title:hover::after,
    123123#customize-theme-controls .control-section.open .accordion-section-title::after,
     
    142142#customize-theme-controls .accordion-section-content {
    143143    margin: 0;
     144}
     145
     146.control-section.control-panel > .accordion-section-title:after {
     147    content: "\f139";
     148}
     149
     150.accordion-sub-container.control-panel-content {
     151    display: none;
     152    position: absolute;
     153    left: 300px;
     154    top: 0;
     155    width: 300px;
     156    border-top: 1px solid #ddd;
     157    -webkit-transition: left ease-in-out .18s;
     158    transition: left ease-in-out .18s;
     159}
     160
     161.accordion-sub-container.control-panel-content.animating {
     162    display: block;
     163}
     164
     165.current-panel .accordion-sub-container.control-panel-content {
     166    width: 100%;
     167}
     168
     169.control-panel-back {
     170    display: block;
     171    position: fixed;
     172    top: 0;
     173    z-index: 99;
     174    left: -48px;
     175    width: 45px;
     176    height: 45px;
     177    padding-right: 2px;
     178    background: #eee;
     179    border-right: 1px solid #ddd;
     180    cursor: pointer;
     181    -webkit-transition: left ease-in-out .18s, color ease-in .1s;
     182    transition: left ease-in-out .18s, color ease-in .1s;
     183}
     184
     185.collapsed .control-panel-back {
     186    display: none;
     187}
     188
     189.control-panel-back:focus,
     190.control-panel-back:hover {
     191    background-color: #0074a2;
     192    color: #fff;
     193    outline: none;
     194}
     195
     196.control-panel-back:before {
     197    font: normal 29px/1 dashicons;
     198    content: "\f340";
     199    position: relative;
     200    top: 9px;
     201    left: 9px;
     202}
     203
     204.current-panel .control-panel-back {
     205    left: 0;
     206}
     207
     208.current-panel > .accordion-section-title {
     209    height: 22px;
     210}
     211
     212#customize-header-actions a.back {
     213    position: relative;
     214    left: 0;
     215    -webkit-transition: left ease-in-out .18s;
     216    transition: left ease-in-out .18s;
     217}
     218
     219.in-sub-panel #customize-header-actions a.back {
     220    left: -120px;
     221}
     222
     223.wp-full-overlay-sidebar .wp-full-overlay-header {
     224    -webkit-transition: padding ease-in-out .18s;
     225    transition: padding ease-in-out .18s;
     226}
     227
     228.in-sub-panel .wp-full-overlay-sidebar .wp-full-overlay-header {
     229    padding-left: 62px;
     230}
     231
     232#customize-info,
     233#customize-theme-controls > ul > .accordion-section {
     234    position: relative;
     235    left: 0;
     236    -webkit-transition: left ease-in-out .18s;
     237    transition: left ease-in-out .18s;
     238}
     239
     240.in-sub-panel #customize-info,
     241.in-sub-panel #customize-theme-controls > ul > .accordion-section {
     242    left: -300px;
     243    width: 300px;
     244}
     245
     246.in-sub-panel #customize-theme-controls .accordion-section.current-panel {
     247    width: 100%;
     248}
     249
     250#customize-theme-controls .control-section.current-panel {
     251    padding: 0;
     252}
     253
     254#customize-theme-controls .control-section > h3.accordion-section-title {
     255    position: relative;
     256    left: 0;
     257}
     258
     259#customize-theme-controls .control-section.current-panel > h3.accordion-section-title {
     260    left: -300px;
     261    -webkit-transition: left ease-in-out .18s;
     262    transition: left ease-in-out .18s;
     263}
     264
     265.control-section.control-panel .accordion-section-title .panel-title {
     266    font-size: 20px;
     267    font-weight: 200;
     268    line-height: 24px;
     269    display: block;
     270    border: none;
     271}
     272
     273.control-section.control-panel .preview-notice {
     274    font-size: 13px;
     275    line-height: 24px;
    144276}
    145277
  • trunk/src/wp-admin/customize.php

    r28482 r28861  
    143143            <div id="customize-theme-controls"><ul>
    144144                <?php
    145                 foreach ( $wp_customize->sections() as $section )
     145                foreach ( $wp_customize->panels() as $panel ) {
     146                    $panel->maybe_render();
     147                }
     148                foreach ( $wp_customize->sections() as $section ) {
    146149                    $section->maybe_render();
     150                }
    147151                ?>
    148152            </ul></div>
  • trunk/src/wp-admin/js/accordion.js

    r24734 r28861  
    55        // Expand/Collapse on click
    66        $( '.accordion-container' ).on( 'click keydown', '.accordion-section-title', function( e ) {
    7             if ( e.type === 'keydown' && 13 !== e.which ) // "return" key
    8                     return;
     7            if ( e.type === 'keydown' && 13 !== e.which ) { // "return" key
     8                return;
     9            }
     10
    911            e.preventDefault(); // Keep this AFTER the key filter above
    1012
    1113            accordionSwitch( $( this ) );
     14        });
     15
     16        // Back to top level
     17        $( '.accordion-container' ).on( 'click keydown', '.control-panel-back', function( e ) {
     18            if ( e.type === 'keydown' && 13 !== e.which ) { // "return" key
     19                return;
     20            }
     21
     22            e.preventDefault(); // Keep this AFTER the key filter above
     23
     24            panelSwitch( $( this ) );
    1225        });
    1326
     
    3447            content = section.find( sectionContent );
    3548
    36         if ( section.hasClass( 'cannot-expand' ) )
     49        if ( section.hasClass( 'cannot-expand' ) ) {
    3750            return;
     51        }
     52
     53        if ( section.hasClass( 'control-panel' ) ) {
     54            panelSwitch( section );
     55            return;
     56        }
    3857
    3958        if ( section.hasClass( 'open' ) ) {
     
    5069    }
    5170
     71    function panelSwitch( panel ) {
     72        var position,
     73            section = panel.closest( '.accordion-section' ),
     74            container = section.closest( '.wp-full-overlay' ),
     75            siblings = container.find( '.accordion-section.open' ),
     76            content = section.find( '.control-panel-content' );
     77
     78        if ( section.hasClass( 'current-panel' ) ) {
     79            section.toggleClass( 'current-panel' );
     80            container.toggleClass( 'in-sub-panel' );
     81            content.delay( 180 ).hide( 0, function() {
     82                content.css( 'margin-top', 'inherit' ); // Reset
     83            } );
     84        } else {
     85            siblings.removeClass( 'open' );
     86            content.show( 0, function() {
     87                position = content.offset().top;
     88                content.css( 'margin-top', ( 45 - position ) );
     89                section.toggleClass( 'current-panel' );
     90                container.toggleClass( 'in-sub-panel' );
     91            } );
     92        }
     93    }
     94
    5295    // Initialize the accordion (currently just corner fixes)
    5396    accordionInit();
  • trunk/src/wp-includes/class-wp-customize-manager.php

    r28546 r28861  
    4646
    4747    protected $settings = array();
     48    protected $panels   = array();
    4849    protected $sections = array();
    4950    protected $controls = array();
     
    313314    public function sections() {
    314315        return $this->sections;
     316    }
     317
     318    /**
     319     * Get the registered panels.
     320     *
     321     * @since 4.0.0
     322     *
     323     * @return array
     324     */
     325    public function panels() {
     326        return $this->panels;
    315327    }
    316328
     
    649661
    650662    /**
     663     * Add a customize panel.
     664     *
     665     * @since 4.0.0
     666     *
     667     * @param WP_Customize_Panel|string $id   Customize Panel object, or Panel ID.
     668     * @param array                     $args Panel arguments.
     669     */
     670    public function add_panel( $id, $args = array() ) {
     671        if ( is_a( $id, 'WP_Customize_Panel' ) ) {
     672            $panel = $id;
     673        }
     674        else {
     675            $panel = new WP_Customize_Panel( $this, $id, $args );
     676        }
     677
     678        $this->panels[ $panel->id ] = $panel;
     679    }
     680
     681    /**
     682     * Retrieve a customize panel.
     683     *
     684     * @since 4.0.0
     685     *
     686     * @param string $id Panel ID.
     687     * @return WP_Customize_Panel
     688     */
     689    public function get_panel( $id ) {
     690        if ( isset( $this->panels[ $id ] ) ) {
     691            return $this->panels[ $id ];
     692        }
     693    }
     694
     695    /**
     696     * Remove a customize panel.
     697     *
     698     * @since 4.0.0
     699     *
     700     * @param string $id Panel ID.
     701     */
     702    public function remove_panel( $id ) {
     703        unset( $this->panels[ $id ] );
     704    }
     705
     706    /**
    651707     * Add a customize section.
    652708     *
     
    750806
    751807    /**
    752      * Prepare settings and sections.
     808     * Prepare panels, sections, and controls.
    753809     *
    754810     * For each, check if required related components exist,
     
    764820
    765821        foreach ( $this->controls as $id => $control ) {
    766             if ( ! isset( $this->sections[ $control->section ] ) || ! $control->check_capabilities() )
     822            if ( ! isset( $this->sections[ $control->section ] ) || ! $control->check_capabilities() ) {
    767823                continue;
     824            }
    768825
    769826            $this->sections[ $control->section ]->controls[] = $control;
     
    779836
    780837        foreach ( $this->sections as $section ) {
    781             if ( ! $section->check_capabilities() || ! $section->controls )
     838            if ( ! $section->check_capabilities() || ! $section->controls ) {
    782839                continue;
     840            }
    783841
    784842            usort( $section->controls, array( $this, '_cmp_priority' ) );
    785             $sections[] = $section;
     843
     844            if ( ! $section->panel ) {
     845                // Top-level section.
     846                $sections[] = $section;
     847            } else {
     848                // This section belongs to a panel.
     849                if ( isset( $this->panels [ $section->panel ] ) ) {
     850                    $this->panels[ $section->panel ]->sections[] = $section;
     851                }
     852            }
    786853        }
    787854        $this->sections = $sections;
     855
     856        // Prepare panels.
     857        // Reversing makes uasort sort by time added when conflicts occur.
     858        $this->panels = array_reverse( $this->panels );
     859        uasort( $this->panels, array( $this, '_cmp_priority' ) );
     860        $panels = array();
     861
     862        foreach ( $this->panels as $panel ) {
     863            if ( ! $panel->check_capabilities() || ! $panel->sections ) {
     864                continue;
     865            }
     866
     867            usort( $panel->sections, array( $this, '_cmp_priority' ) );
     868            $panels[] = $panel;
     869        }
     870        $this->panels = $panels;
    788871    }
    789872
  • trunk/src/wp-includes/class-wp-customize-section.php

    r28827 r28861  
    3737     */
    3838    public $priority = 10;
     39
     40    /**
     41     * Panel in which to show the section, making it a sub-section.
     42     *
     43     * @since 4.0.0
     44     * @access public
     45     * @var string
     46     */
     47    public $panel = '';
    3948
    4049    /**
     
    163172     */
    164173    protected function render() {
     174        $classes = 'control-section accordion-section';
     175        if ( $this->panel ) {
     176            $classes .= ' control-subsection';
     177        }
    165178        ?>
    166         <li id="accordion-section-<?php echo esc_attr( $this->id ); ?>" class="control-section accordion-section">
     179        <li id="accordion-section-<?php echo esc_attr( $this->id ); ?>" class="<?php echo esc_attr( $classes ); ?>">
    167180            <h3 class="accordion-section-title" tabindex="0"><?php echo esc_html( $this->title ); ?></h3>
    168181            <ul class="accordion-section-content">
     
    179192    }
    180193}
     194
     195/**
     196 * Customize Panel Class.
     197 *
     198 * A UI container for sections, managed by the WP_Customize_Manager.
     199 *
     200 * @package WordPress
     201 * @subpackage Customize
     202 * @since 4.0.0
     203 */
     204class WP_Customize_Panel extends WP_Customize_Section {
     205
     206    /**
     207     * Customizer sections for this panel.
     208     *
     209     * @since 4.0.0
     210     * @access public
     211     * @var array
     212     */
     213    public $sections;
     214
     215    /**
     216     * Constructor.
     217     *
     218     * Any supplied $args override class property defaults.
     219     *
     220     * @since 4.0.0
     221     *
     222     * @param WP_Customize_Manager $manager Customizer bootstrap instance.
     223     * @param string               $id      An specific ID of the section.
     224     * @param array                $args    Section arguments.
     225     */
     226    public function __construct( $manager, $id, $args = array() ) {
     227        parent::__construct( $manager, $id, $args );
     228
     229        $this->sections = array(); // Users cannot customize the $sections array.
     230
     231        return $this;
     232    }
     233
     234    /**
     235     * Render the panel, and the sections that have been added to it.
     236     *
     237     * @since 4.0.0
     238     */
     239    protected function render() {
     240        ?>
     241        <li id="accordion-section-<?php echo esc_attr( $this->id ); ?>" class="control-section control-panel accordion-section">
     242            <h3 class="accordion-section-title" tabindex="0"><?php echo esc_html( $this->title ); ?></h3>
     243            <span class="control-panel-back" tabindex="0"><span class="screen-reader-text">Back to Customize</span></span>
     244            <ul class="accordion-sub-container control-panel-content">
     245                <li class="accordion-section control-section<?php if ( empty( $this->description ) ) echo ' cannot-expand'; ?>">
     246                    <div class="accordion-section-title" tabindex="0">
     247                        <span class="preview-notice"><?php
     248                            /* translators: %s is the panel title in the Customize/Live Preview pane */
     249                            echo sprintf( 'You are customizing %s', '<strong class="panel-title">' . esc_html( $this->title ) . '</strong>' );
     250                        ?></span>
     251                    </div>
     252                    <?php if ( ! empty( $this->description ) ) : ?>
     253                        <div class="accordion-section-content description">
     254                            <?php echo $this->description; ?>
     255                        </div>
     256                    <?php endif; ?>
     257                </li>
     258                <?php
     259                foreach ( $this->sections as $section ) {
     260                    $section->maybe_render();
     261                }
     262                ?>
     263            </ul>
     264        </li>
     265        <?php
     266    }
     267}
  • trunk/src/wp-includes/class-wp-customize-widgets.php

    r28143 r28861  
    434434        }
    435435
     436        $this->manager->add_panel( 'widgets', array(
     437            'title' => __( 'Widgets' ),
     438            'description' => __( 'Widgets are independent sections of content that can be placed into widgetized areas provided by your theme (commonly called sidebars).' ),
     439        ) );
     440
    436441        foreach ( $sidebars_widgets as $sidebar_id => $sidebar_widget_ids ) {
    437442            if ( empty( $sidebar_widget_ids ) ) {
     
    459464
    460465                    $section_args = array(
    461                         /* translators: %s: sidebar name */
    462                         'title' => sprintf( __( 'Widgets: %s' ), $GLOBALS['wp_registered_sidebars'][$sidebar_id]['name'] ),
    463                         'description' => $GLOBALS['wp_registered_sidebars'][$sidebar_id]['description'],
    464                         'priority' => 1000 + array_search( $sidebar_id, array_keys( $wp_registered_sidebars ) ),
     466                        'title' => $GLOBALS['wp_registered_sidebars'][ $sidebar_id ]['name'],
     467                        'description' => $GLOBALS['wp_registered_sidebars'][ $sidebar_id ]['description'],
     468                        'priority' => array_search( $sidebar_id, array_keys( $wp_registered_sidebars ) ),
     469                        'panel' => 'widgets',
    465470                    );
    466471
Note: See TracChangeset for help on using the changeset viewer.