diff --git a/Gruntfile.js b/Gruntfile.js index 38904c6dac170..7d6981248f199 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -332,6 +332,7 @@ module.exports = function(grunt) { [ WORKING_DIR + 'wp-admin/js/tags-suggest.js' ]: [ './src/js/_enqueues/admin/tags-suggest.js' ], [ WORKING_DIR + 'wp-admin/js/tags.js' ]: [ './src/js/_enqueues/admin/tags.js' ], [ WORKING_DIR + 'wp-admin/js/site-health.js' ]: [ './src/js/_enqueues/admin/site-health.js' ], + [ WORKING_DIR + 'wp-admin/js/site-icon.js' ]: [ './src/js/_enqueues/admin/site-icon.js' ], [ WORKING_DIR + 'wp-admin/js/privacy-tools.js' ]: [ './src/js/_enqueues/admin/privacy-tools.js' ], [ WORKING_DIR + 'wp-admin/js/theme-plugin-editor.js' ]: [ './src/js/_enqueues/wp/theme-plugin-editor.js' ], [ WORKING_DIR + 'wp-admin/js/theme.js' ]: [ './src/js/_enqueues/wp/theme.js' ], diff --git a/src/js/_enqueues/admin/site-icon.js b/src/js/_enqueues/admin/site-icon.js new file mode 100644 index 0000000000000..5b4bc28a2044f --- /dev/null +++ b/src/js/_enqueues/admin/site-icon.js @@ -0,0 +1,138 @@ +(function($) { + var frame; + + function calculateImageSelectOptions ( attachment ) { + var realWidth = attachment.get( 'width' ), + realHeight = attachment.get( 'height' ), + xInit = 512, + yInit = 512, + ratio = xInit / yInit, + xImg = xInit, + yImg = yInit, + x1, y1, imgSelectOptions; + + if ( realWidth / realHeight > ratio ) { + yInit = realHeight; + xInit = yInit * ratio; + } else { + xInit = realWidth; + yInit = xInit / ratio; + } + + x1 = ( realWidth - xInit ) / 2; + y1 = ( realHeight - yInit ) / 2; + + imgSelectOptions = { + aspectRatio: xInit + ':' + yInit, + handles: true, + keys: true, + instance: true, + persistent: true, + imageWidth: realWidth, + imageHeight: realHeight, + minWidth: xImg > xInit ? xInit : xImg, + minHeight: yImg > yInit ? yInit : yImg, + x1: x1, + y1: y1, + x2: xInit + x1, + y2: yInit + y1 + }; + + return imgSelectOptions; + } + + $( function() { + // Build the choose from library frame. + $( '#choose-from-library-link' ).on( 'click', function() { + var $el = $(this); + + // Create the media frame. + frame = wp.media({ + button: { + // Set the text of the button. + text: $el.data('update'), + // Don't close, we might need to crop. + close: false + }, + states: [ + new wp.media.controller.Library({ + title: $el.data( 'choose' ), + library: wp.media.query({ type: 'image' }), + date: false, + suggestedWidth: $el.data( 'size' ), + suggestedHeight: $el.data( 'size' ) + }), + new wp.media.controller.SiteIconCropper({ + control: { + params: { + width: $el.data( 'size' ), + height: $el.data( 'size' ) + } + }, + imgSelectOptions: calculateImageSelectOptions + }) + ] + }); + + frame.on( 'cropped', function( attachment) { + $( '#site_icon_hidden_field' ).val(attachment.id); + switchToUpdate(attachment.url); + frame.close(); + // Start over with a frame that is so fresh and so clean clean. + frame = null; + }); + + // When an image is selected, run a callback. + frame.on( 'select', function() { + // Grab the selected attachment. + var attachment = frame.state().get('selection').first(); + + if ( attachment.attributes.height === $el.data('size') && $el.data('size') === attachment.attributes.width ) { + // Set the value of the hidden input to the attachment id. + $( '#site_icon_hidden_field').val(attachment.id); + switchToUpdate(attachment.attributes.url); + frame.close(); + } else { + frame.setState( 'cropper' ); + } + }); + + frame.open(); + }); + }); + + function switchToUpdate( url ){ + // Set site-icon-img src to the url and remove the hidden class. + $( '#site-icon-preview').find('img').not('.browser-preview').each( function(i, img ){ + $(img).attr('src', url ); + }); + $( '#site-icon-preview' ).removeClass( 'hidden' ); + // Remove hidden class from remove. + $( '#js-remove-site-icon' ).removeClass( 'hidden' ); + // If the button is not in the update state, swap the classes. + if( $( '#choose-from-library-link' ).attr( 'data-state' ) !== '1' ){ + var classes = $( '#choose-from-library-link' ).attr( 'class' ); + $( '#choose-from-library-link' ).attr( 'class', $( '#choose-from-library-link' ).attr('data-alt-classes') ); + $( '#choose-from-library-link' ).attr( 'data-alt-classes', classes ); + $( '#choose-from-library-link' ).attr( 'data-state', '1' ); + } + + // swap the text of the button + $( '#choose-from-library-link' ).text( $( '#choose-from-library-link' ).attr( 'data-update-text' ) ); + } + + $( '#js-remove-site-icon' ).on( 'click', function() { + $( '#site_icon_hidden_field' ).val( 'false' ); + $( '#site-icon-preview' ).toggleClass( 'hidden' ); + $( this ).toggleClass( 'hidden' ); + + var classes = $( '#choose-from-library-link' ).attr( 'class' ); + $( '#choose-from-library-link' ).attr( 'class', $( '#choose-from-library-link' ).attr( 'data-alt-classes' ) ); + $( '#choose-from-library-link' ).attr( 'data-alt-classes', classes ); + + // Swap the text of the button. + $( '#choose-from-library-link' ).text( $( '#choose-from-library-link' ).attr( 'data-choose-text' ) ); + // Set the state of the button so it can be changed on new icon. + $( '#choose-from-library-link' ).attr( 'data-state', ''); + }); +}(jQuery)); diff --git a/src/wp-admin/css/forms.css b/src/wp-admin/css/forms.css index e6610cac47ea9..db76d6cb05e7a 100644 --- a/src/wp-admin/css/forms.css +++ b/src/wp-admin/css/forms.css @@ -789,6 +789,42 @@ ul#add-to-blog-users { outline: 2px solid transparent; } +.button-add-site-icon{ + width: 100%; + cursor: pointer; + text-align: center; + border: 1px dashed #c3c4c7; + box-sizing: border-box; + padding: 9px 0; + line-height: 1.6; + max-width: 270px; +} + +.button-add-site-icon:focus, +.button-add-site-icon:hover{ + background: white; +} + +.site-icon-section .favicon-preview{ + float: left; +} +.site-icon-section .app-icon-preview{ + float: left; + margin: 0 20px; +} + +.site-icon-section .site-icon-preview img{ + max-width: 100%; +} + +.button-ad-site-icon:focus{ + background-color: #fff; + border-color: #3582c4; + border-style: solid; + box-shadow: 0 0 0 1px #3582c4; + outline: 2px solid transparent; +} + /*------------------------------------------------------------------------------ 15.0 - Comments Screen ------------------------------------------------------------------------------*/ diff --git a/src/wp-admin/css/site-icon.css b/src/wp-admin/css/site-icon.css index eae9a576357a8..7c6ce8663e597 100644 --- a/src/wp-admin/css/site-icon.css +++ b/src/wp-admin/css/site-icon.css @@ -7,6 +7,7 @@ overflow: hidden; position: relative; max-width: 180px; + float: left; } .site-icon-preview .favicon, @@ -52,3 +53,20 @@ .customize-control-site_icon .app-icon-preview { margin-top: 9px; } + +.site-icon-section button.reset { + color: #b32d2e; + text-decoration: none; + border-color: transparent; + box-shadow: none; + background: transparent; + margin: 0 10px; +} + +.site-icon-section button.reset:focus, +.site-icon-section button.reset:hover { + background: #b32d2e; + color: #fff; + border-color: #b32d2e; + box-shadow: 0 0 0 1px #b32d2e; +} diff --git a/src/wp-admin/options-general.php b/src/wp-admin/options-general.php index 490a138580c5f..a516757327a8d 100644 --- a/src/wp-admin/options-general.php +++ b/src/wp-admin/options-general.php @@ -97,7 +97,86 @@

- + + + + +
+
+ +
+ Preview as a browser icon +
+ +
+ Preview as an app icon +
+ +

+ + +

+ +

+ +

+

+ 512 × 512' ); + ?> +

+ + + + + array( 'blogname', 'blogdescription', + 'site_icon', 'gmt_offset', 'date_format', 'time_format', diff --git a/src/wp-includes/css/media-views.css b/src/wp-includes/css/media-views.css index c681f6df78d77..ab392ef890b36 100644 --- a/src/wp-includes/css/media-views.css +++ b/src/wp-includes/css/media-views.css @@ -849,6 +849,7 @@ height: 100%; } +.options-general-php .crop-content.site-icon, .wp-customizer:not(.mobile) .media-frame-content .crop-content.site-icon { margin-right: 300px; } @@ -2560,6 +2561,10 @@ width: 230px; } + .options-general-php .crop-content.site-icon { + margin-right: 262px; + } + .attachments-browser .attachments, .attachments-browser .uploader-inline, .attachments-browser .media-toolbar, @@ -2827,6 +2832,10 @@ position: fixed; } + .options-general-php .crop-content.site-icon { + margin-right: 0; + } + .media-sidebar { z-index: 1900; max-width: 70%; diff --git a/src/wp-includes/script-loader.php b/src/wp-includes/script-loader.php index 932fcfc06c6c0..f41da6eff3a5c 100644 --- a/src/wp-includes/script-loader.php +++ b/src/wp-includes/script-loader.php @@ -849,6 +849,8 @@ function wp_default_scripts( $scripts ) { $scripts->add( 'wp-lists', "/wp-includes/js/wp-lists$suffix.js", array( 'wp-ajax-response', 'jquery-color' ), false, 1 ); + $scripts->add( 'site-icon', '/wp-admin/js/site-icon.js', array( 'jquery', 'jcrop' ), false, 1 ); + // WordPress no longer uses or bundles Prototype or script.aculo.us. These are now pulled from an external source. $scripts->add( 'prototype', 'https://ajax.googleapis.com/ajax/libs/prototype/1.7.1.0/prototype.js', array(), '1.7.1' ); $scripts->add( 'scriptaculous-root', 'https://ajax.googleapis.com/ajax/libs/scriptaculous/1.9.0/scriptaculous.js', array( 'prototype' ), '1.9.0' );