Ticket #34391: 34391_3.diff
| File 34391_3.diff, 56.6 KB (added by , 9 years ago) |
|---|
-
src/wp-admin/css/common.css
diff --git a/src/wp-admin/css/common.css b/src/wp-admin/css/common.css index c699ad8..3d9014a 100644
a b img { 3330 3330 display: none; 3331 3331 } 3332 3332 3333 .control-section .accordion-section-title { 3333 .control-section .accordion-section-title, 3334 .customize-pane-child .accordion-section-title { 3334 3335 border-left: none; 3335 3336 border-right: none; 3336 3337 padding: 10px 10px 11px 14px; … … img { 3338 3339 background: #fff; 3339 3340 } 3340 3341 3341 .control-section .accordion-section-title:after { 3342 .control-section .accordion-section-title:after, 3343 .customize-pane-child .accordion-section-title:after { 3342 3344 top: 11px; 3343 3345 } 3344 3346 -
src/wp-admin/css/customize-controls.css
diff --git a/src/wp-admin/css/customize-controls.css b/src/wp-admin/css/customize-controls.css index a7648fd..273948f 100644
a b body { 78 78 line-height: 24px; 79 79 } 80 80 81 #customize-controls .c ontrol-section.customize-section-title h3,82 #customize-controls .c ontrol-sectionh3.customize-section-title,81 #customize-controls .customize-pane-child .customize-section-title h3, 82 #customize-controls .customize-pane-child h3.customize-section-title, 83 83 #customize-controls .customize-info .panel-title { 84 84 font-size: 20px; 85 85 font-weight: 200; … … body { 219 219 box-sizing: border-box; 220 220 } 221 221 222 .wp-full-overlay #customize-controls .wp-full-overlay-sidebar-content { 223 -webkit-transform: translate3d(0, 0, 0); 224 transform: translate3d(0, 0, 0); /* Promote to separate layer to avoid full-screen repaints */ 225 } 226 227 #customize-info, 228 #customize-theme-controls .customize-pane-parent, 229 #customize-theme-controls .customize-pane-child { 230 overflow: visible; 231 width: 100%; 232 margin: 0; 233 padding: 0; 234 -webkit-box-sizing: border-box; 235 -moz-box-sizing: border-box; 236 box-sizing: border-box; 237 -webkit-transition: 0.36s -webkit-transform cubic-bezier(0.645, 0.045, 0.355, 1); 238 transition: 0.36s -webkit-transform cubic-bezier(0.645, 0.045, 0.355, 1); 239 transition: 0.36s transform cubic-bezier(0.645, 0.045, 0.355, 1); 240 transition: 0.36s transform cubic-bezier(0.645, 0.045, 0.355, 1), 0.36s -webkit-transform cubic-bezier(0.645, 0.045, 0.355, 1); /* easeInOutCubic */ 241 } 242 243 #customize-info, 244 #customize-theme-controls .customize-pane-parent { 245 position: relative; 246 visibility: visible; 247 height: auto; 248 max-height: none; 249 overflow: auto; 250 -webkit-transform: none; 251 -ms-transform: none; 252 transform: none; 253 } 254 255 #customize-theme-controls .customize-pane-child { 256 position: absolute; 257 top: 0; 258 left: 0; 259 visibility: hidden; 260 height: 0; 261 max-height: none; 262 overflow: hidden; 263 -webkit-transform: translateX(100%); 264 -ms-transform: translateX(100%); 265 transform: translateX(100%); 266 } 267 268 #customize-theme-controls .customize-pane-child.open, 269 #customize-theme-controls .customize-pane-child.current-panel, 270 #customize-theme-controls .customize-themes-panel.customize-pane-child.current-panel { 271 -webkit-transform: none; 272 -ms-transform: none; 273 transform: none; 274 } 275 276 #customize-theme-controls .customize-themes-panel.customize-pane-child, 277 .section-open #customize-theme-controls .customize-pane-parent, 278 .in-sub-panel #customize-theme-controls .customize-pane-parent, 279 .section-open #customize-info, 280 .in-sub-panel #customize-info, 281 .in-sub-panel.section-open #customize-theme-controls .customize-pane-child.current-panel, 282 .in-themes-panel #customize-theme-controls .customize-pane-parent, 283 .in-themes-panel #customize-info { 284 visibility: hidden; 285 height: 0; 286 overflow: hidden; 287 -webkit-transform: translateX(-100%); 288 -ms-transform: translateX(-100%); 289 transform: translateX(-100%); 290 } 291 292 .section-open #customize-theme-controls .customize-pane-parent.busy, 293 .in-sub-panel #customize-theme-controls .customize-pane-parent.busy, 294 .in-themes-panel #customize-theme-controls .customize-pane-parent.busy, 295 .section-open #customize-info.busy, 296 .in-sub-panel #customize-info.busy, 297 .in-themes-panel #customize-info.busy, 298 .busy.section-open.in-sub-panel #customize-theme-controls .customize-pane-child.current-panel, 299 #customize-theme-controls .customize-pane-child.open, 300 #customize-theme-controls .customize-pane-child.current-panel, 301 #customize-theme-controls .customize-pane-child.busy { 302 visibility: visible; 303 height: auto; 304 overflow: auto; 305 } 306 307 .in-themes-panel #customize-theme-controls .customize-pane-parent, 308 .in-themes-panel #customize-info { 309 -webkit-transform: translateX(100%); 310 -ms-transform: translateX(100%); 311 transform: translateX(100%); 312 } 313 314 #customize-theme-controls .customize-pane-child.accordion-section-content, 315 #customize-theme-controls .customize-pane-child.accordion-sub-container { 316 display: block; 317 overflow-x: hidden; 318 } 319 320 #customize-theme-controls .customize-pane-child.accordion-section-content { 321 padding: 12px; 322 } 323 222 324 .customize-section-description-container { 223 325 margin-bottom: 15px; 224 326 } … … h3.customize-section-title { 258 360 color: #555; 259 361 } 260 362 261 #customize-theme-controls {262 position: relative;263 left: 0;264 -webkit-transition: .18s left ease-in-out;265 transition: .18s left ease-in-out;266 }267 268 .ios #customize-theme-controls {269 -webkit-transition: left 0s;270 transition: left 0s;271 }272 273 .section-open #customize-info,274 .section-open #customize-theme-controls {275 left: -100%;276 }277 278 363 .accordion-sub-container.control-panel-content { 279 364 display: none; 280 365 position: absolute; 281 left: 100%;282 366 top: 0; 283 367 width: 100%; 284 -webkit-transition: left ease-in-out .18s;285 transition: left ease-in-out .18s;286 }287 288 .ios .accordion-sub-container.control-panel-content {289 -webkit-transition: left 0s;290 transition: left 0s;291 368 } 292 369 293 .accordion-sub-container.control-panel-content. animating{370 .accordion-sub-container.control-panel-content.busy { 294 371 display: block; 295 372 } 296 373 … … h3.customize-section-title { 333 410 -webkit-box-shadow: none; 334 411 box-shadow: none; 335 412 cursor: pointer; 336 -webkit-transition: left .18s ease-in-out,color .1s ease-in-out, background .1s ease-in-out;337 transition: left .18s ease-in-out,color .1s ease-in-out, background .1s ease-in-out;413 -webkit-transition: color .1s ease-in-out, background .1s ease-in-out; 414 transition: color .1s ease-in-out, background .1s ease-in-out; 338 415 } 339 416 340 417 .customize-section-back { 341 418 height: 74px; 342 419 } 343 420 344 .ios .customize-panel-back,345 .ios .customize-section-back {346 -webkit-transition: left 0s;347 transition: left 0s;348 }349 350 421 .ios .customize-panel-back { 351 422 display: none; 352 423 } … … h3.customize-section-title { 412 483 padding-left: 62px; 413 484 } 414 485 415 #customize-info,416 #customize-theme-controls > ul > .accordion-section {417 position: relative;418 left: 0;419 -webkit-transition: left ease-in-out .18s;420 transition: left ease-in-out .18s;421 }422 423 .ios #customize-info,424 .ios #customize-theme-controls > ul > .accordion-section {425 -webkit-transition: left 0s;426 transition: left 0s;427 }428 429 .in-sub-panel #customize-info,430 .in-sub-panel #customize-theme-controls > ul > .accordion-section {431 left: -100%;432 width: 100%;433 }434 435 .in-sub-panel #customize-theme-controls .accordion-section.current-panel {436 width: 100%;437 }438 439 #customize-theme-controls .control-section.current-panel {440 padding: 0;441 }442 443 #customize-theme-controls .control-section > h3.accordion-section-title {444 position: relative;445 left: 0;446 }447 448 #customize-theme-controls .control-section.current-panel > h3.accordion-section-title {449 left: -354px;450 -webkit-transition: left ease-in-out .18s;451 transition: left ease-in-out .18s;452 }453 454 .ios #customize-theme-controls .control-section.current-panel > h3.accordion-section-title {455 -webkit-transition: left 0s;456 transition: left 0s;457 }458 459 .wp-full-overlay.section-open #customize-controls .wp-full-overlay-sidebar-content {460 visibility: hidden;461 overflow-y: hidden;462 }463 464 .wp-full-overlay.section-open .wp-full-overlay-sidebar-content .accordion-section.open {465 visibility: visible;466 }467 468 .wp-full-overlay.section-open .wp-full-overlay-sidebar-content .accordion-section.open .accordion-section-content {469 overflow-y: auto;470 }471 472 486 p.customize-section-description { 473 487 font-style: normal; 474 488 margin-top: 22px; … … p.customize-section-description { 976 990 animation: customize-reload .75s; 977 991 } 978 992 979 .control-section-themes .accordion-section-title {993 #customize-controls .control-section-themes .accordion-section-title { 980 994 cursor: default; 981 995 } 982 996 … … p.customize-section-description { 986 1000 background-color: #fff; 987 1001 } 988 1002 989 .control-section-themes .accordion-section-title {1003 #customize-controls .control-section-themes .accordion-section-title { 990 1004 margin: 15px 0; 991 1005 } 992 1006 993 .customize-themes-panel .accordion-section-title {1007 #customize-controls .customize-themes-panel .accordion-section-title { 994 1008 margin: 15px -8px; 995 1009 } 996 1010 997 .control-section-themes .accordion-section-title { 1011 #customize-controls .control-section-themes .accordion-section-title, 1012 #customize-controls .customize-themes-panel .accordion-section-title { 998 1013 padding-right: 100px; /* Space for the button */ 999 1014 } 1000 1015 1001 .control-section-themes .accordion-section-title span.customize-action,1016 #customize-controls .control-section-themes .accordion-section-title span.customize-action, 1002 1017 #customize-controls .customize-section-title span.customize-action { 1003 1018 font-size: 13px; 1004 1019 display: block; 1005 1020 font-weight: 400; 1006 1021 } 1007 1022 1008 .control-section-themes .accordion-section-title .change-theme,1009 .control-section-themes.accordion-section-title .customize-theme {1023 #customize-controls .control-section-themes .accordion-section-title .change-theme, 1024 #customize-controls .customize-themes-panel .accordion-section-title .customize-theme { 1010 1025 position: absolute; 1011 1026 right: 10px; 1012 1027 top: 50%; … … p.customize-section-description { 1014 1029 font-weight: 400; 1015 1030 } 1016 1031 1017 .control-section-themes .accordion-section-title:before {1032 #customize-controls .control-section-themes .accordion-section-title:before { 1018 1033 display: none; 1019 1034 } 1020 1035 1021 .customize-themes-panel { 1022 display: none; 1036 #customize-controls .customize-themes-panel { 1023 1037 padding: 0 8px; 1024 1038 background: #f1f1f1; 1025 1039 -webkit-box-sizing: border-box; … … p.customize-section-description { 1027 1041 box-sizing: border-box; 1028 1042 } 1029 1043 1030 .customize-themes-panel .accordion-section-title:first-child {1044 #customize-controls .customize-themes-panel .accordion-section-title:first-child { 1031 1045 margin-top: 0; 1032 1046 } 1033 1047 … … p.customize-section-description { 1036 1050 font-weight: 600; 1037 1051 } 1038 1052 1039 .customize-themes-panel > h2 {1053 #customize-controls .customize-themes-panel > h2 { 1040 1054 padding: 15px 8px 0 8px; 1041 1055 } 1042 1056 1043 .control-section.open .customize-themes-panel {1044 display: block;1045 }1046 1047 1057 #customize-theme-controls .customize-themes-panel .accordion-section-content { 1048 1058 background: transparent; 1049 1059 display: block; … … p.customize-section-description { 1089 1099 width: 100%; 1090 1100 } 1091 1101 1092 #accordion-section-themes .accordion-section-title:after { 1102 .control-section-themes .accordion-section-title:after, 1103 .customize-themes-panel .accordion-section-title:after { 1093 1104 display: none; 1094 1105 } 1095 1106 1096 #customize-theme-controls .control-section-themes.current-panel > h3.accordion-section-title {1097 left: 0;1098 }1099 1100 1107 .customize-themes-panel.control-panel-content { 1101 position: absolute;1102 left: -100%;1103 top: 0;1104 width: 100%;1105 1108 border-top: 1px solid #ddd; 1106 1109 } 1107 1110 1108 .in-themes-panel #customize-info,1109 .in-themes-panel #customize-theme-controls > ul > .accordion-section {1110 left: 100%;1111 }1112 1113 1111 /* Details View */ 1114 1112 .wp-customizer .theme-overlay { 1115 1113 display: none; … … p.customize-section-description { 1143 1141 text-align: right; /* Because there's only one action, match the pattern of media modals and right-align the action. */ 1144 1142 } 1145 1143 1146 .modal-open .in-themes-panel #customize-controls .wp-full-overlay-sidebar-content { 1147 overflow: visible; /* Prevent the top-level Customizer controls from becoming visible when elements on the right of the details modal are focused. */ 1144 .in-themes-panel #customize-controls .wp-full-overlay-sidebar-content { 1145 -webkit-transform: none; 1146 -ms-transform: none; 1147 transform: none; /* Prevent creating new stacking contexts and containing blocks for themes modal. */ 1148 1148 } 1149 1149 1150 1150 .ie8 .wp-customizer .theme-overlay .theme-header, -
src/wp-admin/css/customize-nav-menus.css
diff --git a/src/wp-admin/css/customize-nav-menus.css b/src/wp-admin/css/customize-nav-menus.css index 66d2b08..7250da7 100644
a b 377 377 .reordering .menu-item-depth-10 > .menu-item-bar { margin-right: 150px; } 378 378 .reordering .menu-item-depth-11 > .menu-item-bar { margin-right: 165px; } 379 379 380 . control-section-nav_menu.menu .menu-item-edit-active {380 .accordion-section-content.menu .menu-item-edit-active { 381 381 margin-left: 0; 382 382 } 383 383 384 . control-section-nav_menu.menu .menu-item-edit-active .menu-item-bar {384 .accordion-section-content.menu .menu-item-edit-active .menu-item-bar { 385 385 margin-right: 0; 386 386 } 387 387 388 . control-section-nav_menu.menu .sortable-placeholder {388 .accordion-section-content.menu .sortable-placeholder { 389 389 margin-top: 0; 390 390 margin-bottom: 1px; 391 391 max-width: -webkit-calc(100% - 2px); … … 399 399 float: none; 400 400 } 401 401 402 . control-section-nav_menu.menu ul.menu-item-transport .menu-item-bar {402 .accordion-section-content.menu ul.menu-item-transport .menu-item-bar { 403 403 margin-top: 0; 404 404 } 405 405 -
src/wp-admin/customize.php
diff --git a/src/wp-admin/customize.php b/src/wp-admin/customize.php index bd8e118..6c0b20d 100644
a b 142 142 </div> 143 143 144 144 <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> 146 146 </div> 147 147 </div> 148 148 </div> -
src/wp-admin/js/customize-controls.js
diff --git a/src/wp-admin/js/customize-controls.js b/src/wp-admin/js/customize-controls.js index 7078cfd..4c1cddf 100644
a b 1 1 /* global _wpCustomizeHeader, _wpCustomizeBackground, _wpMediaViewsL10n, MediaElementPlayer */ 2 2 (function( exports, $ ){ 3 var Container, focus, api = wp.customize;3 var Container, focus, normalizedTransitionendEventName, api = wp.customize; 4 4 5 5 /** 6 6 * A Customizer Setting. … … 96 96 * @param {Function} [params.completeCallback] 97 97 */ 98 98 focus = function ( params ) { 99 var construct, completeCallback, focus, focusElement; 100 construct = this; 99 var construct = this, 100 completeCallback, focus; 101 101 102 params = params || {}; 102 103 focus = function () { 103 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' ); 108 } else { 109 focusContainer = construct.container; 110 } 104 var focusContainer = construct.container, 105 focusElement; 111 106 112 focusElement = focusContainer.find( '.control-focus:first' ); 107 if ( ( construct.extended( api.Panel ) || construct.extended( api.Section ) ) && construct.expanded && construct.expanded() ) { 108 focusContainer = ( construct.content.is( 'ul' ) ) ? construct.content : construct.content.find( 'ul:first' ); 109 } 110 focusElement = focusContainer.find( '.control-focus, input, select, textarea, button' ).filter( ':visible' ).first(); 113 111 if ( 0 === focusElement.length ) { 114 112 // Note that we can't use :focusable due to a jQuery UI issue. See: https://github.com/jquery/jquery-ui/pull/1583 115 focusElement = focusContainer.find( ' input, select, textarea, button,object, a[href], [tabindex]' ).filter( ':visible' ).first();113 focusElement = focusContainer.find( 'object, a[href], [tabindex]' ).filter( ':visible' ).first(); 116 114 } 117 115 focusElement.focus(); 118 116 }; 117 119 118 if ( params.completeCallback ) { 120 119 completeCallback = params.completeCallback; 121 120 params.completeCallback = function () { … … 188 187 }; 189 188 190 189 /** 190 * Return browser supported `transitionend` event name 191 * 192 * @since 193 * 194 * @returns {String} 195 */ 196 normalizedTransitionendEventName = (function () { 197 var el, transitions, prop; 198 el = document.createElement( 'div' ); 199 transitions = { 200 'transition' : 'transitionend', 201 'OTransition' : 'oTransitionEnd', 202 'MozTransition' : 'transitionend', 203 'WebkitTransition': 'webkitTransitionEnd' 204 }; 205 prop = _.find( _.keys( transitions ), function( prop ) { 206 return ! _.isUndefined( el.style[ prop ] ); 207 } ); 208 if ( prop ) { 209 return transitions[ prop ]; 210 } else { 211 return null; 212 } 213 })(); 214 215 /** 191 216 * Base class for Panel and Section. 192 217 * 193 218 * @since 4.1.0 … … 238 263 if ( 0 === container.container.length ) { 239 264 container.container = $( container.getContainer() ); 240 265 } 266 container.content = container.getContent(); 241 267 242 268 container.deferred = { 243 269 embedded: new $.Deferred() … … 372 398 construct.container.stop( true, true ).slideUp( duration, args.completeCallback ); 373 399 } 374 400 } 375 376 // Recalculate the margin-top immediately, not waiting for debounced reflow, to prevent momentary (100ms) vertical jiggle.377 if ( expandedOtherPanel ) {378 expandedOtherPanel._recalculateTopMargin();379 }380 401 }, 381 402 382 403 /** … … 426 447 }, 427 448 428 449 /** 450 * To override by subclass, handle CSS transitions/animations made on the container. 451 * @abstract 452 */ 453 animateChangeExpanded: function() {}, 454 455 /** 429 456 * Handle the toggle logic for expand/collapse. 430 457 * 431 458 * @param {Boolean} expanded - The new state to apply. … … 507 534 } 508 535 509 536 return '<li></li>'; 537 }, 538 539 /** 540 * Detach and return the content html, extracted from the container html, if it exists. 541 * 542 * @since 543 */ 544 getContent: function () { 545 var container = this, 546 list = container.container.find( '.accordion-section-content, .control-panel-content' ).first(), 547 contentId = 'sub-accordion-list-' + container.id; 548 549 container.setOwnership( contentId ); 550 551 return list.detach().attr( { 552 'id': contentId, 553 'class': 'customize-pane-child ' + list.attr( 'class' ) 554 } ); 555 }, 556 557 /** 558 * Add new element to `aria-owned` property of the container. 559 * 560 * @since 561 */ 562 setOwnership: function ( elementId ) { 563 var container = this.container, 564 ownedElements = container.attr( 'aria-owns' ); 565 566 if ( _.isUndefined( ownedElements ) ) { 567 container.attr( { 568 'aria-owns': elementId 569 } ); 570 } else { 571 container.attr( { 572 'aria-owns': ownedElements + ' ' + elementId 573 } ); 574 } 510 575 } 511 576 }); 512 577 … … 569 634 * @since 4.1.0 570 635 */ 571 636 embed: function () { 572 var section = this, inject; 637 var inject, 638 section = this, 639 container = $( '#customize-theme-controls' ); 573 640 574 641 // Watch for changes to the panel state 575 642 inject = function ( panelId ) { … … 579 646 api.panel( panelId, function ( panel ) { 580 647 // The panel has been registered, wait for it to become ready/initialized 581 648 panel.deferred.embedded.done( function () { 582 parentContainer = panel.cont ainer.find( 'ul:first' );649 parentContainer = panel.content; 583 650 if ( ! section.container.parent().is( parentContainer ) ) { 584 651 parentContainer.append( section.container ); 585 652 } 653 if ( ! section.content.parent().is( section.container ) ) { 654 container.append( section.content ); 655 } 586 656 section.deferred.embedded.resolve(); 587 657 }); 588 658 } ); 589 659 } else { 590 660 // 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 configurable661 parentContainer = $( '.customize-pane-parent' ); // @todo This should be defined elsewhere, and to be configurable 592 662 if ( ! section.container.parent().is( parentContainer ) ) { 593 663 parentContainer.append( section.container ); 594 664 } 665 if ( ! section.content.parent().is( section.container ) ) { 666 container.append( section.content ); 667 } 595 668 section.deferred.embedded.resolve(); 596 669 } 597 670 }; 598 671 section.panel.bind( inject ); 599 672 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 });607 673 }, 608 674 609 675 /** … … 612 678 * @since 4.1.0 613 679 */ 614 680 attachEvents: function () { 615 var section = this; 681 var section = this, 682 toggleHandler; 616 683 617 684 // Expand/Collapse accordion sections on click. 618 section.container.find( '.accordion-section-title, .customize-section-back' ).on( 'click keydown', function( event ) {685 toggleHandler = function ( event ) { 619 686 if ( api.utils.isKeydownButNotEnterEvent( event ) ) { 620 687 return; 621 688 } … … 626 693 } else { 627 694 section.expand(); 628 695 } 629 }); 696 }; 697 698 section.container.find( '.accordion-section-title' ).on( 'click keydown', toggleHandler ); 699 section.content.find( '.customize-section-back' ).on( 'click keydown', toggleHandler ); 630 700 }, 631 701 632 702 /** … … 670 740 onChangeExpanded: function ( expanded, args ) { 671 741 var section = this, 672 742 container = section.container.closest( '.wp-full-overlay-sidebar-content' ), 673 content = section.cont ainer.find( '.accordion-section-content' ),743 content = section.content, 674 744 overlay = section.container.closest( '.wp-full-overlay' ), 675 backBtn = section.container.find( '.customize-section-back' ),745 backBtn = content.find( '.customize-section-back' ), 676 746 sectionTitle = section.container.find( '.accordion-section-title' ).first(), 677 headerActionsHeight = $( '#customize-header-actions' ).height(),678 resizeContentHeight, expand, position, scroll;747 currentScrollTop = container.scrollTop(), 748 previousScrollTop, expand, stateChangeCallback; 679 749 680 if ( expanded && ! section.container.hasClass( 'open' ) ) {750 if ( expanded && ! content.hasClass( 'open' ) ) { 681 751 682 752 if ( args.unchanged ) { 683 753 expand = args.completeCallback; 684 754 } 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' ); 699 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 } 755 expand = $.proxy( function() { 756 stateChangeCallback = function() { 757 sectionTitle.attr( 'tabindex', '-1' ); 758 backBtn.attr( 'tabindex', '0' ); 710 759 711 // Fix the height after browser resize. 712 $( window ).on( 'resize.customizer-section', _.debounce( resizeContentHeight, 100 ) ); 760 backBtn.focus(); 761 content.css( 'top', '' ); 762 container.scrollTop( 0 ); 713 763 714 setTimeout( _.bind( section._recalculateTopMargin, section ), 0 ); 715 }; 764 if ( args.completeCallback ) { 765 args.completeCallback(); 766 } 767 }; 768 769 this.animateChangeExpanded( stateChangeCallback ); 770 771 // Prevent ugly screen flicker for items that are 'below the fold'. 772 if ( normalizedTransitionendEventName && 0 < currentScrollTop ) { 773 content.data( 'previous-scrollTop', currentScrollTop ); 774 content.css( 'top', currentScrollTop + 'px' ); 775 } 776 777 content.addClass( 'open' ); 778 overlay.addClass( 'section-open' ); 779 }, this ); 716 780 } 717 781 718 782 if ( ! args.allowMultiple ) { … … 735 799 expand(); 736 800 } 737 801 738 } else if ( ! expanded && section.container.hasClass( 'open' ) ) { 739 section.container.removeClass( 'open' ); 802 } else if ( ! expanded && content.hasClass( 'open' ) ) { 803 stateChangeCallback = function() { 804 backBtn.attr( 'tabindex', '-1' ); 805 sectionTitle.attr( 'tabindex', '0' ); 806 807 sectionTitle.focus(); 808 content.css( 'top', '' ); 809 810 if ( args.completeCallback ) { 811 args.completeCallback(); 812 } 813 }; 814 815 this.animateChangeExpanded( stateChangeCallback ); 816 817 content.removeClass( 'open' ); 740 818 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(); 819 820 // Prevent ugly screen flicker for items that are 'below the fold'. 821 if ( normalizedTransitionendEventName ) { 822 _.defer( function() { 823 previousScrollTop = content.data( 'previous-scrollTop' ) || 0; 824 if ( 0 < currentScrollTop + previousScrollTop ) { 825 container.scrollTop( previousScrollTop ); 826 content.css( 'top', previousScrollTop - currentScrollTop + 'px' ); 827 } 828 } ); 748 829 } 749 $( window ).off( 'resize.customizer-section' ); 830 750 831 } else { 751 832 if ( args.completeCallback ) { 752 833 args.completeCallback(); … … 755 836 }, 756 837 757 838 /** 758 * Recalculate the top margin.839 * Animate pane state change if transitions are supported by the browser. 759 840 * 760 * @since 4.4.0 761 * @private 841 * @param {function} completeCallback Function to be called after transition is completed. 762 842 */ 763 _recalculateTopMargin: function() { 764 var section = this, content, offset, headerActionsHeight; 765 content = section.container.find( '.accordion-section-content' ); 766 if ( 0 === content.length ) { 843 animateChangeExpanded: function( completeCallback ) { 844 var section = this, 845 content = section.content, 846 overlay = content.closest( '.wp-full-overlay' ), 847 affectedElements, transitionEndCallback; 848 849 if ( ! normalizedTransitionendEventName ) { 850 if ( completeCallback ) { 851 completeCallback(); 852 } 767 853 return; 768 854 } 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 ));855 856 affectedElements = overlay.add( content ); 857 if ( ! overlay.hasClass( 'in-sub-panel' ) ) { 858 affectedElements = affectedElements.add( '#customize-info, .customize-pane-parent' ); 773 859 } 860 861 transitionEndCallback = function( e ) { 862 if ( 2 !== e.eventPhase || ! $( e.target ).is( content ) ) { 863 return; 864 } 865 866 content.off( normalizedTransitionendEventName, transitionEndCallback ); 867 affectedElements.removeClass( 'busy' ); 868 869 if ( completeCallback ) { 870 completeCallback(); 871 } 872 }; 873 874 content.on( normalizedTransitionendEventName, transitionEndCallback ); 875 affectedElements.addClass( 'busy' ); 774 876 } 775 877 }); 776 878 … … 804 906 */ 805 907 ready: function () { 806 908 var section = this; 807 section.overlay = section.cont ainer.find( '.theme-overlay' );909 section.overlay = section.content.find( '.theme-overlay' ); 808 910 section.template = wp.template( 'customize-themes-details-view' ); 809 911 810 912 // Bind global keyboard events. … … 851 953 * @since 4.2.0 852 954 */ 853 955 attachEvents: function () { 854 var section = this; 956 var section = this, 957 content = section.content, 958 toggleHandler; 855 959 856 960 // Expand/Collapse section/panel. 857 section.container.find( '.change-theme, .customize-theme' ).on( 'click keydown', function( event ) {961 toggleHandler = function ( event ) { 858 962 if ( api.utils.isKeydownButNotEnterEvent( event ) ) { 859 963 return; 860 964 } … … 865 969 } else { 866 970 section.expand(); 867 971 } 868 }); 972 }; 973 974 section.container.find( '.change-theme' ).on( 'click keydown', toggleHandler ); 975 content.find( '.customize-theme' ).on( 'click keydown', toggleHandler ); 869 976 870 977 // Theme navigation in details view. 871 section.container.on( 'click keydown', '.left', function( event ) {978 content.on( 'click keydown', '.left', function( event ) { 872 979 if ( api.utils.isKeydownButNotEnterEvent( event ) ) { 873 980 return; 874 981 } … … 878 985 section.previousTheme(); 879 986 }); 880 987 881 section.container.on( 'click keydown', '.right', function( event ) {988 content.on( 'click keydown', '.right', function( event ) { 882 989 if ( api.utils.isKeydownButNotEnterEvent( event ) ) { 883 990 return; 884 991 } … … 888 995 section.nextTheme(); 889 996 }); 890 997 891 section.container.on( 'click keydown', '.theme-backdrop, .close', function( event ) {998 content.on( 'click keydown', '.theme-backdrop, .close', function( event ) { 892 999 if ( api.utils.isKeydownButNotEnterEvent( event ) ) { 893 1000 return; 894 1001 } … … 899 1006 }); 900 1007 901 1008 var renderScreenshots = _.throttle( _.bind( section.renderScreenshots, this ), 100 ); 902 section.container.on( 'input', '#themes-filter', function( event ) {1009 content.on( 'input', '#themes-filter', function( event ) { 903 1010 var count, 904 1011 term = event.currentTarget.value.toLowerCase().trim().replace( '-', ' ' ), 905 1012 controls = section.controls(); … … 911 1018 renderScreenshots(); 912 1019 913 1020 // Update theme count. 914 count = section.container.find( 'li.customize-control:visible' ).length;915 section.container.find( '.theme-count' ).text( count );1021 count = content.find( 'li.customize-control:visible' ).length; 1022 content.find( '.theme-count' ).text( count ); 916 1023 }); 917 1024 918 1025 // Pre-load the first 3 theme screenshots. … … 948 1055 } 949 1056 950 1057 // Note: there is a second argument 'args' passed 951 var position, scroll, 952 panel = this, 953 section = panel.container.closest( '.accordion-section' ), 1058 var panel = this, 1059 section = panel.content, 954 1060 overlay = section.closest( '.wp-full-overlay' ), 955 1061 container = section.closest( '.wp-full-overlay-sidebar-content' ), 956 siblings = container.find( '.open' ),957 1062 customizeBtn = section.find( '.customize-theme' ), 958 changeBtn = section.find( '.change-theme' ), 959 content = section.find( '.control-panel-content' ); 960 961 if ( expanded ) { 1063 changeBtn = panel.container.find( '.change-theme' ), 1064 currentScrollTop = container.scrollTop(), 1065 previousScrollTop, stateChangeCallback; 962 1066 1067 if ( expanded && ! section.hasClass( 'current-panel' ) ) { 963 1068 // Collapse any sibling sections/panels 964 1069 api.section.each( function ( otherSection ) { 965 1070 if ( otherSection !== panel ) { … … 970 1075 otherPanel.collapse( { duration: 0 } ); 971 1076 }); 972 1077 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' );1078 stateChangeCallback = function() { 1079 changeBtn.attr( 'tabindex', '-1' ); 1080 customizeBtn.attr( 'tabindex', '0' ); 1081 1082 customizeBtn.focus(); 1083 section.css( 'top', '' ); 979 1084 container.scrollTop( 0 ); 980 _.delay( panel.renderScreenshots, 10 ); // Wait for the controls 981 panel.$customizeSidebar.on( 'scroll.customize-themes-section', _.throttle( panel.renderScreenshots, 300 ) ); 1085 982 1086 if ( args.completeCallback ) { 983 1087 args.completeCallback(); 984 1088 } 985 } ); 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 1089 }; 1090 1091 this.animateChangeExpanded( stateChangeCallback ); 1092 1093 // Prevent ugly screen flicker for items that are 'below the fold'. 1094 if ( normalizedTransitionendEventName && 0 < currentScrollTop ) { 1095 section.data( 'previous-scrollTop', currentScrollTop ); 1096 section.css( 'top', currentScrollTop + 'px' ); 1097 } 1098 1099 overlay.addClass( 'in-themes-panel' ); 1100 section.addClass( 'current-panel' ); 1101 1102 } else if ( ! expanded && section.hasClass( 'current-panel' ) ) { 1103 1104 stateChangeCallback = function() { 1105 changeBtn.attr( 'tabindex', '0' ); 1106 customizeBtn.attr( 'tabindex', '-1' ); 1107 1108 changeBtn.focus(); 1109 section.css( 'top', '' ); 1110 994 1111 if ( args.completeCallback ) { 995 1112 args.completeCallback(); 996 1113 } 997 } ); 998 customizeBtn.attr( 'tabindex', '0' ); 999 changeBtn.focus(); 1000 container.scrollTop( 0 ); 1114 }; 1115 1116 this.animateChangeExpanded( stateChangeCallback ); 1117 1118 overlay.removeClass( 'in-themes-panel' ); 1119 section.removeClass( 'current-panel' ); 1120 1121 // Prevent ugly screen flicker for items that are 'below the fold'. 1122 if ( normalizedTransitionendEventName ) { 1123 _.defer( function() { 1124 previousScrollTop = section.data( 'previous-scrollTop' ) || 0; 1125 if ( 0 < currentScrollTop + previousScrollTop ) { 1126 container.scrollTop( previousScrollTop ); 1127 section.css( 'top', previousScrollTop - currentScrollTop + 'px' ); 1128 } 1129 } ); 1130 } 1001 1131 } 1002 1132 }, 1003 1133 1134 1004 1135 /** 1005 * Recalculate the top margin.1136 * Animate pane state change if transitions are supported by the browser. 1006 1137 * 1007 * @since 4.4.0 1008 * @private 1138 * @param {function} completeCallback Function to be called after transition is completed. 1009 1139 */ 1010 _recalculateTopMargin: function() { 1011 api.Panel.prototype._recalculateTopMargin.call( this ); 1140 animateChangeExpanded: function( completeCallback ) { 1141 var content = this.content, 1142 overlay = content.closest( '.wp-full-overlay' ), 1143 affectedElements, transitionEndCallback; 1144 1145 if ( ! normalizedTransitionendEventName ) { 1146 if ( completeCallback ) { 1147 completeCallback(); 1148 } 1149 return; 1150 } 1151 1152 affectedElements = overlay.add( content ); 1153 affectedElements = affectedElements.add( '#customize-info, .customize-pane-parent' ); 1154 1155 transitionEndCallback = function( e ) { 1156 if ( 2 !== e.eventPhase || ! $( e.target ).is( content ) ) { 1157 return; 1158 } 1159 1160 content.off( normalizedTransitionendEventName, transitionEndCallback ); 1161 affectedElements.removeClass( 'busy' ); 1162 1163 if ( completeCallback ) { 1164 completeCallback(); 1165 } 1166 }; 1167 1168 content.on( normalizedTransitionendEventName, transitionEndCallback ); 1169 affectedElements.addClass( 'busy' ); 1012 1170 }, 1013 1171 1014 1172 /** … … 1237 1395 */ 1238 1396 embed: function () { 1239 1397 var panel = this, 1240 parentContainer = $( '#customize-theme-controls > ul' ); // @todo This should be defined elsewhere, and to be configurable 1398 container = $( '#customize-theme-controls' ), 1399 parentContainer = $( '.customize-pane-parent' ); // @todo This should be defined elsewhere, and to be configurable 1241 1400 1242 1401 if ( ! panel.container.parent().is( parentContainer ) ) { 1243 1402 parentContainer.append( panel.container ); 1403 } 1404 if ( ! panel.content.parent().is( panel.container ) ) { 1405 container.append( panel.content ); 1244 1406 panel.renderContent(); 1245 1407 } 1246 1408 1247 api.bind( 'pane-contents-reflowed', _.debounce( function() {1248 panel._recalculateTopMargin();1249 }, 100 ) );1250 1251 1409 panel.deferred.embedded.resolve(); 1252 1410 }, 1253 1411 … … 1270 1428 }); 1271 1429 1272 1430 // Close panel. 1273 panel.cont ainer.find( '.customize-panel-back' ).on( 'click keydown', function( event ) {1431 panel.content.find( '.customize-panel-back' ).on( 'click keydown', function( event ) { 1274 1432 if ( api.utils.isKeydownButNotEnterEvent( event ) ) { 1275 1433 return; 1276 1434 } … … 1281 1439 } 1282 1440 }); 1283 1441 1284 meta = panel.cont ainer.find( '.panel-meta:first' );1442 meta = panel.content.find( '.panel-meta:first' ); 1285 1443 1286 1444 meta.find( '> .accordion-section-title .customize-help-toggle' ).on( 'click keydown', function( event ) { 1287 1445 if ( api.utils.isKeydownButNotEnterEvent( event ) ) { … … 1289 1447 } 1290 1448 event.preventDefault(); // Keep this AFTER the key filter above 1291 1449 1292 meta = panel.container.find( '.panel-meta' );1293 1450 if ( meta.hasClass( 'cannot-expand' ) ) { 1294 1451 return; 1295 1452 } … … 1305 1462 $( this ).attr( 'aria-expanded', true ); 1306 1463 } 1307 1464 }); 1308 1309 1465 }, 1310 1466 1311 1467 /** … … 1359 1515 } 1360 1516 1361 1517 // Note: there is a second argument 'args' passed 1362 var position, scroll, 1363 panel = this, 1364 accordionSection = panel.container.closest( '.accordion-section' ), 1518 var panel = this, 1519 accordionSection = panel.content, 1365 1520 overlay = accordionSection.closest( '.wp-full-overlay' ), 1366 1521 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' ), 1522 topPanel = panel.container.find( '.accordion-section-title' ), 1369 1523 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 ) { 1524 currentScrollTop = container.scrollTop(), 1525 previousScrollTop, stateChangeCallback; 1375 1526 1527 if ( expanded && ! accordionSection.hasClass( 'current-panel' ) ) { 1376 1528 // Collapse any sibling sections/panels 1377 1529 api.section.each( function ( section ) { 1378 1530 if ( panel.id !== section.panel() ) { … … 1385 1537 } 1386 1538 }); 1387 1539 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' ); 1540 stateChangeCallback = function() { 1541 topPanel.attr( 'tabindex', '-1' ); 1542 backBtn.attr( 'tabindex', '0' ); 1543 1544 backBtn.focus(); 1545 accordionSection.css( 'top', '' ); 1395 1546 container.scrollTop( 0 ); 1547 1396 1548 if ( args.completeCallback ) { 1397 1549 args.completeCallback(); 1398 1550 } 1399 } ); 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 1551 }; 1552 1553 this.animateChangeExpanded( stateChangeCallback ); 1554 1555 // Prevent ugly screen flicker for items that are 'below the fold'. 1556 if ( normalizedTransitionendEventName && 0 < currentScrollTop ) { 1557 accordionSection.data( 'previous-scrollTop', currentScrollTop ); 1558 accordionSection.css( 'top', currentScrollTop + 'px' ); 1559 } 1560 1561 overlay.addClass( 'in-sub-panel' ); 1562 accordionSection.addClass( 'current-panel' ); 1563 1564 } else if ( ! expanded && accordionSection.hasClass( 'current-panel' ) ) { 1565 stateChangeCallback = function() { 1566 topPanel.attr( 'tabindex', '0' ); 1567 backBtn.attr( 'tabindex', '-1' ); 1568 1569 topPanel.focus(); 1570 accordionSection.css( 'top', '' ); 1571 1410 1572 if ( args.completeCallback ) { 1411 1573 args.completeCallback(); 1412 1574 } 1413 } ); 1414 topPanel.attr( 'tabindex', '0' ); 1415 backBtn.attr( 'tabindex', '-1' ); 1416 panelTitle.focus(); 1417 container.scrollTop( 0 ); 1575 }; 1576 1577 this.animateChangeExpanded( stateChangeCallback ); 1578 1579 // Prevent ugly screen flicker for items that are 'below the fold'. 1580 if ( normalizedTransitionendEventName ) { 1581 _.defer( function() { 1582 previousScrollTop = accordionSection.data( 'previous-scrollTop' ) || 0; 1583 if ( 0 < currentScrollTop + previousScrollTop ) { 1584 accordionSection.css( 'top', previousScrollTop - currentScrollTop + 'px' ); 1585 container.scrollTop( previousScrollTop ); 1586 } 1587 } ); 1588 } 1589 1590 overlay.removeClass( 'in-sub-panel' ); 1591 accordionSection.removeClass( 'current-panel' ); 1418 1592 } 1419 1593 }, 1420 1594 1421 1595 /** 1422 * Recalculate the top margin.1596 * Animate pane state change if transitions are supported by the browser. 1423 1597 * 1424 * @since 4.4.0 1425 * @private 1598 * @param {function} completeCallback Function to be called after transition is completed. 1426 1599 */ 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 ) ) ); 1600 animateChangeExpanded: function( completeCallback ) { 1601 var panel = this, 1602 content = panel.content, 1603 overlay = content.closest( '.wp-full-overlay' ), 1604 affectedElements, transitionEndCallback; 1605 1606 if ( ! normalizedTransitionendEventName ) { 1607 if ( completeCallback ) { 1608 completeCallback(); 1609 } 1610 return; 1611 } 1612 1613 affectedElements = overlay.add( content ); 1614 affectedElements = affectedElements.add( '#customize-info, .customize-pane-parent' ); 1615 1616 transitionEndCallback = function( e ) { 1617 if ( 2 !== e.eventPhase || ! $( e.target ).is( content ) ) { 1618 return; 1619 } 1620 1621 content.off( normalizedTransitionendEventName, transitionEndCallback ); 1622 affectedElements.removeClass( 'busy' ); 1623 1624 if ( completeCallback ) { 1625 completeCallback(); 1626 } 1627 }; 1628 1629 content.on( normalizedTransitionendEventName, transitionEndCallback ); 1630 affectedElements.addClass( 'busy' ); 1433 1631 }, 1434 1632 1435 1633 /** … … 1450 1648 template = wp.template( 'customize-panel-default-content' ); 1451 1649 } 1452 1650 if ( template && panel.container ) { 1453 panel.cont ainer.find( '.accordion-sub-container' ).html( template( panel.params ) );1651 panel.content.html( template( panel.params ) ); 1454 1652 } 1455 1653 } 1456 1654 }); … … 1626 1824 api.section( sectionId, function ( section ) { 1627 1825 // Wait for the section to be ready/initialized 1628 1826 section.deferred.embedded.done( function () { 1629 parentContainer = section.container.find( 'ul:first' );1827 parentContainer = ( section.content.is( 'ul' ) ) ? section.content : section.content.find( 'ul:first' ); 1630 1828 if ( ! control.container.parent().is( parentContainer ) ) { 1631 1829 parentContainer.append( control.container ); 1632 1830 control.renderContent(); … … 3896 4094 }); 3897 4095 }); 3898 4096 4097 /** 4098 * Sort panels, sections, controls by priorities. Hide empty sections and panels. 4099 * 4100 * @since 4.1.0 4101 */ 4102 api.reflowPaneContents = _.bind( function () { 4103 4104 var appendContainer, activeElement, rootContainers, rootNodes = [], wasReflowed = false; 4105 4106 if ( document.activeElement ) { 4107 activeElement = $( document.activeElement ); 4108 } 4109 4110 // Sort the sections within each panel 4111 api.panel.each( function ( panel ) { 4112 var sections = panel.sections(), 4113 sectionContainers = _.pluck( sections, 'container' ); 4114 rootNodes.push( panel ); 4115 appendContainer = ( panel.content.is( 'ul' ) ) ? panel.content : panel.content.find( 'ul:first' ); 4116 if ( ! api.utils.areElementListsEqual( sectionContainers, appendContainer.children( '[id]' ) ) ) { 4117 _( sections ).each( function ( section ) { 4118 appendContainer.append( section.container ); 4119 } ); 4120 wasReflowed = true; 4121 } 4122 } ); 4123 4124 // Sort the controls within each section 4125 api.section.each( function ( section ) { 4126 var controls = section.controls(), 4127 controlContainers = _.pluck( controls, 'container' ); 4128 if ( ! section.panel() ) { 4129 rootNodes.push( section ); 4130 } 4131 appendContainer = ( section.content.is( 'ul' ) ) ? section.content : section.content.find( 'ul:first' ); 4132 if ( ! api.utils.areElementListsEqual( controlContainers, appendContainer.children( '[id]' ) ) ) { 4133 _( controls ).each( function ( control ) { 4134 appendContainer.append( control.container ); 4135 } ); 4136 wasReflowed = true; 4137 } 4138 } ); 4139 4140 // Sort the root panels and sections 4141 rootNodes.sort( api.utils.prioritySort ); 4142 rootContainers = _.pluck( rootNodes, 'container' ); 4143 appendContainer = $( '.customize-pane-parent' ); //$( '#customize-theme-controls' ).children( 'ul' ); // @todo This should be defined elsewhere, and to be configurable 4144 if ( ! api.utils.areElementListsEqual( rootContainers, appendContainer.children() ) ) { 4145 _( rootNodes ).each( function ( rootNode ) { 4146 appendContainer.append( rootNode.container ); 4147 } ); 4148 wasReflowed = true; 4149 } 4150 4151 // Now re-trigger the active Value callbacks to that the panels and sections can decide whether they can be rendered 4152 api.panel.each( function ( panel ) { 4153 var value = panel.active(); 4154 panel.active.callbacks.fireWith( panel.active, [ value, value ] ); 4155 } ); 4156 api.section.each( function ( section ) { 4157 var value = section.active(); 4158 section.active.callbacks.fireWith( section.active, [ value, value ] ); 4159 } ); 4160 4161 // Restore focus if there was a reflow and there was an active (focused) element 4162 if ( wasReflowed && activeElement ) { 4163 activeElement.focus(); 4164 } 4165 api.trigger( 'pane-contents-reflowed' ); 4166 }, api ); 4167 3899 4168 api.bind( 'ready', api.reflowPaneContents ); 3900 4169 $( [ api.panel, api.section, api.control ] ).each( function ( i, values ) { 3901 4170 var debouncedReflowPaneContents = _.debounce( api.reflowPaneContents, 100 ); -
src/wp-admin/js/customize-nav-menus.js
diff --git a/src/wp-admin/js/customize-nav-menus.js b/src/wp-admin/js/customize-nav-menus.js index e514a0a..fbfc63a 100644
a b 655 655 api.Panel.prototype.attachEvents.call( this ); 656 656 657 657 var panel = this, 658 panelMeta = panel.cont ainer.find( '.panel-meta' ),658 panelMeta = panel.content.find( '.panel-meta' ), 659 659 help = panelMeta.find( '.customize-help-toggle' ), 660 660 content = panelMeta.find( '.customize-panel-description' ), 661 661 options = $( '#screen-options-wrap' ), … … 834 834 835 835 api.bind( 'pane-contents-reflowed', function() { 836 836 // Skip menus that have been removed. 837 if ( ! section.cont ainer.parent().length ) {837 if ( ! section.content.parent().length ) { 838 838 return; 839 839 } 840 section.cont ainer.find( '.menu-item .menu-item-reorder-nav button' ).attr({ 'tabindex': '0', 'aria-hidden': 'false' });841 section.cont ainer.find( '.menu-item.move-up-disabled .menus-move-up' ).attr({ 'tabindex': '-1', 'aria-hidden': 'true' });842 section.cont ainer.find( '.menu-item.move-down-disabled .menus-move-down' ).attr({ 'tabindex': '-1', 'aria-hidden': 'true' });843 section.cont ainer.find( '.menu-item.move-left-disabled .menus-move-left' ).attr({ 'tabindex': '-1', 'aria-hidden': 'true' });844 section.cont ainer.find( '.menu-item.move-right-disabled .menus-move-right' ).attr({ 'tabindex': '-1', 'aria-hidden': 'true' });840 section.content.find( '.menu-item .menu-item-reorder-nav button' ).attr({ 'tabindex': '0', 'aria-hidden': 'false' }); 841 section.content.find( '.menu-item.move-up-disabled .menus-move-up' ).attr({ 'tabindex': '-1', 'aria-hidden': 'true' }); 842 section.content.find( '.menu-item.move-down-disabled .menus-move-down' ).attr({ 'tabindex': '-1', 'aria-hidden': 'true' }); 843 section.content.find( '.menu-item.move-left-disabled .menus-move-left' ).attr({ 'tabindex': '-1', 'aria-hidden': 'true' }); 844 section.content.find( '.menu-item.move-right-disabled .menus-move-right' ).attr({ 'tabindex': '-1', 'aria-hidden': 'true' }); 845 845 } ); 846 846 }, 847 847 … … 952 952 var section = this; 953 953 954 954 if ( expanded ) { 955 wpNavMenu.menuList = section.cont ainer.find( '.accordion-section-content:first' );955 wpNavMenu.menuList = section.content; 956 956 wpNavMenu.targetList = wpNavMenu.menuList; 957 957 958 958 // Add attributes needed by wpNavMenu … … 1014 1014 onChangeExpanded: function( expanded ) { 1015 1015 var section = this, 1016 1016 button = section.container.find( '.add-menu-toggle' ), 1017 content = section.cont ainer.find( '.new-menu-section-content' ),1017 content = section.content, 1018 1018 customizer = section.container.closest( '.wp-full-overlay-sidebar-content' ); 1019 1019 if ( expanded ) { 1020 1020 button.addClass( 'open' ); … … 1028 1028 content.slideUp( 'fast' ); 1029 1029 content.find( '.menu-name-field' ).removeClass( 'invalid' ); 1030 1030 } 1031 }, 1032 1033 /** 1034 * Detach and return the content html, extracted from the container html, if it exists. 1035 * 1036 * @since 1037 */ 1038 getContent: function () { 1039 return this.container.find( 'ul:first' ); 1031 1040 } 1032 1041 }); 1033 1042 … … 1984 1993 */ 1985 1994 ready: function() { 1986 1995 var control = this, 1996 section = api.section( control.section() ), 1987 1997 menuId = control.params.menu_id, 1988 1998 menu = control.setting(), 1989 1999 name, … … 2000 2010 * being deactivated. 2001 2011 */ 2002 2012 control.active.validate = function() { 2003 var value , section = api.section( control.section() );2013 var value; 2004 2014 if ( section ) { 2005 2015 value = section.active(); 2006 2016 } else { … … 2009 2019 return value; 2010 2020 }; 2011 2021 2012 control.$controlSection = control.container.closest( '.control-section' );2022 control.$controlSection = section.container; 2013 2023 control.$sectionContent = control.container.closest( '.accordion-section-content' ); 2014 2024 2015 2025 this._setupModel(); … … 2192 2202 section = api.section( control.section() ); 2193 2203 removeSection = function() { 2194 2204 section.container.remove(); 2205 section.content.remove(); 2195 2206 api.section.remove( section.id ); 2196 2207 }; 2197 2208 … … 2283 2294 return; 2284 2295 } 2285 2296 2286 var section = control.container.closest( '.accordion-section'),2297 var section = api.section( control.section() ), 2287 2298 menuId = control.params.menu_id, 2288 controlTitle = section. find( '.accordion-section-title' ),2289 sectionTitle = section. find( '.customize-section-title h3' ),2290 location = section. find( '.menu-in-location' ),2299 controlTitle = section.container.find( '.accordion-section-title' ), 2300 sectionTitle = section.content.find( '.customize-section-title h3' ), 2301 location = section.container.find( '.menu-in-location' ), 2291 2302 action = sectionTitle.find( '.customize-action' ), 2292 2303 name = displayNavMenuName( menu.name ); 2293 2304 … … 2311 2322 } ); 2312 2323 2313 2324 // Update the nav menu name in all location checkboxes. 2314 section. find( '.customize-control-checkbox input' ).each( function() {2325 section.content.find( '.customize-control-checkbox input' ).each( function() { 2315 2326 if ( $( this ).prop( 'checked' ) ) { 2316 2327 $( '.current-menu-location-name-' + $( this ).data( 'location-id' ) ).text( name ); 2317 2328 } … … 2625 2636 2626 2637 // Focus on the new menu section. 2627 2638 api.section( customizeId ).focus(); // @todo should we focus on the new menu's control and open the add-items panel? Thinking user flow... 2628 2629 // Fix an issue with extra space at top immediately after creating new menu.2630 $( '#menu-to-edit' ).css( 'margin-top', 0 );2631 2639 } 2632 2640 }); 2633 2641 -
src/wp-admin/js/customize-widgets.js
diff --git a/src/wp-admin/js/customize-widgets.js b/src/wp-admin/js/customize-widgets.js index 7598023..51b0672 100644
a b 1529 1529 1530 1530 panel.deferred.embedded.done(function() { 1531 1531 var panelMetaContainer, noRenderedAreasNotice, shouldShowNotice; 1532 panelMetaContainer = panel.cont ainer.find( '.panel-meta' );1532 panelMetaContainer = panel.content.find( '.panel-meta' ); 1533 1533 noRenderedAreasNotice = $( '<div></div>', { 1534 1534 'class': 'no-widget-areas-rendered-notice' 1535 1535 }); -
tests/qunit/wp-admin/js/customize-controls.js
diff --git a/tests/qunit/wp-admin/js/customize-controls.js b/tests/qunit/wp-admin/js/customize-controls.js index d806e46..10c7787 100644
a b jQuery( window ).load( function (){ 211 211 section = wp.customize.section( id ); 212 212 ok( ! section.params.content ); 213 213 ok( !! section.container ); 214 ok( !! section.content ); 214 215 ok( section.container.is( '.control-section.control-section-default' ) ); 215 216 ok( 1 === section.container.find( '> .accordion-section-title' ).length ); 216 ok( 1 === section.container.find( '> .accordion-section-content' ).length ); 217 ok( section.content.is( '.accordion-section-content' ) ); 218 equal( section.container.attr( 'aria-owns' ), section.content.attr( 'id' ) ); 217 219 } ); 218 220 219 221 module( 'Customizer Custom Type (titleless) Section with Template in Fixture' ); … … jQuery( window ).load( function (){ 225 227 section = wp.customize.section( id ); 226 228 ok( ! section.params.content ); 227 229 ok( !! section.container ); 230 ok( !! section.content ); 228 231 ok( section.container.is( '.control-section.control-section-titleless' ) ); 229 232 ok( 0 === section.container.find( '> .accordion-section-title' ).length ); 230 ok( 1 === section.container.find( '> .accordion-section-content' ).length ); 233 ok( section.content.is( '.accordion-section-content' ) ); 234 equal( section.container.attr( 'aria-owns' ), section.content.attr( 'id' ) ); 231 235 } ); 232 236 module( 'Customizer Custom Type Section Lacking Specific Template' ); 233 237 test( 'Fixture section has expected content', function () { … … jQuery( window ).load( function (){ 235 239 section = wp.customize.section( id ); 236 240 ok( ! section.params.content ); 237 241 ok( !! section.container ); 242 ok( !! section.content ); 238 243 ok( section.container.is( '.control-section.control-section-' + section.params.type ) ); 239 244 ok( 1 === section.container.find( '> .accordion-section-title' ).length ); 240 ok( 1 === section.container.find( '> .accordion-section-content' ).length ); 245 ok( section.content.is( '.accordion-section-content' ) ); 246 equal( section.container.attr( 'aria-owns' ), section.content.attr( 'id' ) ); 241 247 } ); 242 248 module( 'Customizer Section lacking any params' ); 243 249 test( 'Fixture section has default params supplied', function () { … … jQuery( window ).load( function (){ 270 276 var panel = wp.customize.panel( 'fixture-panel' ); 271 277 ok( !! panel.params.content ); 272 278 ok( !! panel.container ); 279 ok( !! panel.content ); 273 280 } ); 274 281 test( 'Fixture panel has section among its sections()', function () { 275 282 var panel = wp.customize.panel( 'fixture-panel' ); … … jQuery( window ).load( function (){ 304 311 panel = wp.customize.panel( id ); 305 312 ok( ! panel.params.content ); 306 313 ok( !! panel.container ); 314 ok( !! panel.content ); 307 315 ok( panel.container.is( '.control-panel.control-panel-default' ) ); 308 316 ok( 1 === panel.container.find( '> .accordion-section-title' ).length ); 309 ok( 1 === panel.container.find( '> .control-panel-content' ).length ); 317 ok( panel.content.is( '.control-panel-content' ) ); 318 equal( panel.container.attr( 'aria-owns' ), panel.content.attr( 'id' ) ); 310 319 } ); 311 320 312 321 module( 'Customizer Custom Type Panel (titleless) with Template in Fixture' ); … … jQuery( window ).load( function (){ 318 327 panel = wp.customize.panel( id ); 319 328 ok( ! panel.params.content ); 320 329 ok( !! panel.container ); 330 ok( !! panel.content ); 321 331 ok( panel.container.is( '.control-panel.control-panel-titleless' ) ); 322 332 ok( 0 === panel.container.find( '> .accordion-section-title' ).length ); 323 ok( 1 === panel.container.find( '> .control-panel-content' ).length ); 333 ok( panel.content.is( '.control-panel-content' ) ); 334 equal( panel.container.attr( 'aria-owns' ), panel.content.attr( 'id' ) ); 324 335 } ); 325 336 326 337 module( 'Customizer Custom Type Panel Lacking Specific Template' ); … … jQuery( window ).load( function (){ 329 340 panel = wp.customize.panel( id ); 330 341 ok( ! panel.params.content ); 331 342 ok( !! panel.container ); 343 ok( !! panel.content ); 332 344 ok( panel.container.is( '.control-panel.control-panel-' + panel.params.type ) ); 333 345 ok( 1 === panel.container.find( '> .accordion-section-title' ).length ); 334 ok( 1 === panel.container.find( '> .control-panel-content' ).length ); 346 ok( panel.content.is( '.control-panel-content' ) ); 347 equal( panel.container.attr( 'aria-owns' ), panel.content.attr( 'id' ) ); 335 348 } ); 336 349 module( 'Customizer Panel lacking any params' ); 337 350 test( 'Fixture panel has default params supplied', function () { -
tests/qunit/wp-admin/js/customize-widgets.js
diff --git a/tests/qunit/wp-admin/js/customize-widgets.js b/tests/qunit/wp-admin/js/customize-widgets.js index 225d155..bed93d1 100644
a b jQuery( window ).load( function() { 58 58 ok( panel.extended( api.Widgets.WidgetsPanel ) ); 59 59 60 60 panel.deferred.embedded.done( function() { 61 ok( 1 === panel.cont ainer.find( '.no-widget-areas-rendered-notice' ).length );62 ok( panel.cont ainer.find( '.no-widget-areas-rendered-notice' ).is( ':visible' ) );61 ok( 1 === panel.content.find( '.no-widget-areas-rendered-notice' ).length ); 62 ok( panel.content.find( '.no-widget-areas-rendered-notice' ).is( ':visible' ) ); 63 63 api.section( 'sidebar-widgets-sidebar-1' ).active( true ); 64 64 api.control( 'sidebars_widgets[sidebar-1]' ).active( true ); 65 65 api.trigger( 'pane-contents-reflowed' ); 66 ok( ! panel.cont ainer.find( '.no-widget-areas-rendered-notice' ).is( ':visible' ) );66 ok( ! panel.content.find( '.no-widget-areas-rendered-notice' ).is( ':visible' ) ); 67 67 } ); 68 68 69 69 expect( 4 );