WordPress.org

Make WordPress Core

Ticket #30737: 30737.diff

File 30737.diff, 14.1 KB (added by celloexpressions, 7 years ago)

Implement support for JS templates for sections and panel contents. Note that panels are like controls, with separate templates/logic for containers vs. content, but sections just have containers. The section part of this patch represents how we'd implement container templates for controls and panels in #30741.

  • src/wp-admin/customize.php

     
    184184        <div id="customize-preview" class="wp-full-overlay-main"></div>
    185185        <?php
    186186
    187         // Render control templates.
     187        // Render Panel, Section, and Control templates.
     188        $wp_customize->render_panel_templates();
     189        $wp_customize->render_section_templates();
    188190        $wp_customize->render_control_templates();
    189191
    190192        /**
  • src/wp-admin/js/customize-controls.js

     
    162162                        container.params = {};
    163163                        $.extend( container, options || {} );
    164164                        container.container = $( container.params.content );
     165                        if ( 0 === container.container.length ) {
     166                                container.container = $( container.getContainer() );
     167                        }
    165168
    166169                        container.deferred = {
    167170                                embedded: new $.Deferred()
     
    348351                 * Bring the container into view and then expand this and bring it into view
    349352                 * @param {Object} [params]
    350353                 */
    351                 focus: focus
     354                focus: focus,
     355               
     356                /**
     357                 * To override in a subclass, return the container's container element generated from the template.
     358                 * @abstract
     359                 */
     360                getContainer: function () {
     361                        throw new Error( 'Must override with subclass.' );
     362                }
    352363        });
    353364
    354365        /**
     
    517528                                section.container.removeClass( 'open' );
    518529                                content.slideUp( args.duration, args.completeCallback );
    519530                        }
     531                },
     532
     533                /**
     534                 * Return the section contents, generated from its JS template, if it exists.
     535                 *
     536                 * @since 4.2.0
     537                 */
     538                getContainer: function () {
     539                        var template,
     540                                section = this;
     541
     542                        if ( 0 !== $( '#tmpl-customize-section-' + section.params.type ).length ) {
     543                                template = wp.template( 'customize-section-' + section.params.type );
     544                                if ( template && section.container ) {
     545                                        return template( section.params );
     546                                }
     547                        }
    520548                }
    521549        });
    522550
     
    553581
    554582                        if ( ! panel.container.parent().is( parentContainer ) ) {
    555583                                parentContainer.append( panel.container );
     584                                panel.renderContent();
    556585                        }
    557586                        panel.deferred.embedded.resolve();
    558587                },
     
    575604                                }
    576605                        });
    577606
    578                         meta = panel.container.find( '.panel-meta:first' );
    579 
    580                         meta.find( '> .accordion-section-title' ).on( 'click keydown', function( event ) {
     607                        panel.container.on( 'click keydown', '.panel-meta > .accordion-section-title', function( event ) {
    581608                                if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
    582609                                        return;
    583610                                }
    584611                                event.preventDefault(); // Keep this AFTER the key filter above
    585612
     613                                meta = panel.container.find( '.panel-meta' );
    586614                                if ( meta.hasClass( 'cannot-expand' ) ) {
    587615                                        return;
    588616                                }
     
    704732                                panelTitle.focus();
    705733                                container.scrollTop( 0 );
    706734                        }
     735                },
     736
     737                /**
     738                 * Return the panel container, generated from its JS template, if it exists.
     739                 *
     740                 * @since 4.2.0
     741                 */
     742                getContainer: function () {
     743/*                      var template, // @todo dynamic panel containers
     744                                section = this;
     745
     746                        if ( 0 !== $( '#tmpl-customize-panel-' + section.params.type ).length ) {
     747                                template = wp.template( 'customize-panel-' + section.params.type );
     748                                if ( template && section.container ) {
     749                                        return template( section.params );
     750                                }
     751                        }
     752*/              },
     753
     754                /**
     755                 * Render the panel from its JS template, if it exists.
     756                 *
     757                 * The panel's container must already exist in the DOM.
     758                 *
     759                 * @since 4.2.0
     760                 */
     761                renderContent: function () {
     762                        var template,
     763                                panel = this;
     764
     765                        // Add the content to the container.
     766                        if ( 0 !== $( '#tmpl-customize-panel-' + panel.params.type + '-content' ).length ) {
     767                                template = wp.template( 'customize-panel-' + panel.params.type + '-content' );
     768                                if ( template && panel.container ) {
     769                                        panel.container.find( '.accordion-sub-container' ).append( template( panel.params ) );
     770                                }
     771                        }
    707772                }
    708773        });
    709774
  • src/wp-includes/class-wp-customize-control.php

     
    259259         * @return array Array of parameters passed to the JavaScript.
    260260         */
    261261        public function json() {
     262                if ( ! $this->check_capabilities() ) {
     263                        return;
     264                }
     265
    262266                $this->to_json();
    263267                return $this->json;
    264268        }
     
    515519         * @since 4.1.0
    516520         */
    517521        final public function print_template() {
    518                 ?>
    519                 <script type="text/html" id="tmpl-customize-control-<?php echo $this->type; ?>-content">
    520                         <?php $this->content_template(); ?>
    521                 </script>
    522                 <?php
     522        ?>
     523        <script type="text/html" id="tmpl-customize-control-<?php echo $this->type; ?>-content">
     524                <?php $this->content_template(); ?>
     525        </script>
     526        <?php
    523527        }
    524528
    525529        /**
  • src/wp-includes/class-wp-customize-manager.php

     
    5454        protected $customized;
    5555
    5656        /**
    57          * Controls that may be rendered from JS templates.
     57         * Panel types that may be rendered from JS templates.
    5858         *
     59         * @since 4.2.0
     60         * @access protected
     61         * @var array
     62         */
     63        protected $registered_panel_types = array();
     64
     65        /**
     66         * Section types that may be rendered from JS templates.
     67         *
     68         * @since 4.2.0
     69         * @access protected
     70         * @var array
     71         */
     72        protected $registered_section_types = array();
     73
     74        /**
     75         * Control types that may be rendered from JS templates.
     76         *
    5977         * @since 4.1.0
    6078         * @access protected
    6179         * @var array
     
    759777        }
    760778
    761779        /**
     780         * Register a customize panel type.
     781         *
     782         * Registered types are eligible to be rendered via JS and created dynamically.
     783         *
     784         * @since 4.2.0
     785         * @access public
     786         *
     787         * @param string $panel Name of a custom panel which is a subclass of
     788         *                        {@see WP_Customize_Panel}.
     789         */
     790        public function register_panel_type( $panel ) {
     791                $this->registered_panel_types[] = $panel;
     792        }
     793
     794        /**
     795         * Render JS templates for all registered panel types.
     796         *
     797         * @since 4.2.0
     798         * @access public
     799         */
     800        public function render_panel_templates() {
     801                foreach ( $this->registered_panel_types as $panel_type ) {
     802                        $panel = new $panel_type( $this, 'temp', array() );
     803                        $panel->print_template();
     804                }
     805        }
     806
     807        /**
    762808         * Add a customize section.
    763809         *
    764810         * @since 3.4.0
     
    800846        }
    801847
    802848        /**
     849         * Register a customize section type.
     850         *
     851         * Registered types are eligible to be rendered via JS and created dynamically.
     852         *
     853         * @since 4.2.0
     854         * @access public
     855         *
     856         * @param string $section Name of a custom section which is a subclass of
     857         *                        {@see WP_Customize_Section}.
     858         */
     859        public function register_section_type( $section ) {
     860                $this->registered_section_types[] = $section;
     861        }
     862
     863        /**
     864         * Render JS templates for all registered section types.
     865         *
     866         * @since 4.2.0
     867         * @access public
     868         */
     869        public function render_section_templates() {
     870                foreach ( $this->registered_section_types as $section_type ) {
     871                        $section = new $section_type( $this, 'temp', array() );
     872                        $section->print_template();
     873                }
     874        }
     875
     876        /**
    803877         * Add a customize control.
    804878         *
    805879         * @since 3.4.0
     
    9701044         */
    9711045        public function register_controls() {
    9721046
    973                 /* Control Types (custom control classes) */
     1047                /* Panel, Section, and Control Types */
     1048                $this->register_panel_type( 'WP_Customize_Panel' );
     1049                $this->register_section_type( 'WP_Customize_Section' );
     1050                $this->register_section_type( 'WP_Customize_Sidebar_Section' );
    9741051                $this->register_control_type( 'WP_Customize_Color_Control' );
    9751052                $this->register_control_type( 'WP_Customize_Upload_Control' );
    9761053                $this->register_control_type( 'WP_Customize_Image_Control' );
  • src/wp-includes/class-wp-customize-panel.php

     
    206206         * @return array The array to be exported to the client as JSON.
    207207         */
    208208        public function json() {
    209                 $array = wp_array_slice_assoc( (array) $this, array( 'title', 'description', 'priority', 'type' ) );
     209                if ( ! $this->check_capabilities() ) {
     210                        return;
     211                }
     212
     213                $array = wp_array_slice_assoc( (array) $this, array( 'id', 'title', 'description', 'priority', 'type' ) );
    210214                $array['content'] = $this->get_content();
    211215                $array['active'] = $this->active();
    212216                $array['instanceNumber'] = $this->instance_number;
     
    302306        }
    303307
    304308        /**
    305          * Render the sections that have been added to the panel.
     309         * Render the panel UI in a subclass.
    306310         *
     311         * Panel contents are now rendered in JS by default, see {@see WP_Customize_Panel::print_template()}.
     312         *
    307313         * @since 4.1.0
    308314         * @access protected
    309315         */
    310         protected function render_content() {
     316        protected function render_content() {}
     317
     318        /**
     319         * Render the panel's JS template.
     320         *
     321         * This function is only run for panel types that have been registered with
     322         * {@see WP_Customize_Manager::register_panel_type()}.
     323         *
     324         * In the future, this will also print the template for the panel's container
     325         * and be override-able.
     326         *
     327         * @since 4.2.0
     328         */
     329        final public function print_template() {
     330        ?>
     331        <script type="text/html" id="tmpl-customize-panel-<?php echo $this->type; ?>-content">
     332                        <?php $this->content_template(); ?>
     333        </script>
     334        <?php
     335        }
     336
     337        /**
     338         * An Underscore (JS) template for this panel's content (but not its container).
     339         *
     340         * Class variables for this panel class are available in the `data` JS object;
     341         * export custom variables by overriding {@see WP_Customize_Panel::json()}.
     342         *
     343         * @see WP_Customize_Panel::print_template()
     344         *
     345         * @since 4.2.0
     346         */
     347        protected function content_template() {
    311348                ?>
    312                 <li class="panel-meta accordion-section control-section<?php if ( empty( $this->description ) ) { echo ' cannot-expand'; } ?>">
     349                <li class="panel-meta accordion-section control-section<# if ( ! data.description ) { #> cannot-expand<# } #>">
    313350                        <div class="accordion-section-title" tabindex="0">
    314351                                <span class="preview-notice"><?php
    315352                                        /* translators: %s is the site/panel title in the Customizer */
    316                                         echo sprintf( __( 'You are customizing %s' ), '<strong class="panel-title">' . esc_html( $this->title ) . '</strong>' );
     353                                        echo sprintf( __( 'You are customizing %s' ), '<strong class="panel-title">{{ data.title }}</strong>' );
    317354                                ?></span>
    318355                        </div>
    319                         <?php if ( ! empty( $this->description ) ) : ?>
     356                        <# if ( data.description ) { #>
    320357                                <div class="accordion-section-content description">
    321                                         <?php echo $this->description; ?>
     358                                        {{{ data.description }}}
    322359                                </div>
    323                         <?php endif; ?>
     360                        <# } #>
    324361                </li>
    325362                <?php
    326363        }
  • src/wp-includes/class-wp-customize-section.php

     
    215215         * @return array The array to be exported to the client as JSON.
    216216         */
    217217        public function json() {
    218                 $array = wp_array_slice_assoc( (array) $this, array( 'title', 'description', 'priority', 'panel', 'type' ) );
     218                if ( ! $this->check_capabilities() ) {
     219                        return;
     220                }
     221
     222                $array = wp_array_slice_assoc( (array) $this, array( 'id', 'title', 'description', 'priority', 'panel', 'type' ) );
    219223                $array['content'] = $this->get_content();
    220224                $array['active'] = $this->active();
    221225                $array['instanceNumber'] = $this->instance_number;
     
    243247        }
    244248
    245249        /**
    246          * Get the section's content template for insertion into the Customizer pane.
     250         * Get the section's content for insertion into the Customizer pane.
    247251         *
    248252         * @since 4.1.0
    249253         *
     
    289293        }
    290294
    291295        /**
    292          * Render the section, and the controls that have been added to it.
     296         * Render the section UI in a subclass.
    293297         *
     298         * Sections are now rendered in JS by default, see {@see WP_Customize_Section::print_template()}.
     299         *
    294300         * @since 3.4.0
    295301         */
    296         protected function render() {
    297                 $classes = 'accordion-section control-section control-section-' . $this->type;
     302        protected function render() {}
     303
     304        /**
     305         * Render the section's JS template.
     306         *
     307         * This function is only run for section types that have been registered with
     308         * {@see WP_Customize_Manager::register_section_type()}.
     309         *
     310         * In the future, this will also print the template for the control's container
     311         * element and be override-able.
     312         *
     313         * @since 4.2.0
     314         */
     315        public function print_template() {
     316        ?>
     317        <script type="text/html" id="tmpl-customize-section-<?php echo $this->type; ?>">
     318                        <?php $this->render_template(); ?>
     319        </script>
     320        <?php
     321        }
     322
     323        /**
     324         * An Underscore (JS) template for rendering this section.
     325         *
     326         * Class variables for this section class are available in the `data` JS object;
     327         * export custom variables by overriding {@see WP_Customize_Section::json()}.
     328         *
     329         * @see WP_Customize_Section::print_template()
     330         *
     331         * @since 4.2.0
     332         */
     333        protected function render_template() {
    298334                ?>
    299                 <li id="accordion-section-<?php echo esc_attr( $this->id ); ?>" class="<?php echo esc_attr( $classes ); ?>">
     335                <li id="accordion-section-{{ data.id }}" class="accordion-section control-section control-section-{{ data.type }}">
    300336                        <h3 class="accordion-section-title" tabindex="0">
    301                                 <?php echo esc_html( $this->title ); ?>
     337                                {{ data.title }}
    302338                                <span class="screen-reader-text"><?php _e( 'Press return or enter to expand' ); ?></span>
    303339                        </h3>
    304340                        <ul class="accordion-section-content">
    305                                 <?php if ( ! empty( $this->description ) ) : ?>
     341                                <# if ( data.description ) { #>
    306342                                        <li class="customize-section-description-container">
    307                                                 <p class="description customize-section-description"><?php echo $this->description; ?></p>
     343                                                <p class="description customize-section-description">{{{ data.description }}}</p>
    308344                                        </li>
    309                                 <?php endif; ?>
     345                                <# } #>
    310346                        </ul>
    311347                </li>
    312348                <?php