Make WordPress Core

Changeset 38648


Ignore:
Timestamp:
09/23/2016 10:22:09 PM (8 years ago)
Author:
westonruter
Message:

Customize: Re-architect and harden panel/section UI logic.

Removes contents for sections and panels from being logically nested (in the DOM) in order to eliminate many issues related to using margin-top hacks. The element containing the link to expand the content element for panels and sections is now a sibling element to its content element: the content is removed from being nested at initialization. The content element is now available in a contentContainer property whereas the head element (containing the link to open the construct) is in a headContainer property. The existing container property is now a jQuery collection that contains both of these elements. Since the head element is no longer in an ancestor element to the content element, the aria-owns property is now used to maintain the relationship between the headContainer and the contentContainer. These changes are also accompanied by an improvement to the animation performance for the sliding panes.

Props delawski, celloexpressions.
Fixes #34391.
Fixes #34344.
Fixes #35947.

Location:
trunk
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/css/common.css

    r38640 r38648  
    33683368}
    33693369
    3370 .control-section .accordion-section-title {
     3370.control-section .accordion-section-title,
     3371.customize-pane-child .accordion-section-title {
    33713372    border-left: none;
    33723373    border-right: none;
     
    33763377}
    33773378
    3378 .control-section .accordion-section-title:after {
     3379.control-section .accordion-section-title:after,
     3380.customize-pane-child .accordion-section-title:after {
    33793381    top: 11px;
    33803382}
  • trunk/src/wp-admin/css/customize-controls.css

    r38602 r38648  
    7878}
    7979
    80 #customize-controls .control-section .customize-section-title h3,
    81 #customize-controls .control-section h3.customize-section-title,
     80#customize-controls .customize-pane-child .customize-section-title h3,
     81#customize-controls .customize-pane-child h3.customize-section-title,
    8282#customize-controls .customize-info .panel-title {
    8383    font-size: 20px;
     
    230230}
    231231
     232#customize-info,
     233#customize-theme-controls .customize-pane-parent,
     234#customize-theme-controls .customize-pane-child {
     235    overflow: visible;
     236    width: 100%;
     237    margin: 0;
     238    padding: 0;
     239    -webkit-box-sizing: border-box;
     240    -moz-box-sizing: border-box;
     241    box-sizing: border-box;
     242    -webkit-transition: 0.18s -webkit-transform cubic-bezier(0.645, 0.045, 0.355, 1);
     243    transition: 0.18s -webkit-transform cubic-bezier(0.645, 0.045, 0.355, 1);
     244    transition: 0.18s transform cubic-bezier(0.645, 0.045, 0.355, 1);
     245    transition: 0.18s transform cubic-bezier(0.645, 0.045, 0.355, 1), 0.18s -webkit-transform cubic-bezier(0.645, 0.045, 0.355, 1); /* easeInOutCubic */
     246}
     247
     248#customize-info,
     249#customize-theme-controls .customize-pane-parent {
     250    position: relative;
     251    visibility: visible;
     252    height: auto;
     253    max-height: none;
     254    overflow: auto;
     255    -webkit-transform: none;
     256    -ms-transform: none;
     257    transform: none;
     258}
     259
     260#customize-theme-controls .customize-pane-child {
     261    position: absolute;
     262    top: 0;
     263    left: 0;
     264    visibility: hidden;
     265    height: 0;
     266    max-height: none;
     267    overflow: hidden;
     268    -webkit-transform: translateX(100%);
     269    -ms-transform: translateX(100%);
     270    transform: translateX(100%);
     271}
     272
     273#customize-theme-controls .customize-pane-child.open,
     274#customize-theme-controls .customize-pane-child.current-panel,
     275#customize-theme-controls .customize-themes-panel.customize-pane-child.current-panel {
     276    -webkit-transform: none;
     277    -ms-transform: none;
     278    transform: none;
     279}
     280
     281#customize-theme-controls .customize-themes-panel.customize-pane-child,
     282.section-open #customize-theme-controls .customize-pane-parent,
     283.in-sub-panel #customize-theme-controls .customize-pane-parent,
     284.section-open #customize-info,
     285.in-sub-panel #customize-info,
     286.in-sub-panel.section-open #customize-theme-controls .customize-pane-child.current-panel,
     287.in-themes-panel #customize-theme-controls .customize-pane-parent,
     288.in-themes-panel #customize-info {
     289    visibility: hidden;
     290    height: 0;
     291    overflow: hidden;
     292    -webkit-transform: translateX(-100%);
     293    -ms-transform: translateX(-100%);
     294    transform: translateX(-100%);
     295}
     296
     297.section-open #customize-theme-controls .customize-pane-parent.busy,
     298.in-sub-panel #customize-theme-controls .customize-pane-parent.busy,
     299.in-themes-panel #customize-theme-controls .customize-pane-parent.busy,
     300.section-open #customize-info.busy,
     301.in-sub-panel #customize-info.busy,
     302.in-themes-panel #customize-info.busy,
     303.busy.section-open.in-sub-panel #customize-theme-controls .customize-pane-child.current-panel,
     304#customize-theme-controls .customize-pane-child.open,
     305#customize-theme-controls .customize-pane-child.current-panel,
     306#customize-theme-controls .customize-pane-child.busy {
     307    visibility: visible;
     308    height: auto;
     309    overflow: auto;
     310}
     311
     312.in-themes-panel #customize-theme-controls .customize-pane-parent,
     313.in-themes-panel #customize-info {
     314    -webkit-transform: translateX(100%);
     315    -ms-transform: translateX(100%);
     316    transform: translateX(100%);
     317}
     318
     319#customize-theme-controls .customize-pane-child.accordion-section-content,
     320#customize-theme-controls .customize-pane-child.accordion-sub-container {
     321    display: block;
     322    overflow-x: hidden;
     323}
     324
     325#customize-theme-controls .customize-pane-child.accordion-section-content {
     326    padding: 12px;
     327}
     328
    232329.customize-section-description-container {
    233330    margin-bottom: 15px;
     
    269366}
    270367
    271 #customize-theme-controls {
    272     position: relative;
    273     left: 0;
    274     -webkit-transition: .18s left ease-in-out;
    275     transition: .18s left ease-in-out;
    276 }
    277 
    278 .ios #customize-theme-controls {
    279     -webkit-transition: left 0s;
    280     transition: left 0s;
    281 }
    282 
    283 .section-open #customize-info,
    284 .section-open #customize-theme-controls {
    285     left: -100%;
    286 }
    287 
    288368.accordion-sub-container.control-panel-content {
    289369    display: none;
    290370    position: absolute;
    291     left: 100%;
    292371    top: 0;
    293372    width: 100%;
    294     -webkit-transition: left ease-in-out .18s;
    295     transition: left ease-in-out .18s;
    296 }
    297 
    298 .ios .accordion-sub-container.control-panel-content {
    299     -webkit-transition: left 0s;
    300     transition: left 0s;
    301 }
    302 
    303 .accordion-sub-container.control-panel-content.animating {
     373}
     374
     375.accordion-sub-container.control-panel-content.busy {
    304376    display: block;
    305377}
     
    344416    box-shadow: none;
    345417    cursor: pointer;
    346     -webkit-transition: left .18s ease-in-out, color .1s ease-in-out, background .1s ease-in-out;
    347     transition: left .18s ease-in-out, color .1s ease-in-out, background .1s ease-in-out;
     418    -webkit-transition: color .1s ease-in-out, background .1s ease-in-out;
     419    transition: color .1s ease-in-out, background .1s ease-in-out;
    348420}
    349421
    350422.customize-section-back {
    351423    height: 74px;
    352 }
    353 
    354 .ios .customize-panel-back,
    355 .ios .customize-section-back {
    356     -webkit-transition: left 0s;
    357     transition: left 0s;
    358424}
    359425
     
    422488.in-sub-panel .wp-full-overlay-sidebar .wp-full-overlay-header {
    423489    padding-left: 62px;
    424 }
    425 
    426 #customize-info,
    427 #customize-theme-controls > ul > .accordion-section {
    428     position: relative;
    429     left: 0;
    430     -webkit-transition: left ease-in-out .18s;
    431     transition: left ease-in-out .18s;
    432 }
    433 
    434 .ios #customize-info,
    435 .ios #customize-theme-controls > ul > .accordion-section {
    436     -webkit-transition: left 0s;
    437     transition: left 0s;
    438 }
    439 
    440 .in-sub-panel #customize-info,
    441 .in-sub-panel #customize-theme-controls > ul > .accordion-section {
    442     left: -100%;
    443     width: 100%;
    444 }
    445 
    446 .in-sub-panel #customize-theme-controls .accordion-section.current-panel {
    447     width: 100%;
    448 }
    449 
    450 #customize-theme-controls .control-section.current-panel {
    451     padding: 0;
    452 }
    453 
    454 #customize-theme-controls .control-section > h3.accordion-section-title {
    455     position: relative;
    456     left: 0;
    457 }
    458 
    459 #customize-theme-controls .control-section.current-panel > h3.accordion-section-title {
    460     left: -354px;
    461     -webkit-transition: left ease-in-out .18s;
    462     transition: left ease-in-out .18s;
    463 }
    464 
    465 .ios #customize-theme-controls .control-section.current-panel > h3.accordion-section-title {
    466     -webkit-transition: left 0s;
    467     transition: left 0s;
    468 }
    469 
    470 .wp-full-overlay.section-open #customize-controls .wp-full-overlay-sidebar-content {
    471     visibility: hidden;
    472     overflow-y: hidden;
    473 }
    474 
    475 .wp-full-overlay.section-open .wp-full-overlay-sidebar-content .accordion-section.open {
    476     visibility: visible;
    477 }
    478 
    479 .wp-full-overlay.section-open .wp-full-overlay-sidebar-content .accordion-section.open .accordion-section-content {
    480     overflow-y: auto;
    481490}
    482491
     
    10061015#customize-theme-controls .control-section-themes > .accordion-section-title:hover, /* Not a focusable element. */
    10071016#customize-theme-controls .control-section-themes > .accordion-section-title {
    1008     margin: 15px 0;
    1009 }
    1010 
    1011 .customize-themes-panel .accordion-section-title {
     1017    margin: 0 0 15px;
     1018}
     1019
     1020#customize-controls .customize-themes-panel .accordion-section-title {
    10121021    margin: 15px -8px;
    10131022}
    10141023
    1015 .control-section-themes .accordion-section-title {
     1024#customize-controls .control-section-themes .accordion-section-title,
     1025#customize-controls .customize-themes-panel .accordion-section-title {
    10161026    padding-right: 100px; /* Space for the button */
    10171027}
    10181028
    1019 .control-section-themes .accordion-section-title span.customize-action,
     1029#customize-controls .control-section-themes .accordion-section-title span.customize-action,
    10201030#customize-controls .customize-section-title span.customize-action {
    10211031    font-size: 13px;
     
    10241034}
    10251035
    1026 .control-section-themes .accordion-section-title .change-theme,
    1027 .control-section-themes .accordion-section-title .customize-theme {
     1036#customize-controls .control-section-themes .accordion-section-title .change-theme,
     1037#customize-controls .customize-themes-panel .accordion-section-title .customize-theme {
    10281038    position: absolute;
    10291039    right: 10px;
     
    10331043}
    10341044
    1035 .control-section-themes .accordion-section-title:before {
     1045#customize-controls .control-section-themes .accordion-section-title:before {
    10361046    display: none;
    10371047}
    10381048
    1039 .customize-themes-panel {
    1040     display: none;
     1049#customize-controls .customize-themes-panel {
    10411050    padding: 0 8px;
    10421051    background: #f1f1f1;
     
    10461055}
    10471056
    1048 .customize-themes-panel .accordion-section-title:first-child {
     1057#customize-controls .customize-themes-panel .accordion-section-title:first-child {
    10491058    margin-top: 0;
    10501059}
     
    10551064}
    10561065
    1057 .customize-themes-panel > h2 {
     1066#customize-controls .customize-themes-panel > h2 {
    10581067    padding: 15px 8px 0 8px;
    1059 }
    1060 
    1061 .control-section.open .customize-themes-panel {
    1062     display: block;
    10631068}
    10641069
     
    11081113}
    11091114
    1110 #accordion-section-themes .accordion-section-title:after {
     1115.control-section-themes .accordion-section-title:after,
     1116.customize-themes-panel .accordion-section-title:after {
    11111117    display: none;
    11121118}
    11131119
    1114 #customize-theme-controls .control-section-themes.current-panel > h3.accordion-section-title {
    1115     left: 0;
    1116 }
    1117 
    11181120.customize-themes-panel.control-panel-content {
    1119     position: absolute;
    1120     left: -100%;
    1121     top: 0;
    1122     width: 100%;
    11231121    border-top: 1px solid #ddd;
    1124 }
    1125 
    1126 .in-themes-panel #customize-info,
    1127 .in-themes-panel #customize-theme-controls > ul > .accordion-section {
    1128     left: 100%;
    11291122}
    11301123
     
    11601153.wp-customizer .theme-overlay .theme-actions {
    11611154    text-align: right; /* Because there's only one action, match the pattern of media modals and right-align the action. */
    1162 }
    1163 
    1164 .modal-open .in-themes-panel #customize-controls .wp-full-overlay-sidebar-content {
    1165     overflow: visible; /* Prevent the top-level Customizer controls from becoming visible when elements on the right of the details modal are focused. */
    11661155}
    11671156
  • trunk/src/wp-admin/css/customize-nav-menus.css

    r38642 r38648  
    382382.reordering .menu-item-depth-11 > .menu-item-bar { margin-right: 165px; }
    383383
    384 .control-section-nav_menu .menu .menu-item-edit-active {
     384.control-section-nav_menu.menu .menu-item-edit-active {
    385385    margin-left: 0;
    386386}
    387387
    388 .control-section-nav_menu .menu .menu-item-edit-active .menu-item-bar {
     388.control-section-nav_menu.menu .menu-item-edit-active .menu-item-bar {
    389389    margin-right: 0;
    390390}
    391391
    392 .control-section-nav_menu .menu .sortable-placeholder {
     392.control-section-nav_menu.menu .sortable-placeholder {
    393393    margin-top: 0;
    394394    margin-bottom: 1px;
     
    404404}
    405405
    406 .control-section-nav_menu .menu ul.menu-item-transport .menu-item-bar {
     406.control-section-nav_menu.menu ul.menu-item-transport .menu-item-bar {
    407407    margin-top: 0;
    408408}
  • trunk/src/wp-admin/customize.php

    r37914 r38648  
    143143
    144144            <div id="customize-theme-controls">
    145                 <ul><?php // Panels and sections are managed here via JavaScript ?></ul>
     145                <ul class="customize-pane-parent"><?php // Panels and sections are managed here via JavaScript ?></ul>
    146146            </div>
    147147        </div>
  • trunk/src/wp-admin/js/customize-controls.js

    r38520 r38648  
    11/* global _wpCustomizeHeader, _wpCustomizeBackground, _wpMediaViewsL10n, MediaElementPlayer */
    22(function( exports, $ ){
    3     var Container, focus, api = wp.customize;
     3    var Container, focus, normalizedTransitionendEventName, api = wp.customize;
    44
    55    /**
     
    102102        focus = function () {
    103103            var focusContainer;
    104             if ( construct.extended( api.Panel ) && construct.expanded && construct.expanded() ) {
    105                 focusContainer = construct.container.find( 'ul.control-panel-content' );
    106             } else if ( construct.extended( api.Section ) && construct.expanded && construct.expanded() ) {
    107                 focusContainer = construct.container.find( 'ul.accordion-section-content' );
     104            if ( ( construct.extended( api.Panel ) || construct.extended( api.Section ) ) && construct.expanded && construct.expanded() ) {
     105                focusContainer = construct.contentContainer;
    108106            } else {
    109107                focusContainer = construct.container;
     
    187185        return equal;
    188186    };
     187
     188    /**
     189     * Return browser supported `transitionend` event name.
     190     *
     191     * @since 4.7.0
     192     *
     193     * @returns {string|null} Normalized `transitionend` event name or null if CSS transitions are not supported.
     194     */
     195    normalizedTransitionendEventName = (function () {
     196        var el, transitions, prop;
     197        el = document.createElement( 'div' );
     198        transitions = {
     199            'transition'      : 'transitionend',
     200            'OTransition'     : 'oTransitionEnd',
     201            'MozTransition'   : 'transitionend',
     202            'WebkitTransition': 'webkitTransitionEnd'
     203        };
     204        prop = _.find( _.keys( transitions ), function( prop ) {
     205            return ! _.isUndefined( el.style[ prop ] );
     206        } );
     207        if ( prop ) {
     208            return transitions[ prop ];
     209        } else {
     210            return null;
     211        }
     212    })();
    189213
    190214    /**
     
    239263                container.container = $( container.getContainer() );
    240264            }
     265            container.headContainer = container.container;
     266            container.contentContainer = container.getContent();
     267            container.container = container.container.add( container.contentContainer );
    241268
    242269            container.deferred = {
     
    326353         */
    327354        onChangeActive: function( active, args ) {
    328             var duration, construct = this, expandedOtherPanel;
     355            var construct = this,
     356                headContainer = construct.headContainer,
     357                duration, expandedOtherPanel;
     358
    329359            if ( args.unchanged ) {
    330360                if ( args.completeCallback ) {
     
    353383            }
    354384
    355             if ( ! $.contains( document, construct.container[0] ) ) {
     385            if ( ! $.contains( document, headContainer ) ) {
    356386                // jQuery.fn.slideUp is not hiding an element if it is not in the DOM
    357                 construct.container.toggle( active );
     387                headContainer.toggle( active );
    358388                if ( args.completeCallback ) {
    359389                    args.completeCallback();
    360390                }
    361391            } else if ( active ) {
    362                 construct.container.stop( true, true ).slideDown( duration, args.completeCallback );
     392                headContainer.stop( true, true ).slideDown( duration, args.completeCallback );
    363393            } else {
    364394                if ( construct.expanded() ) {
     
    366396                        duration: duration,
    367397                        completeCallback: function() {
    368                             construct.container.stop( true, true ).slideUp( duration, args.completeCallback );
     398                            headContainer.stop( true, true ).slideUp( duration, args.completeCallback );
    369399                        }
    370400                    });
    371401                } else {
    372                     construct.container.stop( true, true ).slideUp( duration, args.completeCallback );
    373                 }
    374             }
    375 
    376             // Recalculate the margin-top immediately, not waiting for debounced reflow, to prevent momentary (100ms) vertical jiggle.
    377             if ( expandedOtherPanel ) {
    378                 expandedOtherPanel._recalculateTopMargin();
     402                    headContainer.stop( true, true ).slideUp( duration, args.completeCallback );
     403                }
    379404            }
    380405        },
     
    484509
    485510        /**
     511         * Animate container state change if transitions are supported by the browser.
     512         *
     513         * @since 4.7.0
     514         *
     515         * @param {function} completeCallback Function to be called after transition is completed.
     516         * @returns {void}
     517         * @private
     518         */
     519        _animateChangeExpanded: function( completeCallback ) {
     520            // Return if CSS transitions are not supported.
     521            if ( ! normalizedTransitionendEventName ) {
     522                if ( completeCallback ) {
     523                    completeCallback();
     524                }
     525                return;
     526            }
     527
     528            var construct = this,
     529                content = construct.contentContainer,
     530                overlay = content.closest( '.wp-full-overlay' ),
     531                elements, transitionEndCallback;
     532
     533            // Determine set of elements that are affected by the animation.
     534            elements = overlay.add( content );
     535            if ( _.isUndefined( construct.panel ) || '' === construct.panel() ) {
     536                elements = elements.add( '#customize-info, .customize-pane-parent' );
     537            }
     538
     539            // Handle `transitionEnd` event.
     540            transitionEndCallback = function( e ) {
     541                if ( 2 !== e.eventPhase || ! $( e.target ).is( content ) ) {
     542                    return;
     543                }
     544                content.off( normalizedTransitionendEventName, transitionEndCallback );
     545                elements.removeClass( 'busy' );
     546                if ( completeCallback ) {
     547                    completeCallback();
     548                }
     549            };
     550            content.on( normalizedTransitionendEventName, transitionEndCallback );
     551            elements.addClass( 'busy' );
     552
     553            // Prevent screen flicker when pane has been scrolled before expanding.
     554            _.defer( function() {
     555                var container = content.closest( '.wp-full-overlay-sidebar-content' ),
     556                    currentScrollTop = container.scrollTop(),
     557                    previousScrollTop = content.data( 'previous-scrollTop' ) || 0,
     558                    expanded = construct.expanded();
     559
     560                if ( expanded && 0 < currentScrollTop ) {
     561                    content.css( 'top', currentScrollTop + 'px' );
     562                    content.data( 'previous-scrollTop', currentScrollTop );
     563                } else if ( ! expanded && 0 < currentScrollTop + previousScrollTop ) {
     564                    content.css( 'top', previousScrollTop - currentScrollTop + 'px' );
     565                    container.scrollTop( previousScrollTop );
     566                }
     567            } );
     568        },
     569
     570        /**
    486571         * Bring the container into view and then expand this and bring it into view
    487572         * @param {Object} [params]
     
    508593
    509594            return '<li></li>';
     595        },
     596
     597        /**
     598         * Find content element which is displayed when the section is expanded.
     599         *
     600         * After a construct is initialized, the return value will be available via the `contentContainer` property.
     601         * By default the element will be related it to the parent container with `aria-owns` and detached.
     602         * Custom panels and sections (such as the `NewMenuSection`) that do not have a sliding pane should
     603         * just return the content element without needing to add the `aria-owns` element or detach it from
     604         * the container. Such non-sliding pane custom sections also need to override the `onChangeExpanded`
     605         * method to handle animating the panel/section into and out of view.
     606         *
     607         * @since 4.7.0
     608         *
     609         * @returns {jQuery} Detached content element.
     610         */
     611        getContent: function() {
     612            var construct = this,
     613                container = construct.container,
     614                content = container.find( '.accordion-section-content, .control-panel-content' ).first(),
     615                contentId = 'sub-' + container.attr( 'id' ),
     616                ownedElements = contentId,
     617                alreadyOwnedElements = container.attr( 'aria-owns' );
     618
     619            if ( alreadyOwnedElements ) {
     620                ownedElements = ownedElements + ' ' + alreadyOwnedElements;
     621            }
     622            container.attr( 'aria-owns', ownedElements );
     623
     624            return content.detach().attr( {
     625                'id': contentId,
     626                'class': 'customize-pane-child ' + content.attr( 'class' ) + ' ' + container.attr( 'class' )
     627            } );
    510628        }
    511629    });
     
    553671            section.panel = new api.Value();
    554672            section.panel.bind( function ( id ) {
    555                 $( section.container ).toggleClass( 'control-subsection', !! id );
     673                $( section.headContainer ).toggleClass( 'control-subsection', !! id );
    556674            });
    557675            section.panel.set( section.params.panel || '' );
     
    570688         */
    571689        embed: function () {
    572             var section = this, inject;
     690            var inject,
     691                section = this,
     692                container = $( '#customize-theme-controls' );
    573693
    574694            // Watch for changes to the panel state
     
    580700                        // The panel has been registered, wait for it to become ready/initialized
    581701                        panel.deferred.embedded.done( function () {
    582                             parentContainer = panel.container.find( 'ul:first' );
    583                             if ( ! section.container.parent().is( parentContainer ) ) {
    584                                 parentContainer.append( section.container );
     702                            parentContainer = panel.contentContainer;
     703                            if ( ! section.headContainer.parent().is( parentContainer ) ) {
     704                                parentContainer.append( section.headContainer );
     705                            }
     706                            if ( ! section.contentContainer.parent().is( section.headContainer ) ) {
     707                                container.append( section.contentContainer );
    585708                            }
    586709                            section.deferred.embedded.resolve();
     
    589712                } else {
    590713                    // There is no panel, so embed the section in the root of the customizer
    591                     parentContainer = $( '#customize-theme-controls' ).children( 'ul' ); // @todo This should be defined elsewhere, and to be configurable
    592                     if ( ! section.container.parent().is( parentContainer ) ) {
    593                         parentContainer.append( section.container );
     714                    parentContainer = $( '.customize-pane-parent' ); // @todo This should be defined elsewhere, and to be configurable
     715                    if ( ! section.headContainer.parent().is( parentContainer ) ) {
     716                        parentContainer.append( section.headContainer );
     717                    }
     718                    if ( ! section.contentContainer.parent().is( section.headContainer ) ) {
     719                        container.append( section.contentContainer );
    594720                    }
    595721                    section.deferred.embedded.resolve();
     
    598724            section.panel.bind( inject );
    599725            inject( section.panel.get() ); // Since a section may never get a panel, assume that it won't ever get one
    600 
    601             section.deferred.embedded.done(function() {
    602                 // Fix the top margin after reflow.
    603                 api.bind( 'pane-contents-reflowed', _.debounce( function() {
    604                     section._recalculateTopMargin();
    605                 }, 100 ) );
    606             });
    607726        },
    608727
     
    670789        onChangeExpanded: function ( expanded, args ) {
    671790            var section = this,
    672                 container = section.container.closest( '.wp-full-overlay-sidebar-content' ),
    673                 content = section.container.find( '.accordion-section-content' ),
    674                 overlay = section.container.closest( '.wp-full-overlay' ),
    675                 backBtn = section.container.find( '.customize-section-back' ),
    676                 sectionTitle = section.container.find( '.accordion-section-title' ).first(),
    677                 headerActionsHeight = $( '#customize-header-actions' ).height(),
    678                 resizeContentHeight, expand, position, scroll;
    679 
    680             if ( expanded && ! section.container.hasClass( 'open' ) ) {
     791                container = section.headContainer.closest( '.wp-full-overlay-sidebar-content' ),
     792                content = section.contentContainer,
     793                overlay = section.headContainer.closest( '.wp-full-overlay' ),
     794                backBtn = content.find( '.customize-section-back' ),
     795                sectionTitle = section.headContainer.find( '.accordion-section-title' ).first(),
     796                expand;
     797
     798            if ( expanded && ! content.hasClass( 'open' ) ) {
    681799
    682800                if ( args.unchanged ) {
    683801                    expand = args.completeCallback;
    684802                } else {
    685                     container.scrollTop( 0 );
    686                     resizeContentHeight = function() {
    687                         var matchMedia, offset;
    688                         matchMedia = window.matchMedia || window.msMatchMedia;
    689                         offset = 90; // 45px for customize header actions + 45px for footer actions.
    690 
    691                         // No footer on small screens.
    692                         if ( matchMedia && matchMedia( '(max-width: 640px)' ).matches ) {
    693                             offset = 45;
    694                         }
    695                         content.css( 'height', ( window.innerHeight - offset ) );
    696                     };
    697                     expand = function() {
    698                         section.container.addClass( 'open' );
     803                    expand = $.proxy( function() {
     804                        section._animateChangeExpanded( function() {
     805                            sectionTitle.attr( 'tabindex', '-1' );
     806                            backBtn.attr( 'tabindex', '0' );
     807
     808                            backBtn.focus();
     809                            content.css( 'top', '' );
     810                            container.scrollTop( 0 );
     811
     812                            if ( args.completeCallback ) {
     813                                args.completeCallback();
     814                            }
     815                        } );
     816
     817                        content.addClass( 'open' );
    699818                        overlay.addClass( 'section-open' );
    700                         position = content.offset().top;
    701                         scroll = container.scrollTop();
    702                         content.css( 'margin-top', ( headerActionsHeight - position - scroll ) );
    703                         resizeContentHeight();
    704                         sectionTitle.attr( 'tabindex', '-1' );
    705                         backBtn.attr( 'tabindex', '0' );
    706                         backBtn.focus();
    707                         if ( args.completeCallback ) {
    708                             args.completeCallback();
    709                         }
    710 
    711                         // Fix the height after browser resize.
    712                         $( window ).on( 'resize.customizer-section', _.debounce( resizeContentHeight, 100 ) );
    713 
    714                         setTimeout( _.bind( section._recalculateTopMargin, section ), 0 );
    715                     };
     819                    }, this );
    716820                }
    717821
     
    736840                }
    737841
    738             } else if ( ! expanded && section.container.hasClass( 'open' ) ) {
    739                 section.container.removeClass( 'open' );
     842            } else if ( ! expanded && content.hasClass( 'open' ) ) {
     843                section._animateChangeExpanded( function() {
     844                    backBtn.attr( 'tabindex', '-1' );
     845                    sectionTitle.attr( 'tabindex', '0' );
     846
     847                    sectionTitle.focus();
     848                    content.css( 'top', '' );
     849
     850                    if ( args.completeCallback ) {
     851                        args.completeCallback();
     852                    }
     853                } );
     854
     855                content.removeClass( 'open' );
    740856                overlay.removeClass( 'section-open' );
    741                 content.css( 'margin-top', '' );
    742                 container.scrollTop( 0 );
    743                 backBtn.attr( 'tabindex', '-1' );
    744                 sectionTitle.attr( 'tabindex', '0' );
    745                 sectionTitle.focus();
    746                 if ( args.completeCallback ) {
    747                     args.completeCallback();
    748                 }
    749                 $( window ).off( 'resize.customizer-section' );
     857
    750858            } else {
    751859                if ( args.completeCallback ) {
    752860                    args.completeCallback();
    753861                }
    754             }
    755         },
    756 
    757         /**
    758          * Recalculate the top margin.
    759          *
    760          * @since 4.4.0
    761          * @private
    762          */
    763         _recalculateTopMargin: function() {
    764             var section = this, content, offset, headerActionsHeight;
    765             content = section.container.find( '.accordion-section-content' );
    766             if ( 0 === content.length ) {
    767                 return;
    768             }
    769             headerActionsHeight = $( '#customize-header-actions' ).height();
    770             offset = ( content.offset().top - headerActionsHeight );
    771             if ( 0 < offset ) {
    772                 content.css( 'margin-top', ( parseInt( content.css( 'margin-top' ), 10 ) - offset ) );
    773862            }
    774863        }
     
    9491038
    9501039            // Note: there is a second argument 'args' passed
    951             var position, scroll,
    952                 panel = this,
    953                 section = panel.container.closest( '.accordion-section' ),
     1040            var panel = this,
     1041                section = panel.contentContainer,
    9541042                overlay = section.closest( '.wp-full-overlay' ),
    9551043                container = section.closest( '.wp-full-overlay-sidebar-content' ),
    956                 siblings = container.find( '.open' ),
    9571044                customizeBtn = section.find( '.customize-theme' ),
    958                 changeBtn = section.find( '.change-theme' ),
    959                 content = section.find( '.control-panel-content' );
    960 
    961             if ( expanded ) {
    962 
     1045                changeBtn = panel.headContainer.find( '.change-theme' );
     1046
     1047            if ( expanded && ! section.hasClass( 'current-panel' ) ) {
    9631048                // Collapse any sibling sections/panels
    9641049                api.section.each( function ( otherSection ) {
     
    9711056                });
    9721057
    973                 content.show( 0, function() {
    974                     position = content.offset().top;
    975                     scroll = container.scrollTop();
    976                     content.css( 'margin-top', ( $( '#customize-header-actions' ).height() - position - scroll ) );
    977                     section.addClass( 'current-panel' );
    978                     overlay.addClass( 'in-themes-panel' );
     1058                panel._animateChangeExpanded( function() {
     1059                    changeBtn.attr( 'tabindex', '-1' );
     1060                    customizeBtn.attr( 'tabindex', '0' );
     1061
     1062                    customizeBtn.focus();
     1063                    section.css( 'top', '' );
    9791064                    container.scrollTop( 0 );
    980                     _.delay( panel.renderScreenshots, 10 ); // Wait for the controls
    981                     panel.$customizeSidebar.on( 'scroll.customize-themes-section', _.throttle( panel.renderScreenshots, 300 ) );
     1065
    9821066                    if ( args.completeCallback ) {
    9831067                        args.completeCallback();
    9841068                    }
    9851069                } );
    986                 customizeBtn.focus();
    987             } else {
    988                 siblings.removeClass( 'open' );
    989                 section.removeClass( 'current-panel' );
    990                 overlay.removeClass( 'in-themes-panel' );
    991                 panel.$customizeSidebar.off( 'scroll.customize-themes-section' );
    992                 content.delay( 180 ).hide( 0, function() {
    993                     content.css( 'margin-top', 'inherit' ); // Reset
     1070
     1071                overlay.addClass( 'in-themes-panel' );
     1072                section.addClass( 'current-panel' );
     1073
     1074            } else if ( ! expanded && section.hasClass( 'current-panel' ) ) {
     1075                panel._animateChangeExpanded( function() {
     1076                    changeBtn.attr( 'tabindex', '0' );
     1077                    customizeBtn.attr( 'tabindex', '-1' );
     1078
     1079                    changeBtn.focus();
     1080                    section.css( 'top', '' );
     1081
    9941082                    if ( args.completeCallback ) {
    9951083                        args.completeCallback();
    9961084                    }
    9971085                } );
    998                 customizeBtn.attr( 'tabindex', '0' );
    999                 changeBtn.focus();
    1000                 container.scrollTop( 0 );
    1001             }
    1002         },
    1003 
    1004         /**
    1005          * Recalculate the top margin.
    1006          *
    1007          * @since 4.4.0
    1008          * @private
    1009          */
    1010         _recalculateTopMargin: function() {
    1011             api.Panel.prototype._recalculateTopMargin.call( this );
     1086
     1087                overlay.removeClass( 'in-themes-panel' );
     1088                section.removeClass( 'current-panel' );
     1089            }
    10121090        },
    10131091
     
    12381316        embed: function () {
    12391317            var panel = this,
    1240                 parentContainer = $( '#customize-theme-controls > ul' ); // @todo This should be defined elsewhere, and to be configurable
    1241 
    1242             if ( ! panel.container.parent().is( parentContainer ) ) {
    1243                 parentContainer.append( panel.container );
     1318                container = $( '#customize-theme-controls' ),
     1319                parentContainer = $( '.customize-pane-parent' ); // @todo This should be defined elsewhere, and to be configurable
     1320
     1321            if ( ! panel.headContainer.parent().is( parentContainer ) ) {
     1322                parentContainer.append( panel.headContainer );
     1323            }
     1324            if ( ! panel.contentContainer.parent().is( panel.headContainer ) ) {
     1325                container.append( panel.contentContainer );
    12441326                panel.renderContent();
    12451327            }
    1246 
    1247             api.bind( 'pane-contents-reflowed', _.debounce( function() {
    1248                 panel._recalculateTopMargin();
    1249             }, 100 ) );
    12501328
    12511329            panel.deferred.embedded.resolve();
     
    12591337
    12601338            // Expand/Collapse accordion sections on click.
    1261             panel.container.find( '.accordion-section-title' ).on( 'click keydown', function( event ) {
     1339            panel.headContainer.find( '.accordion-section-title' ).on( 'click keydown', function( event ) {
    12621340                if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
    12631341                    return;
     
    12901368                event.preventDefault(); // Keep this AFTER the key filter above
    12911369
    1292                 meta = panel.container.find( '.panel-meta' );
    12931370                if ( meta.hasClass( 'cannot-expand' ) ) {
    12941371                    return;
     
    13601437
    13611438            // Note: there is a second argument 'args' passed
    1362             var position, scroll,
    1363                 panel = this,
    1364                 accordionSection = panel.container.closest( '.accordion-section' ),
     1439            var panel = this,
     1440                accordionSection = panel.contentContainer,
    13651441                overlay = accordionSection.closest( '.wp-full-overlay' ),
    13661442                container = accordionSection.closest( '.wp-full-overlay-sidebar-content' ),
    1367                 siblings = container.find( '.open' ),
    1368                 topPanel = overlay.find( '#customize-theme-controls > ul > .accordion-section > .accordion-section-title' ),
    1369                 backBtn = accordionSection.find( '.customize-panel-back' ),
    1370                 panelTitle = accordionSection.find( '.accordion-section-title' ).first(),
    1371                 content = accordionSection.find( '.control-panel-content' ),
    1372                 headerActionsHeight = $( '#customize-header-actions' ).height();
    1373 
    1374             if ( expanded ) {
    1375 
     1443                topPanel = panel.headContainer.find( '.accordion-section-title' ),
     1444                backBtn = accordionSection.find( '.customize-panel-back' );
     1445
     1446            if ( expanded && ! accordionSection.hasClass( 'current-panel' ) ) {
    13761447                // Collapse any sibling sections/panels
    13771448                api.section.each( function ( section ) {
     
    13861457                });
    13871458
    1388                 content.show( 0, function() {
    1389                     content.parent().show();
    1390                     position = content.offset().top;
    1391                     scroll = container.scrollTop();
    1392                     content.css( 'margin-top', ( headerActionsHeight - position - scroll ) );
    1393                     accordionSection.addClass( 'current-panel' );
    1394                     overlay.addClass( 'in-sub-panel' );
     1459                panel._animateChangeExpanded( function() {
     1460                    topPanel.attr( 'tabindex', '-1' );
     1461                    backBtn.attr( 'tabindex', '0' );
     1462
     1463                    backBtn.focus();
     1464                    accordionSection.css( 'top', '' );
    13951465                    container.scrollTop( 0 );
     1466
    13961467                    if ( args.completeCallback ) {
    13971468                        args.completeCallback();
    13981469                    }
    13991470                } );
    1400                 topPanel.attr( 'tabindex', '-1' );
    1401                 backBtn.attr( 'tabindex', '0' );
    1402                 backBtn.focus();
    1403                 panel._recalculateTopMargin();
    1404             } else {
    1405                 siblings.removeClass( 'open' );
    1406                 accordionSection.removeClass( 'current-panel' );
    1407                 overlay.removeClass( 'in-sub-panel' );
    1408                 content.delay( 180 ).hide( 0, function() {
    1409                     content.css( 'margin-top', 'inherit' ); // Reset
     1471
     1472                overlay.addClass( 'in-sub-panel' );
     1473                accordionSection.addClass( 'current-panel' );
     1474
     1475            } else if ( ! expanded && accordionSection.hasClass( 'current-panel' ) ) {
     1476                panel._animateChangeExpanded( function() {
     1477                    topPanel.attr( 'tabindex', '0' );
     1478                    backBtn.attr( 'tabindex', '-1' );
     1479
     1480                    topPanel.focus();
     1481                    accordionSection.css( 'top', '' );
     1482
    14101483                    if ( args.completeCallback ) {
    14111484                        args.completeCallback();
    14121485                    }
    14131486                } );
    1414                 topPanel.attr( 'tabindex', '0' );
    1415                 backBtn.attr( 'tabindex', '-1' );
    1416                 panelTitle.focus();
    1417                 container.scrollTop( 0 );
    1418             }
    1419         },
    1420 
    1421         /**
    1422          * Recalculate the top margin.
    1423          *
    1424          * @since 4.4.0
    1425          * @private
    1426          */
    1427         _recalculateTopMargin: function() {
    1428             var panel = this, headerActionsHeight, content, accordionSection;
    1429             headerActionsHeight = $( '#customize-header-actions' ).height();
    1430             accordionSection = panel.container.closest( '.accordion-section' );
    1431             content = accordionSection.find( '.control-panel-content' );
    1432             content.css( 'margin-top', ( parseInt( content.css( 'margin-top' ), 10 ) - ( content.offset().top - headerActionsHeight ) ) );
     1487
     1488                overlay.removeClass( 'in-sub-panel' );
     1489                accordionSection.removeClass( 'current-panel' );
     1490            }
    14331491        },
    14341492
     
    14501508                template = wp.template( 'customize-panel-default-content' );
    14511509            }
    1452             if ( template && panel.container ) {
    1453                 panel.container.find( '.accordion-sub-container' ).html( template( panel.params ) );
     1510            if ( template && panel.headContainer ) {
     1511                panel.contentContainer.html( template( panel.params ) );
    14541512            }
    14551513        }
     
    16271685                    // Wait for the section to be ready/initialized
    16281686                    section.deferred.embedded.done( function () {
    1629                         parentContainer = section.container.find( 'ul:first' );
     1687                        parentContainer = ( section.contentContainer.is( 'ul' ) ) ? section.contentContainer : section.contentContainer.find( 'ul:first' );
    16301688                        if ( ! control.container.parent().is( parentContainer ) ) {
    16311689                            parentContainer.append( control.container );
     
    35433601    api.reflowPaneContents = _.bind( function () {
    35443602
    3545         var appendContainer, activeElement, rootContainers, rootNodes = [], wasReflowed = false;
     3603        var appendContainer, activeElement, rootHeadContainers, rootNodes = [], wasReflowed = false;
    35463604
    35473605        if ( document.activeElement ) {
     
    35523610        api.panel.each( function ( panel ) {
    35533611            var sections = panel.sections(),
    3554                 sectionContainers = _.pluck( sections, 'container' );
     3612                sectionHeadContainers = _.pluck( sections, 'headContainer' );
    35553613            rootNodes.push( panel );
    3556             appendContainer = panel.container.find( 'ul:first' );
    3557             if ( ! api.utils.areElementListsEqual( sectionContainers, appendContainer.children( '[id]' ) ) ) {
     3614            appendContainer = ( panel.contentContainer.is( 'ul' ) ) ? panel.contentContainer : panel.contentContainer.find( 'ul:first' );
     3615            if ( ! api.utils.areElementListsEqual( sectionHeadContainers, appendContainer.children( '[id]' ) ) ) {
    35583616                _( sections ).each( function ( section ) {
    3559                     appendContainer.append( section.container );
     3617                    appendContainer.append( section.headContainer );
    35603618                } );
    35613619                wasReflowed = true;
     
    35703628                rootNodes.push( section );
    35713629            }
    3572             appendContainer = section.container.find( 'ul:first' );
     3630            appendContainer = ( section.contentContainer.is( 'ul' ) ) ? section.contentContainer : section.contentContainer.find( 'ul:first' );
    35733631            if ( ! api.utils.areElementListsEqual( controlContainers, appendContainer.children( '[id]' ) ) ) {
    35743632                _( controls ).each( function ( control ) {
     
    35813639        // Sort the root panels and sections
    35823640        rootNodes.sort( api.utils.prioritySort );
    3583         rootContainers = _.pluck( rootNodes, 'container' );
    3584         appendContainer = $( '#customize-theme-controls' ).children( 'ul' ); // @todo This should be defined elsewhere, and to be configurable
    3585         if ( ! api.utils.areElementListsEqual( rootContainers, appendContainer.children() ) ) {
     3641        rootHeadContainers = _.pluck( rootNodes, 'headContainer' );
     3642        appendContainer = $( '#customize-theme-controls .customize-pane-parent' ); // @todo This should be defined elsewhere, and to be configurable
     3643        if ( ! api.utils.areElementListsEqual( rootHeadContainers, appendContainer.children() ) ) {
    35863644            _( rootNodes ).each( function ( rootNode ) {
    3587                 appendContainer.append( rootNode.container );
     3645                appendContainer.append( rootNode.headContainer );
    35883646            } );
    35893647            wasReflowed = true;
  • trunk/src/wp-admin/js/customize-nav-menus.js

    r38624 r38648  
    852852            api.bind( 'pane-contents-reflowed', function() {
    853853                // Skip menus that have been removed.
    854                 if ( ! section.container.parent().length ) {
     854                if ( ! section.contentContainer.parent().length ) {
    855855                    return;
    856856                }
     
    970970
    971971            if ( expanded ) {
    972                 wpNavMenu.menuList = section.container.find( '.accordion-section-content:first' );
     972                wpNavMenu.menuList = section.contentContainer;
    973973                wpNavMenu.targetList = wpNavMenu.menuList;
    974974
     
    10321032            var section = this,
    10331033                button = section.container.find( '.add-menu-toggle' ),
    1034                 content = section.container.find( '.new-menu-section-content' ),
    1035                 customizer = section.container.closest( '.wp-full-overlay-sidebar-content' );
     1034                content = section.contentContainer,
     1035                customizer = section.headContainer.closest( '.wp-full-overlay-sidebar-content' );
    10361036            if ( expanded ) {
    10371037                button.addClass( 'open' );
     
    10461046                content.find( '.menu-name-field' ).removeClass( 'invalid' );
    10471047            }
     1048        },
     1049
     1050        /**
     1051         * Find the content element.
     1052         *
     1053         * @since 4.7.0
     1054         *
     1055         * @returns {jQuery} Content UL element.
     1056         */
     1057        getContent: function() {
     1058            return this.container.find( 'ul:first' );
    10481059        }
    10491060    });
     
    20022013        ready: function() {
    20032014            var control = this,
     2015                section = api.section( control.section() ),
    20042016                menuId = control.params.menu_id,
    20052017                menu = control.setting(),
     
    20182030             */
    20192031            control.active.validate = function() {
    2020                 var value, section = api.section( control.section() );
     2032                var value;
    20212033                if ( section ) {
    20222034                    value = section.active();
     
    20272039            };
    20282040
    2029             control.$controlSection = control.container.closest( '.control-section' );
     2041            control.$controlSection = section.headContainer;
    20302042            control.$sectionContent = control.container.closest( '.accordion-section-content' );
    20312043
     
    23012313                }
    23022314
    2303                 var section = control.container.closest( '.accordion-section' ),
     2315                var section = api.section( control.section() ),
    23042316                    menuId = control.params.menu_id,
    2305                     controlTitle = section.find( '.accordion-section-title' ),
    2306                     sectionTitle = section.find( '.customize-section-title h3' ),
    2307                     location = section.find( '.menu-in-location' ),
     2317                    controlTitle = section.headContainer.find( '.accordion-section-title' ),
     2318                    sectionTitle = section.contentContainer.find( '.customize-section-title h3' ),
     2319                    location = section.headContainer.find( '.menu-in-location' ),
    23082320                    action = sectionTitle.find( '.customize-action' ),
    23092321                    name = displayNavMenuName( menu.name );
     
    23292341
    23302342                // Update the nav menu name in all location checkboxes.
    2331                 section.find( '.customize-control-checkbox input' ).each( function() {
     2343                section.contentContainer.find( '.customize-control-checkbox input' ).each( function() {
    23322344                    if ( $( this ).prop( 'checked' ) ) {
    23332345                        $( '.current-menu-location-name-' + $( this ).data( 'location-id' ) ).text( name );
     
    26432655            // Focus on the new menu section.
    26442656            api.section( customizeId ).focus(); // @todo should we focus on the new menu's control and open the add-items panel? Thinking user flow...
    2645 
    2646             // Fix an issue with extra space at top immediately after creating new menu.
    2647             $( '#menu-to-edit' ).css( 'margin-top', 0 );
    26482657        }
    26492658    });
  • trunk/tests/qunit/wp-admin/js/customize-controls.js

    r37700 r38648  
    212212        ok( ! section.params.content );
    213213        ok( !! section.container );
    214         ok( section.container.is( '.control-section.control-section-default' ) );
    215         ok( 1 === section.container.find( '> .accordion-section-title' ).length );
    216         ok( 1 === section.container.find( '> .accordion-section-content' ).length );
     214        ok( !! section.headContainer );
     215        ok( !! section.contentContainer );
     216        ok( section.container.has( section.headContainer ) );
     217        ok( section.container.has( section.contentContainer ) );
     218        ok( section.headContainer.is( '.control-section.control-section-default' ) );
     219        ok( 1 === section.headContainer.find( '> .accordion-section-title' ).length );
     220        ok( section.contentContainer.is( '.accordion-section-content' ) );
     221        equal( section.headContainer.attr( 'aria-owns' ), section.contentContainer.attr( 'id' ) );
    217222    } );
    218223
     
    226231        ok( ! section.params.content );
    227232        ok( !! section.container );
     233        ok( !! section.headContainer );
     234        ok( !! section.contentContainer );
     235        ok( section.container.has( section.headContainer ) );
     236        ok( section.container.has( section.contentContainer ) );
    228237        ok( section.container.is( '.control-section.control-section-titleless' ) );
    229         ok( 0 === section.container.find( '> .accordion-section-title' ).length );
    230         ok( 1 === section.container.find( '> .accordion-section-content' ).length );
     238        ok( 0 === section.headContainer.find( '> .accordion-section-title' ).length );
     239        ok( section.contentContainer.is( '.accordion-section-content' ) );
     240        equal( section.headContainer.attr( 'aria-owns' ), section.contentContainer.attr( 'id' ) );
    231241    } );
    232242    module( 'Customizer Custom Type Section Lacking Specific Template' );
     
    236246        ok( ! section.params.content );
    237247        ok( !! section.container );
    238         ok( section.container.is( '.control-section.control-section-' + section.params.type ) );
    239         ok( 1 === section.container.find( '> .accordion-section-title' ).length );
    240         ok( 1 === section.container.find( '> .accordion-section-content' ).length );
     248        ok( !! section.headContainer );
     249        ok( !! section.contentContainer );
     250        ok( section.container.has( section.headContainer ) );
     251        ok( section.container.has( section.contentContainer ) );
     252        ok( section.headContainer.is( '.control-section.control-section-' + section.params.type ) );
     253        ok( 1 === section.headContainer.find( '> .accordion-section-title' ).length );
     254        ok( section.contentContainer.is( '.accordion-section-content' ) );
     255        equal( section.headContainer.attr( 'aria-owns' ), section.contentContainer.attr( 'id' ) );
    241256    } );
    242257    module( 'Customizer Section lacking any params' );
     
    271286        ok( !! panel.params.content );
    272287        ok( !! panel.container );
     288        ok( !! panel.headContainer );
     289        ok( !! panel.contentContainer );
     290        ok( panel.container.has( panel.headContainer ) );
     291        ok( panel.container.has( panel.contentContainer ) );
    273292    } );
    274293    test( 'Fixture panel has section among its sections()', function () {
     
    305324        ok( ! panel.params.content );
    306325        ok( !! panel.container );
    307         ok( panel.container.is( '.control-panel.control-panel-default' ) );
    308         ok( 1 === panel.container.find( '> .accordion-section-title' ).length );
    309         ok( 1 === panel.container.find( '> .control-panel-content' ).length );
     326        ok( !! panel.headContainer );
     327        ok( !! panel.contentContainer );
     328        ok( panel.container.has( panel.headContainer ) );
     329        ok( panel.container.has( panel.contentContainer ) );
     330        ok( panel.headContainer.is( '.control-panel.control-panel-default' ) );
     331        ok( 1 === panel.headContainer.find( '> .accordion-section-title' ).length );
     332        ok( panel.contentContainer.is( '.control-panel-content' ) );
     333        equal( panel.headContainer.attr( 'aria-owns' ), panel.contentContainer.attr( 'id' ) );
    310334    } );
    311335
     
    319343        ok( ! panel.params.content );
    320344        ok( !! panel.container );
    321         ok( panel.container.is( '.control-panel.control-panel-titleless' ) );
    322         ok( 0 === panel.container.find( '> .accordion-section-title' ).length );
    323         ok( 1 === panel.container.find( '> .control-panel-content' ).length );
     345        ok( !! panel.headContainer );
     346        ok( !! panel.contentContainer );
     347        ok( panel.container.has( panel.headContainer ) );
     348        ok( panel.container.has( panel.contentContainer ) );
     349        ok( panel.headContainer.is( '.control-panel.control-panel-titleless' ) );
     350        ok( 0 === panel.headContainer.find( '> .accordion-section-title' ).length );
     351        ok( panel.contentContainer.is( '.control-panel-content' ) );
     352        equal( panel.headContainer.attr( 'aria-owns' ), panel.contentContainer.attr( 'id' ) );
    324353    } );
    325354
     
    330359        ok( ! panel.params.content );
    331360        ok( !! panel.container );
    332         ok( panel.container.is( '.control-panel.control-panel-' + panel.params.type ) );
    333         ok( 1 === panel.container.find( '> .accordion-section-title' ).length );
    334         ok( 1 === panel.container.find( '> .control-panel-content' ).length );
     361        ok( !! panel.headContainer );
     362        ok( !! panel.contentContainer );
     363        ok( panel.container.has( panel.headContainer ) );
     364        ok( panel.container.has( panel.contentContainer ) );
     365        ok( panel.headContainer.is( '.control-panel.control-panel-' + panel.params.type ) );
     366        ok( 1 === panel.headContainer.find( '> .accordion-section-title' ).length );
     367        ok( panel.contentContainer.is( '.control-panel-content' ) );
     368        equal( panel.headContainer.attr( 'aria-owns' ), panel.contentContainer.attr( 'id' ) );
    335369    } );
    336370    module( 'Customizer Panel lacking any params' );
  • trunk/tests/qunit/wp-admin/js/customize-widgets.js

    r35231 r38648  
    5959
    6060        panel.deferred.embedded.done( function() {
    61             ok( 1 === panel.container.find( '.no-widget-areas-rendered-notice' ).length );
    62             ok( panel.container.find( '.no-widget-areas-rendered-notice' ).is( ':visible' ) );
     61            ok( 1 === panel.contentContainer.find( '.no-widget-areas-rendered-notice' ).length );
     62            ok( panel.contentContainer.find( '.no-widget-areas-rendered-notice' ).is( ':visible' ) );
    6363            api.section( 'sidebar-widgets-sidebar-1' ).active( true );
    6464            api.control( 'sidebars_widgets[sidebar-1]' ).active( true );
    6565            api.trigger( 'pane-contents-reflowed' );
    66             ok( ! panel.container.find( '.no-widget-areas-rendered-notice' ).is( ':visible' ) );
     66            ok( ! panel.contentContainer.find( '.no-widget-areas-rendered-notice' ).is( ':visible' ) );
    6767        } );
    6868
Note: See TracChangeset for help on using the changeset viewer.