Changeset 31533
- Timestamp:
- 02/24/2015 08:30:22 PM (10 years ago)
- Location:
- trunk/src
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-admin/css/customize-controls.css
r31505 r31533 826 826 .customize-control-header .new { 827 827 float: right; 828 } 829 830 /** 831 * Themes 832 */ 833 @-webkit-keyframes customize-reload { 834 0% { opacity: 0; } 835 100% { opacity: 1; } 836 } 837 838 @-moz-keyframes customize-reload { 839 0% { opacity: 0; } 840 100% { opacity: 1; } 841 } 842 843 @keyframes customize-reload { 844 0% { opacity: 0; } 845 100% { opacity: 1; } 846 } 847 848 /* #customize-container is reused from customize-loader.js, hence the naming. */ 849 .wp-customizer .customize-loading #customize-container { 850 display: block; 851 -webkit-animation: customize-reload .75s; /* Can't use `transition` because `display` changes here. */ 852 -moz-animation: customize-reload .75s; 853 animation: customize-reload .75s; 854 } 855 856 .customize-themes-panel { 857 display: none; 858 padding: 0 8px; 859 background: #f1f1f1; 860 box-sizing: border-box; 861 -webkit-box-sizing: border-box; 862 -moz-box-sizing: border-box; 863 } 864 865 .control-section.open .customize-themes-panel { 866 display: block; 867 } 868 869 #customize-theme-controls .customize-themes-panel .accordion-section-content { 870 background: transparent; 871 display: block; 872 } 873 874 .customize-control.customize-control-theme { 875 margin-bottom: 8px; 876 } 877 878 .wp-customizer .theme-browser .themes { 879 padding-bottom: 8px; 880 } 881 882 .wp-customizer .theme-browser .theme { 883 margin: 0; 884 width: 100%; 885 } 886 887 .wp-customizer .theme-browser .theme .theme-actions { 888 -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; 889 opacity: 1; 890 } 891 892 #customize-controls h3.theme-name { 893 font-size: 15px; 894 } 895 896 .wp-customizer .theme-browser .theme.active .theme-name { 897 padding-right: 15px; 898 } 899 900 .wp-customizer #themes-filter { 901 width: 100%; 902 } 903 904 /* Panel-like behavior */ 905 #accordion-section-themes .accordion-section-title:after { 906 content: "\f148"; 907 } 908 909 .rtl #accordion-section-themes .accordion-section-title:after { 910 -webkit-transform: rotate(180deg); 911 -ms-transform: rotate(180deg); 912 transform: rotate(180deg); 913 } 914 915 #customize-theme-controls .control-section.current-panel > h3.accordion-section-title { 916 left: 0; 917 } 918 919 .customize-themes-panel.control-panel-content { 920 position: absolute; 921 left: -100%; 922 top: 0; 923 width: 100%; 924 border-top: 1px solid #ddd; 925 } 926 927 .in-themes-panel #customize-info, 928 .in-themes-panel #customize-theme-controls > ul > .accordion-section { 929 left: 100%; 930 } 931 932 .themes-panel-back:before { 933 top: 13px; 934 left: 14px; 935 } 936 937 .in-themes-panel .themes-panel-back { 938 left: 0; 939 } 940 941 .in-sub-panel .themes-panel-back { 942 display: none; 943 } 944 945 .control-panel-back.themes-panel-back:before { 946 content: "\f345"; 947 } 948 949 .rtl .control-panel-back.themes-panel-back:before { 950 content: "\f341"; 951 } 952 953 /* Details View */ 954 .wp-customizer .theme-overlay { 955 display: none; 956 } 957 958 .wp-customizer.modal-open .theme-overlay { 959 position: fixed; 960 left: 0; 961 top: 0; 962 right: 0; 963 bottom: 0; 964 z-index: 109; 965 } 966 967 .wp-customizer .theme-overlay .theme-backdrop { 968 background: rgba( 238, 238, 238, 0.75 ); 969 position: fixed; 970 z-index: 110; 971 } 972 973 .wp-customizer .theme-overlay .theme-wrap { 974 left: 90px; 975 right: 90px; 976 top: 45px; 977 bottom: 45px; 978 z-index: 120; 979 max-width: 1740px; /* To ensure that theme screenshots are not displayed larger than 880px wide. */ 980 } 981 982 .wp-customizer .theme-overlay .theme-actions { 983 text-align: right; /* Because there's only one action, match the pattern of media modals and right-align the action. */ 984 } 985 986 .modal-open .in-themes-panel #customize-controls .wp-full-overlay-sidebar-content { 987 overflow: visible; /* Prevent the top-level Customizer controls from becoming visible when elements on the right of the details modal are focused. */ 988 } 989 990 /* Small Screens */ 991 @media (max-width:850px), (max-height:472px) { 992 .wp-customizer .theme-overlay .theme-wrap { 993 left: 0; 994 right: 0; 995 top: 0; 996 bottom: 0; 997 } 828 998 } 829 999 -
trunk/src/wp-admin/customize.php
r31484 r31533 137 137 </div> 138 138 139 <?php140 $screenshot = $wp_customize->theme()->get_screenshot();141 $cannot_expand = ! ( $wp_customize->is_theme_active() || $screenshot || $wp_customize->theme()->get('Description') );142 ?>143 144 139 <div id="widgets-right"><!-- For Widget Customizer, many widgets try to look for instances under div#widgets-right, so we have to add that ID to a container div in the Customizer for compat --> 145 140 <div class="wp-full-overlay-sidebar-content" tabindex="-1"> 146 <div id="customize-info" class="accordion-section <?php if ( $cannot_expand ) echo ' cannot-expand'; ?>">141 <div id="customize-info" class="accordion-section"> 147 142 <div class="accordion-section-title" aria-label="<?php esc_attr_e( 'Customizer Options' ); ?>" tabindex="0"> 148 143 <span class="preview-notice"><?php 149 if ( ! $wp_customize->is_theme_active() ) { 150 /* translators: %s is the theme name in the Customize/Live Preview pane */ 151 echo sprintf( __( 'You are previewing %s' ), '<strong class="theme-name">' . $wp_customize->theme()->display('Name') . '</strong>' ); 152 } else { 153 /* translators: %s is the site/panel title in the Customize pane */ 154 echo sprintf( __( 'You are customizing %s' ), '<strong class="theme-name site-title">' . get_bloginfo( 'name' ) . '</strong>' ); 155 } 144 echo sprintf( __( 'You are customizing %s' ), '<strong class="theme-name site-title">' . get_bloginfo( 'name' ) . '</strong>' ); 156 145 ?></span> 157 146 </div> 158 <?php if ( ! $cannot_expand ) : ?> 159 <div class="accordion-section-content"> 160 <?php if ( ! $wp_customize->is_theme_active() ) : 161 if ( $screenshot ) : ?> 162 <img class="theme-screenshot" src="<?php echo esc_url( $screenshot ); ?>" /> 163 <?php endif; ?> 164 165 <?php if ( $wp_customize->theme()->get('Description') ): ?> 166 <div class="theme-description"><?php echo $wp_customize->theme()->display('Description'); ?></div> 167 <?php endif; 168 else: 169 echo __( 'The Customizer allows you to preview changes to your site before publishing them. You can also navigate to different pages on your site to preview them.' ); 170 endif; ?> 171 </div> 172 <?php endif; ?> 147 <div class="accordion-section-content"><?php 148 echo __( 'The Customizer allows you to preview changes to your site before publishing them. You can also navigate to different pages on your site to preview them.' ); 149 ?></div> 173 150 </div> 174 151 … … 247 224 'preview' => esc_url_raw( $url ? $url : home_url( '/' ) ), 248 225 'parent' => esc_url_raw( admin_url() ), 249 'activated' => esc_url_raw( admin_url( 'themes.php?activated=true&previewed' ) ),226 'activated' => esc_url_raw( home_url( '/' ) ), 250 227 'ajax' => esc_url_raw( admin_url( 'admin-ajax.php', 'relative' ) ), 251 228 'allowed' => array_map( 'esc_url_raw', $allowed_urls ), -
trunk/src/wp-admin/includes/theme.php
r31363 r31533 487 487 return array_values( $prepared_themes ); 488 488 } 489 490 /** 491 * Print JS templates for the theme-browsing UI in the Customizer. 492 * 493 * @since 4.2.0 494 */ 495 function customize_themes_print_templates() { 496 ?> 497 <script type="text/html" id="tmpl-customize-themes-details-view"> 498 <div class="theme-backdrop"></div> 499 <div class="theme-wrap"> 500 <div class="theme-header"> 501 <button type="button" class="left dashicons dashicons-no"><span class="screen-reader-text"><?php _e( 'Show previous theme' ); ?></span></button> 502 <button type="button" class="right dashicons dashicons-no"><span class="screen-reader-text"><?php _e( 'Show next theme' ); ?></span></button> 503 <button type="button" class="close dashicons dashicons-no"><span class="screen-reader-text"><?php _e( 'Close details dialog' ); ?></span></button> 504 </div> 505 <div class="theme-about"> 506 <div class="theme-screenshots"> 507 <# if ( data.screenshot[0] ) { #> 508 <div class="screenshot"><img src="{{ data.screenshot[0] }}" alt="" /></div> 509 <# } else { #> 510 <div class="screenshot blank"></div> 511 <# } #> 512 </div> 513 514 <div class="theme-info"> 515 <# if ( data.active ) { #> 516 <span class="current-label"><?php _e( 'Current Theme' ); ?></span> 517 <# } #> 518 <h3 class="theme-name">{{{ data.name }}}<span class="theme-version"><?php printf( __( 'Version: %s' ), '{{ data.version }}' ); ?></span></h3> 519 <h4 class="theme-author"><?php printf( __( 'By %s' ), '{{{ data.authorAndUri }}}' ); ?></h4> 520 <p class="theme-description">{{{ data.description }}}</p> 521 522 <# if ( data.parent ) { #> 523 <p class="parent-theme"><?php printf( __( 'This is a child theme of %s.' ), '<strong>{{{ data.parent }}}</strong>' ); ?></p> 524 <# } #> 525 526 <# if ( data.tags ) { #> 527 <p class="theme-tags"><span><?php _e( 'Tags:' ); ?></span> {{ data.tags }}</p> 528 <# } #> 529 </div> 530 </div> 531 532 <div class="theme-actions"> 533 <# if ( ! data.active ) { #> 534 <div class="inactive-theme"> 535 <a href="<?php echo add_query_arg( 'theme', '{{ data.id }}', remove_query_arg( 'theme' ) ); ?>" target="_top" class="button button-primary"><?php _e( 'Live Preview' ); ?></a> 536 </div> 537 <# } #> 538 </div> 539 </div> 540 </script> 541 <?php 542 } 543 add_action( 'customize_controls_print_footer_scripts', 'customize_themes_print_templates' ); -
trunk/src/wp-admin/js/customize-controls.js
r31384 r31533 518 518 content.slideUp( args.duration, args.completeCallback ); 519 519 } 520 } 521 }); 522 523 /** 524 * wp.customize.ThemesSection 525 * 526 * Custom section for themes that functions similarly to a backwards panel, 527 * and also handles the theme-details view rendering and navigation. 528 * 529 * @constructor 530 * @augments wp.customize.Section 531 * @augments wp.customize.Container 532 */ 533 api.ThemesSection = api.Section.extend({ 534 currentTheme: '', 535 overlay: '', 536 template: '', 537 538 /** 539 * @since 4.2.0 540 */ 541 ready: function () { 542 var section = this; 543 section.overlay = section.container.find( '.theme-overlay' ); 544 section.template = wp.template( 'customize-themes-details-view' ); 545 546 // Bind global keyboard events. 547 $( 'body' ).on( 'keyup', function( event ) { 548 if ( ! section.overlay.find( '.theme-wrap' ).is( ':visible' ) ) { 549 return; 550 } 551 552 // Pressing the right arrow key fires a theme:next event 553 if ( 39 === event.keyCode ) { 554 section.nextTheme(); 555 } 556 557 // Pressing the left arrow key fires a theme:previous event 558 if ( 37 === event.keyCode ) { 559 section.previousTheme(); 560 } 561 562 // Pressing the escape key fires a theme:collapse event 563 if ( 27 === event.keyCode ) { 564 section.closeDetails(); 565 } 566 }); 567 }, 568 569 /** 570 * @since 4.2.0 571 */ 572 attachEvents: function () { 573 var meta, section = this; 574 575 // Expand/Collapse section/panel. 576 section.container.find( '.accordion-section-title' ).on( 'click keydown', function( event ) { 577 if ( api.utils.isKeydownButNotEnterEvent( event ) ) { 578 return; 579 } 580 event.preventDefault(); // Keep this AFTER the key filter above 581 582 if ( section.expanded() ) { 583 section.collapse(); 584 } else { 585 section.expand(); 586 } 587 }); 588 589 section.container.find( '.themes-panel-back' ).on( 'click keydown', function( event ) { 590 if ( api.utils.isKeydownButNotEnterEvent( event ) ) { 591 return; 592 } 593 594 event.preventDefault(); // Keep this AFTER the key filter above 595 596 section.collapse(); 597 }); 598 599 // Theme navigation in details view. 600 section.container.on( 'click keydown', '.left', function( event ) { 601 if ( api.utils.isKeydownButNotEnterEvent( event ) ) { 602 return; 603 } 604 605 event.preventDefault(); // Keep this AFTER the key filter above 606 607 section.previousTheme(); 608 }); 609 610 section.container.on( 'click keydown', '.right', function( event ) { 611 if ( api.utils.isKeydownButNotEnterEvent( event ) ) { 612 return; 613 } 614 615 event.preventDefault(); // Keep this AFTER the key filter above 616 617 section.nextTheme(); 618 }); 619 620 section.container.on( 'click keydown', '.theme-backdrop, .close', function( event ) { 621 if ( api.utils.isKeydownButNotEnterEvent( event ) ) { 622 return; 623 } 624 625 event.preventDefault(); // Keep this AFTER the key filter above 626 627 section.closeDetails(); 628 }); 629 630 section.container.on( 'click keydown', '.theme-actions .button', function( event ) { 631 if ( api.utils.isKeydownButNotEnterEvent( event ) ) { 632 return; 633 } 634 635 $( '.wp-full-overlay' ).addClass( 'customize-loading' ); 636 }); 637 638 section.container.on( 'input', '#themes-filter', function( event ) { 639 var term = event.currentTarget.value.toLowerCase().trim().replace( '-', ' ' ), 640 controls = section.controls(); 641 controls.pop(); // Remove the last control (the add-new control). 642 _.each( controls, function( control ) { 643 control.filter( term ); 644 }); 645 // Update theme count. Note that the add-theme tile is a div.customize-control. 646 count = section.container.find( 'li.customize-control:visible' ).length; 647 section.container.find( '.theme-count' ).text( count ); 648 }); 649 }, 650 651 /** 652 * Update UI to reflect expanded state 653 * 654 * @since 4.2.0 655 * 656 * @param {Boolean} expanded 657 * @param {Object} args 658 * @param {Boolean} args.unchanged 659 * @param {Callback} args.completeCallback 660 */ 661 onChangeExpanded: function ( expanded, args ) { 662 663 // Immediately call the complete callback if there were no changes 664 if ( args.unchanged ) { 665 if ( args.completeCallback ) { 666 args.completeCallback(); 667 } 668 return; 669 } 670 671 // Note: there is a second argument 'args' passed 672 var position, scroll, 673 panel = this, 674 section = panel.container.closest( '.accordion-section' ), 675 overlay = section.closest( '.wp-full-overlay' ), 676 container = section.closest( '.accordion-container' ), 677 siblings = container.find( '.open' ), 678 topPanel = overlay.find( '#customize-theme-controls > ul > .accordion-section > .accordion-section-title' ).add( '#customize-info > .accordion-section-title' ), 679 backBtn = overlay.find( '.themes-panel-back' ), 680 panelTitle = section.find( '.accordion-section-title' ).first(), 681 content = section.find( '.control-panel-content' ); 682 683 if ( expanded ) { 684 685 // Collapse any sibling sections/panels 686 api.section.each( function ( otherSection ) { 687 if ( otherSection !== panel ) { 688 otherSection.collapse( { duration: args.duration } ); 689 } 690 }); 691 api.panel.each( function ( otherPanel ) { 692 if ( panel !== otherPanel ) { 693 otherPanel.collapse( { duration: 0 } ); 694 } 695 }); 696 697 content.show( 0, function() { 698 position = content.offset().top; 699 scroll = container.scrollTop(); 700 content.css( 'margin-top', ( 45 - position - scroll ) ); 701 section.addClass( 'current-panel' ); 702 overlay.addClass( 'in-themes-panel' ); 703 container.scrollTop( 0 ); 704 if ( args.completeCallback ) { 705 args.completeCallback(); 706 } 707 } ); 708 topPanel.attr( 'tabindex', '-1' ); 709 backBtn.attr( 'tabindex', '0' ); 710 backBtn.focus(); 711 } else { 712 siblings.removeClass( 'open' ); 713 section.removeClass( 'current-panel' ); 714 overlay.removeClass( 'in-themes-panel' ); 715 content.delay( 180 ).hide( 0, function() { 716 content.css( 'margin-top', 'inherit' ); // Reset 717 if ( args.completeCallback ) { 718 args.completeCallback(); 719 } 720 } ); 721 topPanel.attr( 'tabindex', '0' ); 722 backBtn.attr( 'tabindex', '-1' ); 723 panelTitle.focus(); 724 container.scrollTop( 0 ); 725 } 726 }, 727 728 /** 729 * Advance the modal to the next theme. 730 * 731 * @since 4.2.0 732 */ 733 nextTheme: function () { 734 var section = this; 735 if ( section.getNextTheme() ) { 736 section.showDetails( section.getNextTheme(), function() { 737 section.overlay.find( '.right' ).focus(); 738 } ); 739 } 740 }, 741 742 /** 743 * Get the next theme model. 744 * 745 * @since 4.2.0 746 */ 747 getNextTheme: function () { 748 var control, next; 749 control = api.control( 'theme_' + this.currentTheme ); 750 next = control.container.next( 'li.customize-control-theme' ); 751 if ( ! next.length ) { 752 return false; 753 } 754 next = next[0].id.replace( 'customize-control-', '' ); 755 control = api.control( next ); 756 757 return control.params.theme; 758 }, 759 760 /** 761 * Advance the modal to the previous theme. 762 * 763 * @since 4.2.0 764 */ 765 previousTheme: function () { 766 var section = this; 767 if ( section.getPreviousTheme() ) { 768 section.showDetails( section.getPreviousTheme(), function() { 769 section.overlay.find( '.left' ).focus(); 770 } ); 771 } 772 }, 773 774 /** 775 * Get the previous theme model. 776 * 777 * @since 4.2.0 778 */ 779 getPreviousTheme: function () { 780 var control, previous; 781 control = api.control( 'theme_' + this.currentTheme ); 782 previous = control.container.prev( 'li.customize-control-theme' ); 783 if ( ! previous.length ) { 784 return false; 785 } 786 previous = previous[0].id.replace( 'customize-control-', '' ); 787 control = api.control( previous ); 788 789 return control.params.theme; 790 }, 791 792 /** 793 * Disable buttons when we're viewing the first or last theme. 794 * 795 * @since 4.2.0 796 */ 797 updateLimits: function () { 798 if ( ! this.getNextTheme() ) { 799 this.overlay.find( '.right' ).addClass( 'disabled' ); 800 } 801 if ( ! this.getPreviousTheme() ) { 802 this.overlay.find( '.left' ).addClass( 'disabled' ); 803 } 804 }, 805 806 /** 807 * Render & show the theme details for a given theme model. 808 * 809 * @since 4.2.0 810 * 811 * @param {Object} theme 812 */ 813 showDetails: function ( theme, callback ) { 814 var section = this; 815 callback = callback || function(){}; 816 section.currentTheme = theme.id; 817 section.overlay.html( section.template( theme ) ) 818 .fadeIn( 'fast' ) 819 .focus(); 820 $( 'body' ).addClass( 'modal-open' ); 821 section.containFocus( section.overlay ); 822 section.updateLimits(); 823 callback(); 824 }, 825 826 /** 827 * Close the theme details modal. 828 * 829 * @since 4.2.0 830 */ 831 closeDetails: function ( theme ) { 832 $( 'body' ).removeClass( 'modal-open' ); 833 this.overlay.fadeOut( 'fast' ); 834 api.control( 'theme_' + this.currentTheme ).focus(); 835 }, 836 837 /** 838 * Keep tab focus within the theme details modal. 839 * 840 * @since 4.2.0 841 */ 842 containFocus: function( el ) { 843 var tabbables; 844 845 el.on( 'keydown', function( event ) { 846 847 // Return if it's not the tab key 848 // When navigating with prev/next focus is already handled 849 if ( 9 !== event.keyCode ) { 850 return; 851 } 852 853 // uses jQuery UI to get the tabbable elements 854 tabbables = $( ':tabbable', el ); 855 856 // Keep focus within the overlay 857 if ( tabbables.last()[0] === event.target && ! event.shiftKey ) { 858 tabbables.first().focus(); 859 return false; 860 } else if ( tabbables.first()[0] === event.target && event.shiftKey ) { 861 tabbables.last().focus(); 862 return false; 863 } 864 }); 520 865 } 521 866 }); … … 1410 1755 }); 1411 1756 1757 /** 1758 * wp.customize.ThemeControl 1759 * 1760 * @constructor 1761 * @augments wp.customize.Control 1762 * @augments wp.customize.Class 1763 */ 1764 api.ThemeControl = api.Control.extend({ 1765 1766 /** 1767 * @since 4.2.0 1768 */ 1769 ready: function() { 1770 var control = this; 1771 1772 // Bind details view trigger. 1773 control.container.on( 'click keydown', '.theme', function( event ) { 1774 if ( api.utils.isKeydownButNotEnterEvent( event ) ) { 1775 return; 1776 } 1777 1778 if ( 'button' === event.target.className ) { 1779 return; 1780 } 1781 1782 api.section( control.section() ).showDetails( control.params.theme ); 1783 }); 1784 1785 control.container.on( 'click keydown', '.theme-actions .button', function( event ) { 1786 if ( api.utils.isKeydownButNotEnterEvent( event ) ) { 1787 return; 1788 } 1789 1790 $( '.wp-full-overlay' ).addClass( 'customize-loading' ); 1791 }); 1792 }, 1793 1794 /** 1795 * Show or hide the theme based on the presence of the term in the title, description, and author. 1796 * 1797 * @since 4.2.0 1798 */ 1799 filter: function( term ) { 1800 var control = this, 1801 haystack = control.params.theme.name + ' ' 1802 + control.params.theme.description + ' ' 1803 + control.params.theme.tags + ' ' 1804 + control.params.theme.author; 1805 haystack = haystack.toLowerCase().replace( '-', ' ' ); 1806 if ( -1 !== haystack.search( term ) ) { 1807 control.activate(); 1808 } else { 1809 control.deactivate(); 1810 } 1811 } 1812 }); 1813 1412 1814 // Change objects contained within the main customize object to Settings. 1413 1815 api.defaultConstructor = api.Setting; … … 1854 2256 1855 2257 api.controlConstructor = { 1856 color: api.ColorControl, 1857 upload: api.UploadControl, 1858 image: api.ImageControl, 1859 header: api.HeaderControl, 1860 background: api.BackgroundControl 2258 color: api.ColorControl, 2259 upload: api.UploadControl, 2260 image: api.ImageControl, 2261 header: api.HeaderControl, 2262 background: api.BackgroundControl, 2263 theme: api.ThemeControl 1861 2264 }; 1862 2265 api.panelConstructor = {}; 1863 api.sectionConstructor = {}; 2266 api.sectionConstructor = { 2267 themes: api.ThemesSection 2268 }; 1864 2269 1865 2270 $( function() { … … 2274 2679 $( window ).on( 'beforeunload', function () { 2275 2680 if ( ! api.state( 'saved' )() ) { 2681 var timeout = setTimeout( function() { 2682 overlay.removeClass( 'customize-loading' ); 2683 }, 1 ); 2276 2684 return api.l10n.saveAlert; 2277 2685 } -
trunk/src/wp-includes/admin-bar.php
r31456 r31533 651 651 $wp_admin_bar->add_group( array( 'parent' => 'site-name', 'id' => 'appearance' ) ); 652 652 653 if ( current_user_can( 'switch_themes' ) || current_user_can( 'edit_theme_options' ) )654 $wp_admin_bar->add_menu( array( 'parent' => 'appearance', 'id' => 'themes', 'title' => __('Themes'), 'href' => admin_url('themes.php') ) );655 656 if ( ! current_user_can( 'edit_theme_options' ) )657 return;658 659 653 $current_url = ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; 660 654 $customize_url = add_query_arg( 'url', urlencode( $current_url ), wp_customize_url() ); 655 656 if ( current_user_can( 'switch_themes' ) ) { 657 $wp_admin_bar->add_menu( array( 658 'parent' => 'appearance', 659 'id' => 'themes', 660 'title' => __( 'Themes' ), 661 'href' => admin_url( 'themes.php' ), 662 'meta' => array( 663 'class' => 'hide-if-customize', 664 ), 665 ) ); 666 667 if ( current_user_can( 'customize' ) ) { 668 $wp_admin_bar->add_menu( array( 669 'parent' => 'appearance', 670 'id' => 'customize-themes', 671 'title' => __( 'Themes' ), 672 'href' => add_query_arg( urlencode( 'autofocus[section]' ), 'themes', $customize_url ), // urlencode() needed due to #16859 673 'meta' => array( 674 'class' => 'hide-if-no-customize', 675 ), 676 ) ); 677 } 678 } 679 661 680 if ( current_user_can( 'customize' ) ) { 662 681 $wp_admin_bar->add_menu( array( … … 670 689 ) ); 671 690 add_action( 'wp_before_admin_bar_render', 'wp_customize_support_script' ); 691 } 692 693 if ( ! current_user_can( 'edit_theme_options' ) ) { 694 return; 672 695 } 673 696 -
trunk/src/wp-includes/class-wp-customize-control.php
r31101 r31533 1102 1102 1103 1103 /** 1104 * Customize Theme Control Class 1105 * 1106 * @package WordPress 1107 * @subpackage Customize 1108 * @since 4.2.0 1109 */ 1110 class WP_Customize_Theme_Control extends WP_Customize_Control { 1111 1112 public $type = 'theme'; 1113 public $theme; 1114 1115 /** 1116 * Refresh the parameters passed to the JavaScript via JSON. 1117 * 1118 * @since 4.2.0 1119 * @uses WP_Customize_Control::to_json() 1120 */ 1121 public function to_json() { 1122 parent::to_json(); 1123 $this->json['theme'] = $this->theme; 1124 } 1125 1126 /** 1127 * Don't render the control content from PHP, as it's rendered via JS on load. 1128 * 1129 * @since 4.2.0 1130 */ 1131 public function render_content() {} 1132 1133 /** 1134 * Render a JS template for theme display. 1135 * 1136 * @since 4.2.0 1137 */ 1138 public function content_template() { 1139 ?> 1140 <div class="theme<# if ( data.theme.active ) { #> active<# } #>" tabindex="0" aria-describedby="{{ data.theme.id }}-action {{ data.theme.id }}-name"> 1141 <# if ( data.theme.screenshot[0] ) { #> 1142 <div class="theme-screenshot"> 1143 <img src="{{ data.theme.screenshot[0] }}" alt="" /> 1144 </div> 1145 <# } else { #> 1146 <div class="theme-screenshot blank"></div> 1147 <# } #> 1148 <span class="more-details" id="{{ data.theme.id }}-action"><?php _e( 'Theme Details' ); ?></span> 1149 <div class="theme-author"><?php printf( __( 'By %s' ), '{{ data.theme.author }}' ); ?></div> 1150 1151 <# if ( data.theme.active ) { #> 1152 <h3 class="theme-name" id="{{ data.theme.id }}-name"><span><?php _ex( 'Previewing:', 'theme' ); ?></span> {{ data.theme.name }}</h3> 1153 <# } else { #> 1154 <h3 class="theme-name" id="{{ data.theme.id }}-name">{{ data.theme.name }}</h3> 1155 <# } #> 1156 1157 <# if ( ! data.theme.active ) { #> 1158 <div class="theme-actions"> 1159 <a class="button" href="<?php echo add_query_arg( 'theme', '{{ data.theme.id }}', remove_query_arg( 'theme' ) ); ?>" target="_top"><?php _e( 'Live Preview' ); ?></a> 1160 </div> 1161 <# } #> 1162 </div> 1163 <?php 1164 } 1165 } 1166 1167 /** 1168 * Customize New Theme Control Class 1169 * 1170 * @package WordPress 1171 * @subpackage Customize 1172 * @since 4.2.0 1173 */ 1174 class WP_Customize_New_Theme_Control extends WP_Customize_Control { 1175 1176 /** 1177 * Render the new control. 1178 * 1179 * @since 4.2.0 1180 */ 1181 public function render() { 1182 if ( is_multisite() || ! current_user_can( 'install_themes') ) { 1183 return; 1184 } 1185 ?> 1186 <div class="theme add-new-theme"> 1187 <a href="<?php echo admin_url( 'theme-install.php' ); ?>" target="_top"> 1188 <div class="theme-screenshot"> 1189 <span></span> 1190 </div> 1191 <h3 class="theme-name"><?php _e( 'Add New Theme' ); ?></h3> 1192 </a> 1193 </div> 1194 <?php 1195 } 1196 } 1197 1198 /** 1104 1199 * Widget Area Customize Control Class 1105 1200 * -
trunk/src/wp-includes/class-wp-customize-manager.php
r31421 r31533 1111 1111 $this->register_control_type( 'WP_Customize_Image_Control' ); 1112 1112 $this->register_control_type( 'WP_Customize_Background_Image_Control' ); 1113 $this->register_control_type( 'WP_Customize_Theme_Control' ); 1114 1115 /* Themes */ 1116 1117 $this->add_section( new WP_Customize_Themes_Section( $this, 'themes', array( 1118 'title' => sprintf( __( 'Theme: %s' ), $this->theme()->display('Name') ), 1119 'capability' => 'switch_themes', 1120 'priority' => 0, 1121 ) ) ); 1122 1123 // Themes Setting (unused - the theme is considerably more fundamental to the Customizer experience). 1124 $this->add_setting( new WP_Customize_Filter_Setting( $this, 'active_theme', array( 1125 'capability' => 'switch_themes', 1126 ) ) ); 1127 1128 require_once( ABSPATH . 'wp-admin/includes/theme.php' ); 1129 1130 // Theme Controls. 1131 $themes = wp_prepare_themes_for_js(); 1132 foreach ( $themes as $theme ) { 1133 $theme_id = 'theme_' . $theme['id']; 1134 $this->add_control( new WP_Customize_Theme_Control( $this, $theme_id, array( 1135 'theme' => $theme, 1136 'section' => 'themes', 1137 'settings' => 'active_theme', 1138 ) ) ); 1139 } 1140 1141 $this->add_control( new WP_Customize_New_Theme_Control( $this, 'add_theme', array( 1142 'section' => 'themes', 1143 'settings' => 'active_theme', 1144 ) ) ); 1113 1145 1114 1146 /* Site Title & Tagline */ -
trunk/src/wp-includes/class-wp-customize-section.php
r31126 r31533 313 313 314 314 /** 315 * Customize Themes Section Class. 316 * 317 * A UI container for theme controls, which behaves like a backwards Panel. 318 * 319 * @package WordPress 320 * @subpackage Customize 321 * @since 4.2.0 322 */ 323 class WP_Customize_Themes_Section extends WP_Customize_Section { 324 325 public $type = 'themes'; 326 327 /** 328 * Render the themes section, which behaves like a panel. 329 * 330 * @since 4.2.0 331 */ 332 protected function render() { 333 $classes = 'accordion-section control-section control-section-' . $this->type; 334 ?> 335 <li id="accordion-section-<?php echo esc_attr( $this->id ); ?>" class="<?php echo esc_attr( $classes ); ?>"> 336 <h3 class="accordion-section-title" tabindex="0"> 337 <?php echo esc_html( $this->title ); ?> 338 <span class="screen-reader-text"><?php _e( 'Press return or enter to expand' ); ?></span> 339 </h3> 340 <span class="control-panel-back themes-panel-back" tabindex="-1"><span class="screen-reader-text"><?php _e( 'Back' ); ?></span></span> 341 <div class="customize-themes-panel control-panel-content themes-php"> 342 <h2><?php esc_html_e( 'Themes' ); ?> 343 <span class="title-count theme-count"><?php echo count( $this->controls ) - 1; ?></span> 344 <?php if ( ! is_multisite() && current_user_can( 'install_themes' ) ) : ?> 345 <a href="<?php echo admin_url( 'theme-install.php' ); ?>" target="_top" class="add-new-h2"><?php echo esc_html_x( 'Add New', 'Add new theme' ); ?></a> 346 <?php endif; ?> 347 </h2> 348 <div class="theme-overlay" tabindex="0" role="dialog" aria-label="<?php esc_attr_e( 'Theme details' ); ?>"></div> 349 <div id="customize-container"></div> 350 <?php if ( 6 < count( $this->controls ) ) : ?> 351 <p><label for="themes-filter"> 352 <span class="screen-reader-text"><?php _e( 'Search installed themes...' ); ?></span> 353 <input type="search" id="themes-filter" placeholder="<?php esc_attr_e( 'Search installed themes...' ); ?>" /> 354 </label></p> 355 <?php endif; ?> 356 <div class="theme-browser rendered"> 357 <ul class="themes accordion-section-content"> 358 </ul> 359 </div> 360 </div> 361 </li> 362 <?php } 363 } 364 365 /** 315 366 * Customizer section representing widget area (sidebar). 316 367 * -
trunk/src/wp-includes/version.php
r31351 r31533 12 12 * @global int $wp_db_version 13 13 */ 14 $wp_db_version = 31 351;14 $wp_db_version = 31532; 15 15 16 16 /**
Note: See TracChangeset
for help on using the changeset viewer.