diff --git a/src/wp-admin/css/themes.css b/src/wp-admin/css/themes.css index fba8b89d63..0ef76acc6f 100644 --- a/src/wp-admin/css/themes.css +++ b/src/wp-admin/css/themes.css @@ -1283,6 +1283,7 @@ body.more-filters-opened.filters-applied .theme-browser { .more-filters-container .filtering-by .tag { background: #fff; border: 1px solid #e5e5e5; + -webkit-box-shadow: 0 1px 1px rgba(0,0,0,0.04); box-shadow: 0 1px 1px rgba(0,0,0,0.04); font-size: 11px; margin: 0 5px; diff --git a/src/wp-includes/css/media-views.css b/src/wp-includes/css/media-views.css index 7ee5d1e31e..b216f7f4d9 100644 --- a/src/wp-includes/css/media-views.css +++ b/src/wp-includes/css/media-views.css @@ -1640,10 +1640,8 @@ } .image-details .advanced-toggle { - font-style: italic; color: #666; text-decoration: none; - margin: 20px; display: block; } @@ -1663,6 +1661,39 @@ margin-top: 0; } +.image-details .embed-media-settings .size { + margin-bottom: 4px; +} + +.image-details .custom-size span { + display: block; +} + +.image-details .custom-size label { + display: block; + float: left; +} + +.image-details .custom-size span small { + color: #999; + font-size: inherit; +} + +.image-details .custom-size input { + width: 5em; +} + +.image-details .custom-size .sep { + float: left; + margin: 26px 6px 0 6px; +} + +.image-details .custom-size::after { + content: ''; + display: table; + clear: both; +} + .media-embed .thumbnail { max-width: 100%; max-height: 200px; @@ -1724,7 +1755,8 @@ } .image-details .embed-media-settings .setting input.link-to-custom, -.image-details .embed-media-settings .link-target { +.image-details .embed-media-settings .link-target, +.image-details .embed-media-settings .custom-size { margin-left: 27%; width: 70%; } @@ -2003,8 +2035,8 @@ margin-left: 0; } - .image-details .link-target { - width: 100%; + .image-details .embed-media-settings .custom-size { + margin-left: 20px; } .media-selection { diff --git a/src/wp-includes/js/media-models.js b/src/wp-includes/js/media-models.js index 19e9021810..9aa8031d2f 100644 --- a/src/wp-includes/js/media-models.js +++ b/src/wp-includes/js/media-models.js @@ -369,6 +369,9 @@ window.wp = window.wp || {}; this.on( 'change:size', this.updateSize, this ); this.setLinkTypeFromUrl(); + + this.set( 'aspectRatio', attributes.customWidth / attributes.customHeight ); + this.set( 'originalUrl', attributes.url ); }, bindAttachmentListeners: function() { @@ -447,6 +450,13 @@ window.wp = window.wp || {}; return; } + if ( this.get( 'size' ) === 'custom' ) { + this.set( 'width', this.get( 'customWidth' ) ); + this.set( 'height', this.get( 'customHeight' ) ); + this.set( 'url', this.get( 'originalUrl' ) ); + return; + } + size = this.attachment.get( 'sizes' )[ this.get( 'size' ) ]; if ( ! size ) { diff --git a/src/wp-includes/js/media-views.js b/src/wp-includes/js/media-views.js index def3993369..377f020ea1 100644 --- a/src/wp-includes/js/media-views.js +++ b/src/wp-includes/js/media-views.js @@ -6059,13 +6059,18 @@ events: _.defaults( media.view.Settings.AttachmentDisplay.prototype.events, { 'click .edit-attachment': 'editAttachment', 'click .replace-attachment': 'replaceAttachment', - 'click .advanced-toggle': 'toggleAdvanced' + 'click .advanced-toggle': 'toggleAdvanced', + 'change [data-setting="customWidth"]': 'syncCustomSize', + 'change [data-setting="customHeight"]': 'syncCustomSize', + 'keyup [data-setting="customWidth"]': 'syncCustomSize', + 'keyup [data-setting="customHeight"]': 'syncCustomSize' } ), initialize: function() { // used in AttachmentDisplay.prototype.updateLinkTo this.options.attachment = this.model.attachment; this.listenTo( this.model, 'change:url', this.updateUrl ); this.listenTo( this.model, 'change:link', this.toggleLinkSettings ); + this.listenTo( this.model, 'change:size', this.toggleCustomSize ); media.view.Settings.AttachmentDisplay.prototype.initialize.apply( this, arguments ); }, @@ -6123,6 +6128,29 @@ } }, + toggleCustomSize: function() { + if ( this.model.get( 'size' ) !== 'custom' ) { + this.$( '.custom-size' ).addClass('hidden'); + } else { + this.$( '.custom-size' ).removeClass('hidden'); + } + }, + + syncCustomSize: function( event ) { + var dimension = $( event.target ).data('setting'), + value; + + if ( dimension === 'customWidth' ) { + value = Math.round( 1 / this.model.get( 'aspectRatio' ) * $( event.target ).val() ); + this.model.set( 'customHeight', value, { silent: true } ); + this.$( '[data-setting="customHeight"]' ).val( value ); + } else { + value = Math.round( this.model.get( 'aspectRatio' ) * $( event.target ).val() ); + this.$( '[data-setting="customWidth"]' ).val( value ); + this.model.set( 'customWidth', value, { silent: true } ); + } + }, + toggleAdvanced: function( event ) { var $advanced = $( event.target ).closest( '.advanced' ); event.preventDefault(); diff --git a/src/wp-includes/js/tinymce/plugins/wpeditimage/plugin.js b/src/wp-includes/js/tinymce/plugins/wpeditimage/plugin.js index a5af171c15..b7dcbae59f 100644 --- a/src/wp-includes/js/tinymce/plugins/wpeditimage/plugin.js +++ b/src/wp-includes/js/tinymce/plugins/wpeditimage/plugin.js @@ -123,7 +123,9 @@ tinymce.PluginManager.add( 'wpeditimage', function( editor ) { url: false, height: '', width: '', - size: false, + customWidth: '', + customHeight: '', + size: 'custom', caption: '', alt: '', align: 'none', @@ -139,12 +141,12 @@ tinymce.PluginManager.add( 'wpeditimage', function( editor ) { metadata.url = dom.getAttrib( imageNode, 'src' ); metadata.alt = dom.getAttrib( imageNode, 'alt' ); metadata.title = dom.getAttrib( imageNode, 'title' ); - width = dom.getAttrib( imageNode, 'width' ) || imageNode.width; height = dom.getAttrib( imageNode, 'height' ) || imageNode.height; - metadata.width = parseInt( width, 10 ); metadata.height = parseInt( height, 10 ); + metadata.customWidth = metadata.width; + metadata.customHeight = metadata.height; classes = tinymce.explode( imageNode.className, ' ' ); extraClasses = []; @@ -199,9 +201,13 @@ tinymce.PluginManager.add( 'wpeditimage', function( editor ) { return metadata; } + function hasTextContent( node ) { + return node && !! ( node.textContent || node.innerText ); + } + function updateImage( imageNode, imageData ) { - var classes, className, width, node, html, parent, wrap, - captionNode, dd, dl, id, attrs, linkAttrs, + var classes, className, node, html, parent, wrap, linkNode, + captionNode, dd, dl, id, attrs, linkAttrs, width, height, dom = editor.dom; classes = tinymce.explode( imageData.extraClasses, ' ' ); @@ -216,15 +222,23 @@ tinymce.PluginManager.add( 'wpeditimage', function( editor ) { if ( imageData.attachment_id ) { classes.push( 'wp-image-' + imageData.attachment_id ); - if ( imageData.size ) { + if ( imageData.size && imageData.size !== 'custom' ) { classes.push( 'size-' + imageData.size ); } } + width = imageData.width; + height = imageData.height; + + if ( imageData.size === 'custom' ) { + width = imageData.customWidth; + height = imageData.customHeight; + } + attrs = { src: imageData.url, - width: imageData.width || null, - height: imageData.height || null, + width: width || null, + height: height || null, alt: imageData.alt, title: imageData.title || null, 'class': classes.join( ' ' ) || null @@ -239,31 +253,41 @@ tinymce.PluginManager.add( 'wpeditimage', function( editor ) { 'class': imageData.linkClassName || null }; - if ( imageNode.parentNode.nodeName === 'A' ) { + if ( imageNode.parentNode && imageNode.parentNode.nodeName === 'A' && ! hasTextContent( imageNode.parentNode ) ) { + // Update or remove an existing link wrapped around the image if ( imageData.linkUrl ) { dom.setAttribs( imageNode.parentNode, linkAttrs ); } else { dom.remove( imageNode.parentNode, true ); } } else if ( imageData.linkUrl ) { - html = dom.createHTML( 'a', linkAttrs, dom.getOuterHTML( imageNode ) ); - dom.outerHTML( imageNode, html ); + if ( linkNode = dom.getParent( imageNode, 'a' ) ) { + // The image is inside a link together with other nodes, + // or is nested in another node, move it out + dom.insertAfter( imageNode, linkNode ); + } + + // Add link wrapped around the image + linkNode = dom.create( 'a', linkAttrs ); + imageNode.parentNode.insertBefore( linkNode, imageNode ); + linkNode.appendChild( imageNode ); } captionNode = editor.dom.getParent( imageNode, '.mceTemp' ); - if ( imageNode.parentNode.nodeName === 'A' ) { + if ( imageNode.parentNode && imageNode.parentNode.nodeName === 'A' && ! hasTextContent( imageNode.parentNode ) ) { node = imageNode.parentNode; } else { node = imageNode; } if ( imageData.caption ) { - width = parseInt( imageData.width, 10 ); + id = imageData.attachment_id ? 'attachment_' + imageData.attachment_id : null; - className = 'wp-caption align' + imageData.align; + className = 'wp-caption align' + ( imageData.align || 'none' ); if ( ! editor.getParam( 'wpeditimage_html5_captions' ) ) { + width = parseInt( width, 10 ); width += 10; } @@ -312,7 +336,7 @@ tinymce.PluginManager.add( 'wpeditimage', function( editor ) { } editor.nodeChanged(); - // refresh the toolbar + // Refresh the toolbar addToolbar( imageNode ); } @@ -324,8 +348,6 @@ tinymce.PluginManager.add( 'wpeditimage', function( editor ) { return; } - editor.undoManager.add(); - frame = wp.media({ frame: 'image', state: 'image-details', @@ -333,8 +355,10 @@ tinymce.PluginManager.add( 'wpeditimage', function( editor ) { } ); callback = function( imageData ) { - updateImage( img, imageData ); editor.focus(); + editor.undoManager.transact( function() { + updateImage( img, imageData ); + } ); frame.detach(); }; diff --git a/src/wp-includes/media-template.php b/src/wp-includes/media-template.php index aa2e11f922..905bc6d5d7 100644 --- a/src/wp-includes/media-template.php +++ b/src/wp-includes/media-template.php @@ -689,7 +689,7 @@ function wp_print_media_templates() { <# if ( data.attachment ) { #> <# if ( 'undefined' !== typeof data.attachment.sizes ) { #> -