Changeset 35231
- Timestamp:
- 10/16/2015 11:47:56 PM (9 years ago)
- Location:
- trunk
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-admin/css/customize-controls.css
r33912 r35231 124 124 } 125 125 126 #customize-controls .customize-info .customize-panel-description { 126 #customize-controls .customize-info .customize-panel-description, 127 #customize-controls .no-widget-areas-rendered-notice { 127 128 color: #555; 128 129 display: none; … … 130 131 padding: 12px 15px; 131 132 border-top: 1px solid #ddd; 133 } 134 #customize-controls .customize-info .customize-panel-description.open + .no-widget-areas-rendered-notice { 135 border-top: none; 132 136 } 133 137 -
trunk/src/wp-admin/js/customize-controls.js
r34557 r35231 301 301 */ 302 302 onChangeActive: function( active, args ) { 303 var duration, construct = this ;303 var duration, construct = this, expandedOtherPanel; 304 304 if ( args.unchanged ) { 305 305 if ( args.completeCallback ) { … … 310 310 311 311 duration = ( 'resolved' === api.previewer.deferred.active.state() ? args.duration : 0 ); 312 313 if ( construct.extended( api.Panel ) ) { 314 // If this is a panel is not currently expanded but another panel is expanded, do not animate. 315 api.panel.each(function ( panel ) { 316 if ( panel !== construct && panel.expanded() ) { 317 expandedOtherPanel = panel; 318 duration = 0; 319 } 320 }); 321 322 // Collapse any expanded sections inside of this panel first before deactivating. 323 if ( ! active ) { 324 _.each( construct.sections(), function( section ) { 325 section.collapse( { duration: 0 } ); 326 } ); 327 } 328 } 329 312 330 if ( ! $.contains( document, construct.container[0] ) ) { 313 331 // jQuery.fn.slideUp is not hiding an element if it is not in the DOM … … 330 348 } 331 349 } 350 351 // Recalculate the margin-top immediately, not waiting for debounced reflow, to prevent momentary (100ms) vertical jiggle. 352 if ( expandedOtherPanel ) { 353 expandedOtherPanel._recalculateTopMargin(); 354 } 332 355 }, 333 356 … … 379 402 380 403 /** 381 * @param {Boolean} expanded 382 * @param {Object} [params] 383 * @returns {Boolean} false if state already applied 384 */ 385 _toggleExpanded: function ( expanded, params ) { 386 var self = this; 404 * Handle the toggle logic for expand/collapse. 405 * 406 * @param {Boolean} expanded - The new state to apply. 407 * @param {Object} [params] - Object containing options for expand/collapse. 408 * @param {Function} [params.completeCallback] - Function to call when expansion/collapse is complete. 409 * @returns {Boolean} false if state already applied or active state is false 410 */ 411 _toggleExpanded: function( expanded, params ) { 412 var instance = this, previousCompleteCallback; 387 413 params = params || {}; 388 var section = this, previousCompleteCallback = params.completeCallback; 389 params.completeCallback = function () { 414 previousCompleteCallback = params.completeCallback; 415 416 // Short-circuit expand() if the instance is not active. 417 if ( expanded && ! instance.active() ) { 418 return false; 419 } 420 421 params.completeCallback = function() { 390 422 if ( previousCompleteCallback ) { 391 previousCompleteCallback.apply( section, arguments );423 previousCompleteCallback.apply( instance, arguments ); 392 424 } 393 425 if ( expanded ) { 394 section.container.trigger( 'expanded' );426 instance.container.trigger( 'expanded' ); 395 427 } else { 396 section.container.trigger( 'collapsed' );428 instance.container.trigger( 'collapsed' ); 397 429 } 398 430 }; 399 if ( ( expanded && this.expanded.get() ) || ( ! expanded && ! this.expanded.get() ) ) {431 if ( ( expanded && instance.expanded.get() ) || ( ! expanded && ! instance.expanded.get() ) ) { 400 432 params.unchanged = true; 401 self.onChangeExpanded( self.expanded.get(), params );433 instance.onChangeExpanded( instance.expanded.get(), params ); 402 434 return false; 403 435 } else { 404 436 params.unchanged = false; 405 this.expandedArgumentsQueue.push( params );406 this.expanded.set( expanded );437 instance.expandedArgumentsQueue.push( params ); 438 instance.expanded.set( expanded ); 407 439 return true; 408 440 } … … 411 443 /** 412 444 * @param {Object} [params] 413 * @returns {Boolean} false if already expanded 445 * @returns {Boolean} false if already expanded or if inactive. 414 446 */ 415 447 expand: function ( params ) { … … 419 451 /** 420 452 * @param {Object} [params] 421 * @returns {Boolean} false if already collapsed 453 * @returns {Boolean} false if already collapsed. 422 454 */ 423 455 collapse: function ( params ) { … … 540 572 section.panel.bind( inject ); 541 573 inject( section.panel.get() ); // Since a section may never get a panel, assume that it won't ever get one 574 575 section.deferred.embedded.done(function() { 576 // Fix the top margin after reflow. 577 api.bind( 'pane-contents-reflowed', _.debounce( function() { 578 section._recalculateTopMargin(); 579 }, 100 ) ); 580 }); 542 581 }, 543 582 … … 647 686 $( window ).on( 'resize.customizer-section', _.debounce( resizeContentHeight, 100 ) ); 648 687 649 // Fix the top margin after reflow. 650 api.bind( 'pane-contents-reflowed', _.debounce( function() { 651 var offset = ( content.offset().top - headerActionsHeight ); 652 if ( 0 < offset ) { 653 content.css( 'margin-top', ( parseInt( content.css( 'margin-top' ), 10 ) - offset ) ); 654 } 655 }, 100 ) ); 688 section._recalculateTopMargin(); 656 689 }; 657 690 } … … 693 726 args.completeCallback(); 694 727 } 728 } 729 }, 730 731 /** 732 * Recalculate the top margin. 733 * 734 * @since 4.4.0 735 * @private 736 */ 737 _recalculateTopMargin: function() { 738 var section = this, content, offset, headerActionsHeight; 739 content = section.container.find( '.accordion-section-content' ); 740 if ( 0 === content.length ) { 741 return; 742 } 743 headerActionsHeight = $( '#customize-header-actions' ).height(); 744 offset = ( content.offset().top - headerActionsHeight ); 745 if ( 0 < offset ) { 746 content.css( 'margin-top', ( parseInt( content.css( 'margin-top' ), 10 ) - offset ) ); 695 747 } 696 748 } … … 1156 1208 panel.renderContent(); 1157 1209 } 1210 1211 api.bind( 'pane-contents-reflowed', _.debounce( function() { 1212 panel._recalculateTopMargin(); 1213 }, 100 ) ); 1214 1158 1215 panel.deferred.embedded.resolve(); 1159 1216 }, … … 1254 1311 * @param {Object} args 1255 1312 * @param {Boolean} args.unchanged 1256 * @param { Callback} args.completeCallback1313 * @param {Function} args.completeCallback 1257 1314 */ 1258 1315 onChangeExpanded: function ( expanded, args ) { … … 1269 1326 var position, scroll, 1270 1327 panel = this, 1271 section = panel.container.closest( '.accordion-section' ), // This is actually the panel.1272 overlay = section.closest( '.wp-full-overlay' ),1273 container = section.closest( '.wp-full-overlay-sidebar-content' ),1328 accordionSection = panel.container.closest( '.accordion-section' ), 1329 overlay = accordionSection.closest( '.wp-full-overlay' ), 1330 container = accordionSection.closest( '.wp-full-overlay-sidebar-content' ), 1274 1331 siblings = container.find( '.open' ), 1275 1332 topPanel = overlay.find( '#customize-theme-controls > ul > .accordion-section > .accordion-section-title' ), 1276 backBtn = section.find( '.customize-panel-back' ),1277 panelTitle = section.find( '.accordion-section-title' ).first(),1278 content = section.find( '.control-panel-content' ),1333 backBtn = accordionSection.find( '.customize-panel-back' ), 1334 panelTitle = accordionSection.find( '.accordion-section-title' ).first(), 1335 content = accordionSection.find( '.control-panel-content' ), 1279 1336 headerActionsHeight = $( '#customize-header-actions' ).height(); 1280 1337 … … 1298 1355 scroll = container.scrollTop(); 1299 1356 content.css( 'margin-top', ( headerActionsHeight - position - scroll ) ); 1300 section.addClass( 'current-panel' );1357 accordionSection.addClass( 'current-panel' ); 1301 1358 overlay.addClass( 'in-sub-panel' ); 1302 1359 container.scrollTop( 0 ); … … 1308 1365 backBtn.attr( 'tabindex', '0' ); 1309 1366 backBtn.focus(); 1310 1311 // Fix the top margin after reflow. 1312 api.bind( 'pane-contents-reflowed', _.debounce( function() { 1313 content.css( 'margin-top', ( parseInt( content.css( 'margin-top' ), 10 ) - ( content.offset().top - headerActionsHeight ) ) ); 1314 }, 100 ) ); 1367 panel._recalculateTopMargin(); 1315 1368 } else { 1316 1369 siblings.removeClass( 'open' ); 1317 section.removeClass( 'current-panel' );1370 accordionSection.removeClass( 'current-panel' ); 1318 1371 overlay.removeClass( 'in-sub-panel' ); 1319 1372 content.delay( 180 ).hide( 0, function() { … … 1328 1381 container.scrollTop( 0 ); 1329 1382 } 1383 }, 1384 1385 /** 1386 * Recalculate the top margin. 1387 * 1388 * @since 4.4.0 1389 * @private 1390 */ 1391 _recalculateTopMargin: function() { 1392 var panel = this, headerActionsHeight, content, accordionSection; 1393 headerActionsHeight = $( '#customize-header-actions' ).height(); 1394 accordionSection = panel.container.closest( '.accordion-section' ); 1395 content = accordionSection.find( '.control-panel-content' ); 1396 content.css( 'margin-top', ( parseInt( content.css( 'margin-top' ), 10 ) - ( content.offset().top - headerActionsHeight ) ) ); 1330 1397 }, 1331 1398 -
trunk/src/wp-admin/js/customize-widgets.js
r34883 r35231 1507 1507 1508 1508 /** 1509 * wp.customize.Widgets.WidgetsPanel 1510 * 1511 * Customizer panel containing the widget area sections. 1512 * 1513 * @since 4.4.0 1514 */ 1515 api.Widgets.WidgetsPanel = api.Panel.extend({ 1516 1517 /** 1518 * Add and manage the display of the no-rendered-areas notice. 1519 * 1520 * @since 4.4.0 1521 */ 1522 ready: function () { 1523 var panel = this; 1524 1525 api.Panel.prototype.ready.call( panel ); 1526 1527 panel.deferred.embedded.done(function() { 1528 var panelMetaContainer, noRenderedAreasNotice, shouldShowNotice; 1529 panelMetaContainer = panel.container.find( '.panel-meta' ); 1530 noRenderedAreasNotice = $( '<div></div>', { 1531 'class': 'no-widget-areas-rendered-notice' 1532 }); 1533 noRenderedAreasNotice.append( $( '<em></em>', { 1534 text: l10n.noAreasRendered 1535 } ) ); 1536 panelMetaContainer.append( noRenderedAreasNotice ); 1537 1538 shouldShowNotice = function() { 1539 return ( 0 === _.filter( panel.sections(), function( section ) { 1540 return section.active(); 1541 } ).length ); 1542 }; 1543 1544 /* 1545 * Set the initial visibility state for rendered notice. 1546 * Update the visibility of the notice whenever a reflow happens. 1547 */ 1548 noRenderedAreasNotice.toggle( shouldShowNotice() ); 1549 api.previewer.deferred.active.done( function () { 1550 noRenderedAreasNotice.toggle( shouldShowNotice() ); 1551 }); 1552 api.bind( 'pane-contents-reflowed', function() { 1553 var duration = ( 'resolved' === api.previewer.deferred.active.state() ) ? 'fast' : 0; 1554 if ( shouldShowNotice() ) { 1555 noRenderedAreasNotice.slideDown( duration ); 1556 } else { 1557 noRenderedAreasNotice.slideUp( duration ); 1558 } 1559 }); 1560 }); 1561 }, 1562 1563 /** 1564 * Allow an active widgets panel to be contextually active even when it has no active sections (widget areas). 1565 * 1566 * This ensures that the widgets panel appears even when there are no 1567 * sidebars displayed on the URL currently being previewed. 1568 * 1569 * @since 4.4.0 1570 * 1571 * @returns {boolean} 1572 */ 1573 isContextuallyActive: function() { 1574 var panel = this; 1575 return panel.active(); 1576 } 1577 }); 1578 1579 /** 1509 1580 * wp.customize.Widgets.SidebarSection 1510 1581 * … … 1969 2040 } ); 1970 2041 1971 // Register models for custom section and control types 2042 // Register models for custom panel, section, and control types 2043 $.extend( api.panelConstructor, { 2044 widgets: api.Widgets.WidgetsPanel 2045 }); 1972 2046 $.extend( api.sectionConstructor, { 1973 2047 sidebar: api.Widgets.SidebarSection -
trunk/src/wp-includes/class-wp-customize-widgets.php
r35102 r35231 356 356 357 357 $this->manager->add_panel( 'widgets', array( 358 'title' => __( 'Widgets' ), 359 'description' => __( 'Widgets are independent sections of content that can be placed into widgetized areas provided by your theme (commonly called sidebars).' ), 360 'priority' => 110, 358 'type' => 'widgets', 359 'title' => __( 'Widgets' ), 360 'description' => __( 'Widgets are independent sections of content that can be placed into widgetized areas provided by your theme (commonly called sidebars).' ), 361 'priority' => 110, 362 'active_callback' => array( $this, 'is_panel_active' ), 361 363 ) ); 362 364 … … 453 455 454 456 add_filter( 'sidebars_widgets', array( $this, 'preview_sidebars_widgets' ), 1 ); 457 } 458 459 /** 460 * Return whether the widgets panel is active, based on whether there are sidebars registered. 461 * 462 * @since 4.4.0 463 * @access public 464 * 465 * @see WP_Customize_Panel::$active_callback 466 * 467 * @global array $wp_registered_sidebars 468 * @return bool Active. 469 */ 470 public function is_panel_active() { 471 global $wp_registered_sidebars; 472 return ! empty( $wp_registered_sidebars ); 455 473 } 456 474 … … 656 674 'widgetMovedUp' => __( 'Widget moved up' ), 657 675 'widgetMovedDown' => __( 'Widget moved down' ), 676 'noAreasRendered' => __( 'There are no widget areas currently rendered in the preview. Navigate in the preview to a template that makes use of a widget area in order to access its widgets here.' ), 658 677 ), 659 678 'tpl' => array( -
trunk/tests/qunit/fixtures/customize-widgets.js
r34563 r35231 65 65 'description': 'Widgets are independent sections of content that can be placed into widgetized areas provided by your theme (commonly called sidebars).', 66 66 'priority': 110, 67 'type': ' default',67 'type': 'widgets', 68 68 'title': 'Widgets', 69 69 'content': '', -
trunk/tests/qunit/wp-admin/js/customize-controls.js
r32681 r35231 394 394 panelTitle = 'Mock Panel Title'; 395 395 panelDescription = 'Mock panel description'; 396 panelContent = '<li id="accordion-panel- widgets" class="control-section control-panel accordion-section">';396 panelContent = '<li id="accordion-panel-mockPanelId" class="accordion-section control-section control-panel control-panel-default"> <h3 class="accordion-section-title" tabindex="0"> Fixture Panel <span class="screen-reader-text">Press return or enter to open this panel</span> </h3> <ul class="accordion-sub-container control-panel-content"> <li class="panel-meta customize-info accordion-section cannot-expand"> <button class="customize-panel-back" tabindex="-1"><span class="screen-reader-text">Back</span></button> <div class="accordion-section-title"> <span class="preview-notice">You are customizing <strong class="panel-title">Fixture Panel</strong></span> <button class="customize-help-toggle dashicons dashicons-editor-help" tabindex="0" aria-expanded="false"><span class="screen-reader-text">Help</span></button> </div> </li> </ul> </li>'; 397 397 panelData = { 398 398 content: panelContent, -
trunk/tests/qunit/wp-admin/js/customize-widgets.js
r34563 r35231 35 35 ok( 0 === control.container.find( '> .widget' ).length ); 36 36 37 // Preview sets the active state. 38 section.active.set( true ); 39 control.active.set( true ); 40 api.control( 'sidebars_widgets[sidebar-1]' ).active.set( true ); 41 37 42 section.expand(); 38 ok( ! widgetAddedEvent );39 ok( 1 === control.container.find( '> .widget' ).length );43 ok( ! widgetAddedEvent, 'expected widget added event not fired' ); 44 ok( 1 === control.container.find( '> .widget' ).length, 'expected there to be one .widget element in the container' ); 40 45 ok( 0 === control.container.find( '.widget-content' ).children().length ); 41 46 … … 48 53 $( document ).off( 'widget-added' ); 49 54 }); 55 56 test( 'widgets panel should have notice', function() { 57 var panel = api.panel( 'widgets' ); 58 ok( panel.extended( api.Widgets.WidgetsPanel ) ); 59 60 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' ) ); 63 api.section( 'sidebar-widgets-sidebar-1' ).active( true ); 64 api.control( 'sidebars_widgets[sidebar-1]' ).active( true ); 65 api.trigger( 'pane-contents-reflowed' ); 66 ok( ! panel.container.find( '.no-widget-areas-rendered-notice' ).is( ':visible' ) ); 67 } ); 68 69 expect( 4 ); 70 }); 50 71 });
Note: See TracChangeset
for help on using the changeset viewer.