Ticket #21483: 21483.3.diff
File 21483.3.diff, 21.6 KB (added by , 10 years ago) |
---|
-
src/wp-admin/css/customize-controls.css
10 10 font-size: 14px; 11 11 } 12 12 13 #customize-controls img { 14 max-width: 100%; 15 } 16 13 17 #customize-controls .submit { 14 18 text-align: center; 15 19 } … … 414 418 margin-right: 5px; 415 419 } 416 420 421 .customize-control .attachment-thumb.type-icon { 422 float: left; 423 margin-right: 12px; 424 } 425 426 .customize-control .attachment-title { 427 font-weight: bold; 428 margin: 0 0 12px 0; 429 } 430 431 .customize-control .remove-button { 432 margin-left: 8px; 433 vertical-align: middle; 434 } 435 436 .customize-control .thumbnail-audio .attachment-title, 437 .customize-control .thumbnail.thumbnail-audio, 438 .customize-control .thumbnail.thumbnail-video, 439 .customize-control .thumbnail.thumbnail-image { 440 margin-bottom: 8px; 441 } 442 417 443 #customize-preview iframe { 418 444 width: 100%; 419 445 height: 100%; -
src/wp-admin/js/customize-controls.js
883 883 * @augments wp.customize.Class 884 884 */ 885 885 api.UploadControl = api.Control.extend({ 886 ready: function() { 886 887 /** 888 * Set up control and do event bindings. 889 */ 890 ready: function() { 887 891 var control = this; 888 892 889 this.params.removed = this.params.removed || ''; 893 control.setupEvents(); 894 control.setting.bind( function () { control.reRender() } ) 895 }, 890 896 891 this.success = $.proxy( this.success, this ); 897 setupEvents: function() { 898 // Cache buttons for re-use. 899 this.$button = this.container.find( '.upload-button' ); 900 this.$img = this.container.find( '.thumbnail-image img' ); 901 this.$defaultButton = this.container.find( '.default-button' ); 902 this.$removeButton = this.container.find( '.remove-button' ); 892 903 893 this.uploader = $.extend({ 894 container: this.container, 895 browser: this.container.find('.upload'), 896 dropzone: this.container.find('.upload-dropzone'), 897 success: this.success, 898 plupload: {}, 899 params: {} 900 }, this.uploader || {} ); 904 // Shortcut so that we don't have to use _.bind every time we add a callback. 905 _.bindAll( this, 'removeFile', 'reRender', 'openFrame', 'select' ); 901 906 902 if ( control.params.extensions ) { 903 control.uploader.plupload.filters = [{ 904 title: api.l10n.allowedFiles, 905 extensions: control.params.extensions 906 }]; 907 } 907 this.$defaultButton.on( 'click keydown', this.restoreDefault ); 908 this.$removeButton.on( 'click keydown', this.removeFile ); 909 this.$button.on( 'click keydown', this.openFrame ); 910 this.$img.on( 'click keydown', this.openFrame ); 911 }, 908 912 909 if ( control.params.context ) 910 control.uploader.params['post_data[context]'] = this.params.context; 913 /** 914 * Open the media modal. 915 */ 916 openFrame: function( event ) { 917 if ( event.type === 'keydown' && 13 !== event.which ) { // enter 918 return; 919 } 911 920 912 if ( api.settings.theme.stylesheet ) 913 control.uploader.params['post_data[theme]'] = api.settings.theme.stylesheet; 921 event.preventDefault(); 922 923 if ( ! this.frame ) { 924 this.initFrame(); 925 } 914 926 915 this.uploader = new wp.Uploader( this.uploader ); 927 this.frame.open(); 928 }, 916 929 917 this.remover = this.container.find('.remove'); 918 this.remover.on( 'click keydown', function( event ) { 919 if ( isKeydownButNotEnterEvent( event ) ) { 920 return; 921 } 930 /** 931 * Set up the media modal so that it can be reused and accessed when needed. 932 */ 933 initFrame: function() { 934 this.frame = wp.media({ 935 // The title of the media modal. 936 title: this.params.button_labels.frame_title, 937 938 // Restrict to specified mime type. 939 // @todo try to map $extensions to this in PHP? 940 library: { 941 type: this.params.mime_type 942 }, 943 button: { 944 // Change the submit button label. 945 text: this.params.button_labels.frame_button 946 }, 947 multiple: false 948 }); 949 950 // When a file is selected, run a callback. 951 this.frame.on( 'select', this.select ); 952 }, 922 953 923 control.setting.set( control.params.removed ); 924 event.preventDefault(); 925 }); 954 /** 955 * Fired when an attachment is selected in the media modal. Gets the selected 956 * image information, and sets it within the control. 957 */ 958 select: function() { 959 // Get the attachment from the modal frame. 960 var attachment = this.frame.state().get( 'selection' ).first().toJSON(); 961 962 this.params.attachment = attachment; 963 964 // Set the Customizer setting; the callback takes care of rendering. 965 this.setting( attachment.url ); 966 }, 926 967 927 this.removerVisibility = $.proxy( this.removerVisibility, this ); 928 this.setting.bind( this.removerVisibility ); 929 this.removerVisibility( this.setting.get() ); 968 /** 969 * Called on whenever a setting is changed. 970 */ 971 reRender: function() { 972 this.container.html(''); 973 this.renderContent(); 974 this.setupEvents(); 975 // @todo: something else is needed to preview audio/video files 930 976 }, 931 success: function( attachment ) {932 this.setting.set( attachment.get('url') );933 },934 removerVisibility: function( to ) {935 this.remover.toggle( to != this.params.removed );936 }937 });938 977 939 /** 940 * @constructor 941 * @augments wp.customize.UploadControl 942 * @augments wp.customize.Control 943 * @augments wp.customize.Class 944 */ 945 api.ImageControl = api.UploadControl.extend({ 946 ready: function() { 947 var control = this, 948 panels; 949 950 this.uploader = { 951 init: function() { 952 var fallback, button; 953 954 if ( this.supports.dragdrop ) 955 return; 956 957 // Maintain references while wrapping the fallback button. 958 fallback = control.container.find( '.upload-fallback' ); 959 button = fallback.children().detach(); 960 961 this.browser.detach().empty().append( button ); 962 fallback.append( this.browser ).show(); 963 } 964 }; 965 966 api.UploadControl.prototype.ready.call( this ); 967 968 this.thumbnail = this.container.find('.preview-thumbnail img'); 969 this.thumbnailSrc = $.proxy( this.thumbnailSrc, this ); 970 this.setting.bind( this.thumbnailSrc ); 971 972 this.library = this.container.find('.library'); 973 974 // Generate tab objects 975 this.tabs = {}; 976 panels = this.library.find('.library-content'); 977 978 this.library.children('ul').children('li').each( function() { 979 var link = $(this), 980 id = link.data('customizeTab'), 981 panel = panels.filter('[data-customize-tab="' + id + '"]'); 982 983 control.tabs[ id ] = { 984 both: link.add( panel ), 985 link: link, 986 panel: panel 987 }; 988 }); 989 990 // Bind tab switch events 991 this.library.children('ul').on( 'click keydown', 'li', function( event ) { 992 if ( isKeydownButNotEnterEvent( event ) ) { 993 return; 994 } 995 996 var id = $(this).data('customizeTab'), 997 tab = control.tabs[ id ]; 998 999 event.preventDefault(); 1000 1001 if ( tab.link.hasClass('library-selected') ) 1002 return; 1003 1004 control.selected.both.removeClass('library-selected'); 1005 control.selected = tab; 1006 control.selected.both.addClass('library-selected'); 1007 }); 1008 1009 // Bind events to switch image urls. 1010 this.library.on( 'click keydown', 'a', function( event ) { 1011 if ( isKeydownButNotEnterEvent( event ) ) { 1012 return; 1013 } 1014 1015 var value = $(this).data('customizeImageValue'); 1016 1017 if ( value ) { 1018 control.setting.set( value ); 1019 event.preventDefault(); 1020 } 1021 }); 1022 1023 if ( this.tabs.uploaded ) { 1024 this.tabs.uploaded.target = this.library.find('.uploaded-target'); 1025 if ( ! this.tabs.uploaded.panel.find('.thumbnail').length ) 1026 this.tabs.uploaded.both.addClass('hidden'); 978 /** 979 * Reset the setting to the default value. @todo default button instead of remove that calls this. 980 */ 981 restoreDefault: function( event ) { 982 if ( event.type === 'keydown' && 13 !== event.which ) { // enter 983 return; 1027 984 } 1028 985 1029 // Select a tab 1030 panels.each( function() { 1031 var tab = control.tabs[ $(this).data('customizeTab') ]; 986 event.preventDefault(); 987 this.setting( this.params.defaultAttachment.url ); 988 this.params.attachment = this.params.defaultAttachment; 989 }, 1032 990 1033 // Select the first visible tab. 1034 if ( ! tab.link.hasClass('hidden') ) { 1035 control.selected = tab; 1036 tab.both.addClass('library-selected'); 1037 return false; 1038 } 1039 }); 991 /** 992 * Called when the "Remove" link is clicked. Empties the setting. 993 * @param {object} event jQuery Event object 994 */ 995 removeFile: function( event ) { 996 if ( event.type === 'keydown' && 13 !== event.which ) { // enter 997 return; 998 } 1040 999 1041 this.dropdownInit(); 1042 }, 1043 success: function( attachment ) { 1044 api.UploadControl.prototype.success.call( this, attachment ); 1000 event.preventDefault(); 1001 this.params.attachment = {}; 1002 this.setting( '' ); 1003 } 1004 }); 1045 1005 1046 // Add the uploaded image to the uploaded tab.1047 if ( this.tabs.uploaded && this.tabs.uploaded.target.length ) {1048 this.tabs.uploaded.both.removeClass('hidden');1049 1050 // @todo: Do NOT store this on the attachment model. That is bad.1051 attachment.element = $( '<a href="#" class="thumbnail"></a>' )1052 .data( 'customizeImageValue', attachment.get('url') )1053 .append( '<img src="' + attachment.get('url')+ '" />' )1054 .appendTo( this.tabs.uploaded.target );1055 }1056 },1057 thumbnailSrc: function( to ) {1058 if ( /^(https?:)?\/\//.test( to ) )1059 this.thumbnail.prop( 'src', to ).show();1060 else1061 this.thumbnail.hide();1062 }1063 });1064 1065 1006 /** 1066 1007 * @constructor 1067 1008 * @augments wp.customize.Control … … 1702 1643 api.controlConstructor = { 1703 1644 color: api.ColorControl, 1704 1645 upload: api.UploadControl, 1705 image: api.ImageControl,1706 1646 header: api.HeaderControl 1707 1647 }; 1708 1648 api.panelConstructor = {}; -
src/wp-includes/class-wp-customize-control.php
613 613 * @since 3.4.0 614 614 */ 615 615 class WP_Customize_Upload_Control extends WP_Customize_Control { 616 public $type = 'upload'; 617 public $removed = ''; 618 public $context; 619 public $extensions = array(); 616 public $type = 'upload'; 617 public $mime_type = ''; 618 public $button_labels = array( 619 'select' => 'Select File', // @todo PHP doesn't like letting us translate these 620 'change' => 'Change File', 621 'remove' => 'Remove', 622 'frame_title' => 'Select File', 623 'frame_button' => 'Choose File', 624 ); 625 public $removed = ''; // unused 626 public $context; // unused 627 public $extensions = array(); // unused 620 628 621 629 /** 622 630 * Enqueue control related scripts/styles. … … 624 632 * @since 3.4.0 625 633 */ 626 634 public function enqueue() { 627 wp_enqueue_ script( 'wp-plupload');635 wp_enqueue_media(); 628 636 } 629 637 630 638 /** … … 635 643 */ 636 644 public function to_json() { 637 645 parent::to_json(); 646 $this->json['mime_type'] = $this->mime_type; 647 $this->json['button_labels'] = $this->button_labels; 638 648 639 $this->json['removed'] = $this->removed; 649 if ( $this->setting ) { 650 if ( $this->settings['default']->value() ) { 651 // @todo: 652 // generate an attachment object & prepare for js (or fake it - needs all fields used by template) 653 // $this->json['defaultAttachment'] = $default_attachment; 654 } 640 655 641 if ( $this->context ) 642 $this->json['context'] = $this->context; 643 644 if ( $this->extensions ) 645 $this->json['extensions'] = implode( ',', $this->extensions ); 656 // Get the attachment model for the existing file, or make one. 657 if ( $this->value() ) { 658 $attachment_id = attachment_url_to_postid( $this->value() ); 659 if ( $attachment_id ) { 660 $this->json['attachment'] = wp_prepare_attachment_for_js( $attachment_id); 661 } 662 } 663 } 646 664 } 647 665 648 666 /** 649 * Render the control's content.667 * Don't render any content for this control from PHP. 650 668 * 669 * @see WP_Customize_Upload_Control::content_template() 651 670 * @since 3.4.0 652 671 */ 653 public function render_content() { 672 public function render_content() {} 673 674 /** 675 * Render a JS template for the content of the upload control. 676 * 677 * @since 4.1.0 678 */ 679 public function content_template() { 654 680 ?> 655 681 <label> 656 <?php if ( ! empty( $this->label ) ) : ?> 657 <span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span> 658 <?php endif; 659 if ( ! empty( $this->description ) ) : ?> 660 <span class="description customize-control-description"><?php echo $this->description; ?></span> 661 <?php endif; ?> 662 <div> 663 <a href="#" class="button-secondary upload"><?php _e( 'Upload' ); ?></a> 664 <a href="#" class="remove"><?php _e( 'Remove' ); ?></a> 665 </div> 682 <# if ( data.label ) { #> 683 <span class="customize-control-title">{{ data.label }}</span> 684 <# } #> 685 <# if ( data.description ) { #> 686 <span class="description customize-control-description">{{ data.description }}</span> 687 <# } #> 688 689 <# if ( data.attachment && data.attachment.id ) { #> 690 <div class="attachment-media-view {{ data.attachment.orientation }}"> 691 <div class="thumbnail thumbnail-{{ data.attachment.type }}"> 692 <# if ( 'image' === data.attachment.type && data.attachment.sizes && data.attachment.sizes.medium ) { #> 693 <img class="attachment-thumb" src="{{ data.attachment.sizes.medium.url }}" draggable="false" /> 694 <# } else if ( 'image' === data.attachment.type && data.attachment.sizes && data.attachment.sizes.full ) { #> 695 <img class="attachment-thumb" src="{{ data.attachment.sizes.full.url }}" draggable="false" /> 696 <# } else if ( -1 === jQuery.inArray( data.attachment.type, [ 'audio', 'video' ] ) ) { #> 697 <img class="attachment-thumb type-icon" src="{{ data.attachment.icon }}" class="icon" draggable="false" /> 698 <p class="attachment-title">{{ data.attachment.title }}</p> 699 <# } #> 700 701 <# if ( 'audio' === data.attachment.type ) { #> 702 <div class="wp-media-wrapper"> 703 <p class="attachment-title">{{ data.attachment.title }}</p> 704 <audio style="visibility: hidden" controls class="wp-audio-shortcode" width="100%" preload="none"> 705 <source type="{{ data.attachment.mime }}" src="{{ data.attachment.url }}"/> 706 </audio> 707 </div> 708 <# } else if ( 'video' === data.attachment.type ) { 709 var w_rule = h_rule = ''; 710 if ( data.attachment.width ) { 711 w_rule = 'width: ' + data.attachment.width + 'px;'; 712 } else if ( wp.media.view.settings.contentWidth ) { 713 w_rule = 'width: ' + wp.media.view.settings.contentWidth + 'px;'; 714 } 715 if ( data.attachment.height ) { 716 h_rule = 'height: ' + data.attachment.height + 'px;'; 717 } 718 #> 719 <div style="{{ w_rule }}{{ h_rule }}" class="wp-media-wrapper wp-video"> 720 <video controls="controls" class="wp-video-shortcode" preload="metadata" 721 <# if ( data.attachment.width ) { #>width="{{ data.attachment.width }}"<# } #> 722 <# if ( data.attachment.height ) { #>height="{{ data.attachment.height }}"<# } #> 723 <# if ( data.attachment.image && data.attachment.image.src !== data.attachment.icon ) { #>poster="{{ data.attachment.image.src }}"<# } #>> 724 <source type="{{ data.attachment.mime }}" src="{{ data.attachment.url }}"/> 725 </video> 726 </div> 727 <# } #> 728 </div> 729 </div> 730 <a class="button upload-button" href="#"><?php echo $this->button_labels['change']; ?></a> 731 <# if ( data.defaultAttachmet && data.defaultAttachment.id !== data.attachment.id ) { #> 732 <a class="default-button remove-button" href="#"><?php echo $this->button_labels['default']; ?></a> 733 <# } else { #> 734 <a class="remove-button" href="#"><?php echo $this->button_labels['remove']; ?></a> 735 <# } #> 736 <# } else { #> 737 <a class="button upload-button" href="#"><?php echo $this->button_labels['select']; ?></a> 738 <# } #> 666 739 </label> 667 740 <?php 668 741 } … … 676 749 * @since 3.4.0 677 750 */ 678 751 class WP_Customize_Image_Control extends WP_Customize_Upload_Control { 679 public $type = 'image'; 680 public $get_url; 681 public $statuses; 682 public $extensions = array( 'jpg', 'jpeg', 'gif', 'png' ); 752 public $mime_type = 'image'; 753 public $button_labels = array( 754 'select' => 'Select Image', // @todo PHP doesn't like letting us translate these 755 'change' => 'Change Image', 756 'remove' => 'Remove', 757 'frame_title' => 'Select Image', 758 'frame_button' => 'Choose Image', 759 ); 683 760 684 protected $tabs = array();685 686 761 /** 687 * Constructor.688 *689 * @since 3.4.0690 * @uses WP_Customize_Upload_Control::__construct()691 *692 * @param WP_Customize_Manager $manager693 * @param string $id694 * @param array $args695 */696 public function __construct( $manager, $id, $args ) {697 $this->statuses = array( '' => __('No Image') );698 699 parent::__construct( $manager, $id, $args );700 701 $this->add_tab( 'upload-new', __('Upload New'), array( $this, 'tab_upload_new' ) );702 $this->add_tab( 'uploaded', __('Uploaded'), array( $this, 'tab_uploaded' ) );703 704 // Early priority to occur before $this->manager->prepare_controls();705 add_action( 'customize_controls_init', array( $this, 'prepare_control' ), 5 );706 }707 708 /**709 * Prepares the control.710 *711 * If no tabs exist, removes the control from the manager.712 *713 762 * @since 3.4.2 763 * @deprecated 4.1.0 714 764 */ 715 public function prepare_control() { 716 if ( ! $this->tabs ) 717 $this->manager->remove_control( $this->id ); 718 } 765 public function prepare_control() {} 719 766 720 767 /** 721 * Refresh the parameters passed to the JavaScript via JSON.722 *723 768 * @since 3.4.0 724 * @uses WP_Customize_Upload_Control::to_json() 725 */ 726 public function to_json() { 727 parent::to_json(); 728 $this->json['statuses'] = $this->statuses; 729 } 730 731 /** 732 * Render the control's content. 769 * @deprecated 4.1.0 733 770 * 734 * @since 3.4.0735 */736 public function render_content() {737 $src = $this->value();738 if ( isset( $this->get_url ) )739 $src = call_user_func( $this->get_url, $src );740 741 ?>742 <div class="customize-image-picker">743 <?php if ( ! empty( $this->label ) ) : ?>744 <span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span>745 <?php endif;746 if ( ! empty( $this->description ) ) : ?>747 <span class="description customize-control-description"><?php echo $this->description; ?></span>748 <?php endif; ?>749 750 <div class="customize-control-content">751 <div class="dropdown preview-thumbnail" tabindex="0">752 <div class="dropdown-content">753 <?php if ( empty( $src ) ): ?>754 <img style="display:none;" />755 <?php else: ?>756 <img src="<?php echo esc_url( set_url_scheme( $src ) ); ?>" />757 <?php endif; ?>758 <div class="dropdown-status"></div>759 </div>760 <div class="dropdown-arrow"></div>761 </div>762 </div>763 764 <div class="library">765 <ul>766 <?php foreach ( $this->tabs as $id => $tab ): ?>767 <li data-customize-tab='<?php echo esc_attr( $id ); ?>' tabindex='0'>768 <?php echo esc_html( $tab['label'] ); ?>769 </li>770 <?php endforeach; ?>771 </ul>772 <?php foreach ( $this->tabs as $id => $tab ): ?>773 <div class="library-content" data-customize-tab='<?php echo esc_attr( $id ); ?>'>774 <?php call_user_func( $tab['callback'] ); ?>775 </div>776 <?php endforeach; ?>777 </div>778 779 <div class="actions">780 <a href="#" class="remove"><?php _e( 'Remove Image' ); ?></a>781 </div>782 </div>783 <?php784 }785 786 /**787 * Add a tab to the control.788 *789 * @since 3.4.0790 *791 771 * @param string $id 792 772 * @param string $label 793 773 * @param mixed $callback 794 774 */ 795 public function add_tab( $id, $label, $callback ) { 796 $this->tabs[ $id ] = array( 797 'label' => $label, 798 'callback' => $callback, 799 ); 800 } 775 public function add_tab( $id, $label, $callback ) {} 801 776 802 777 /** 803 * Remove a tab from the control.804 *805 778 * @since 3.4.0 779 * @deprecated 4.1.0 806 780 * 807 781 * @param string $id 808 782 */ 809 public function remove_tab( $id ) { 810 unset( $this->tabs[ $id ] ); 811 } 783 public function remove_tab( $id ) {} 812 784 813 785 /** 814 786 * @since 3.4.0 815 */ 816 public function tab_upload_new() { 817 if ( ! _device_can_upload() ) { 818 echo '<p>' . sprintf( __('The web browser on your device cannot be used to upload files. You may be able to use the <a href="%s">native app for your device</a> instead.'), 'https://apps.wordpress.org/' ) . '</p>'; 819 } else { 820 ?> 821 <div class="upload-dropzone"> 822 <?php _e('Drop a file here or <a href="#" class="upload">select a file</a>.'); ?> 823 </div> 824 <div class="upload-fallback"> 825 <span class="button-secondary"><?php _e('Select File'); ?></span> 826 </div> 827 <?php 828 } 829 } 830 831 /** 832 * @since 3.4.0 833 */ 834 public function tab_uploaded() { 835 ?> 836 <div class="uploaded-target"></div> 837 <?php 838 } 839 840 /** 841 * @since 3.4.0 787 * @deprecated 4.1.0 842 788 * 843 789 * @param string $url 844 790 * @param string $thumbnail_url 845 791 */ 846 public function print_tab_image( $url, $thumbnail_url = null ) { 847 $url = set_url_scheme( $url ); 848 $thumbnail_url = ( $thumbnail_url ) ? set_url_scheme( $thumbnail_url ) : $url; 849 ?> 850 <a href="#" class="thumbnail" data-customize-image-value="<?php echo esc_url( $url ); ?>"> 851 <img src="<?php echo esc_url( $thumbnail_url ); ?>" /> 852 </a> 853 <?php 854 } 792 public function print_tab_image( $url, $thumbnail_url = null ) {} 855 793 } 856 794 857 795 /** -
src/wp-includes/class-wp-customize-manager.php
970 970 971 971 /* Control Types (custom control classes) */ 972 972 $this->register_control_type( 'WP_Customize_Color_Control' ); 973 $this->register_control_type( 'WP_Customize_Upload_Control' ); 974 $this->register_control_type( 'WP_Customize_Image_Control' ); 973 975 974 976 /* Site Title & Tagline */ 975 977