diff --git a/src/wp-includes/css/media-views.css b/src/wp-includes/css/media-views.css index 0dab53422c..05e01f7e18 100644 --- a/src/wp-includes/css/media-views.css +++ b/src/wp-includes/css/media-views.css @@ -1462,6 +1462,10 @@ padding: 16px; } +.media-frame .imgedit-wrap table { + width: 100%; +} + .media-frame .imgedit-wrap table td { vertical-align: top; padding-top: 0; @@ -1513,10 +1517,49 @@ overflow: auto; } +.image-details .media-modal { + left: 140px; + right: 140px; +} + +.image-details .media-frame-menu { + display: none; +} + +.image-details .media-frame-title, +.image-details .media-frame-content, +.image-details .media-frame-router { + left: 0; +} + .image-details .embed-media-settings { top: 0; + overflow: visible; } +.image-details .column-settings { + width: 44%; + float: left; + margin-right: 20px; +} + +.image-details .column-image { + width: 53%; + float: left; +} + +.image-details .column-image:after { + content: ''; + display: table; + clear: both; +} + +.image-details .image img { + max-width: 100%; + max-height: 500px; +} + + .media-embed .thumbnail { max-width: 100%; max-height: 200px; @@ -1529,10 +1572,6 @@ display: block; } -.media-embed .edit-attachment { - margin-left: 10px; -} - .media-embed .thumbnail:after { content: ''; display: block; @@ -1548,13 +1587,34 @@ .media-embed .setting { width: 100%; - margin-top: 10px; + margin: 10px 0; float: left; display: block; clear: both; } -.media-embed .setting .hidden { +.image-details .setting { + float: none; +} + +.image-details .actions { + margin: 10px 0; +} + +.media-embed .setting input[type="text"], +.media-embed .setting textarea { + display: block; + width: 100%; + max-width: 400px; + margin: 1px 0; +} + +.image-details .setting input[type="text"], +.image-details .setting textarea { + max-width: inherit; +} + +.media-embed .setting input.hidden { display: none; } @@ -1570,12 +1630,19 @@ margin: 2px 0; } -.media-embed .setting input[type="text"], -.media-embed .setting textarea { - display: block; - width: 100%; - max-width: 400px; - margin: 1px 0; +.media-embed-sidebar { + position: absolute; + top: 0; + left: 440px; +} + +.advanced, +.link-settings { + margin-top: 10px; +} + +.advanced .hidden { + display: none; } /* Drag & drop on the editor upload */ @@ -1781,6 +1848,11 @@ top: 40%; } + .image-details .media-modal { + left: 30px; + right: 30px; + } + .media-selection { min-width: 120px; } @@ -1849,6 +1921,12 @@ display: none; } + .image-details .media-frame-title { + display: block; + top: 0; + font-size: 14px; + } + .media-frame-toolbar { position: absolute; bottom: 0px; @@ -1905,6 +1983,10 @@ top: 118px; } + .image-details .media-frame.hide-router .media-frame-content { + top: 40px; + } + .media-frame .attachments-browser { padding-bottom: 300px; } @@ -1939,7 +2021,8 @@ } /* Full-bleed modal */ - .media-modal { + .media-modal, + .image-details .media-modal { position: fixed; top: 0; left: 0; @@ -1975,6 +2058,12 @@ padding-bottom: 52px; } + .image-details .column-settings, + .image-details .column-image { + float: none; + width: 100%; + } + /* Gallery */ .media-frame.hide-router .media-frame-content { top: 73px; diff --git a/src/wp-includes/images/media/archive.png b/src/wp-includes/images/media/archive.png index 4b1962ed3f..2864901ff3 100644 Binary files a/src/wp-includes/images/media/archive.png and b/src/wp-includes/images/media/archive.png differ diff --git a/src/wp-includes/images/media/audio.png b/src/wp-includes/images/media/audio.png index bfcd396bec..455d9f28b0 100644 Binary files a/src/wp-includes/images/media/audio.png and b/src/wp-includes/images/media/audio.png differ diff --git a/src/wp-includes/js/media-views.js b/src/wp-includes/js/media-views.js index e543b7a5be..7bcf5b586b 100644 --- a/src/wp-includes/js/media-views.js +++ b/src/wp-includes/js/media-views.js @@ -761,6 +761,10 @@ initialize: function( options ) { this.image = options.image; media.controller.State.prototype.initialize.apply( this, arguments ); + }, + + activate: function() { + this.frame.modal.$el.addClass('image-details'); } }); @@ -2622,7 +2626,6 @@ }, - renderMenu: function( view ) { var lastState = this.lastState(), previous = lastState && lastState.id, @@ -2677,9 +2680,25 @@ }, renderReplaceImageToolbar: function() { + var frame = this, + lastState = frame.lastState(), + previous = lastState && lastState.id; + this.toolbar.set( new media.view.Toolbar({ controller: this, items: { + back: { + text: l10n.back, + priority: 20, + click: function() { + if ( previous ) { + frame.setState( previous ); + } else { + frame.close(); + } + } + }, + replace: { style: 'primary', text: l10n.replace, @@ -5970,13 +5989,16 @@ className: 'image-details', template: media.template('image-details'), events: _.defaults( media.view.Settings.AttachmentDisplay.prototype.events, { - 'click .edit-attachment': 'editAttachment' + 'click .edit-attachment': 'editAttachment', + 'click .replace-attachment': 'replaceAttachment', + 'click .show-advanced': 'showAdvanced' } ), initialize: function() { // used in AttachmentDisplay.prototype.updateLinkTo this.options.attachment = this.model.attachment; if ( this.model.attachment ) { - this.listenTo( this.model.attachment, 'change:url', this.updateUrl ); + this.listenTo( this.model, 'change:url', this.updateUrl ); + this.listenTo( this.model, 'change:link', this.toggleLinkSettings ); } media.view.Settings.AttachmentDisplay.prototype.initialize.apply( this, arguments ); }, @@ -6001,29 +6023,47 @@ this.model.dfd.done( function() { media.view.Settings.AttachmentDisplay.prototype.render.apply( self, args ); self.resetFocus(); + self.toggleLinkSettings(); } ).fail( function() { self.model.attachment = false; media.view.Settings.AttachmentDisplay.prototype.render.apply( self, args ); self.resetFocus(); + self.toggleLinkSettings(); } ); } else { media.view.Settings.AttachmentDisplay.prototype.render.apply( this, arguments ); setTimeout( function() { self.resetFocus(); }, 10 ); + self.toggleLinkSettings(); } return this; }, resetFocus: function() { - this.$( '.caption textarea' ).focus(); - this.$( '.embed-image-settings' ).scrollTop( 0 ); + this.$( '.link-to-custom' ).blur(); + this.$( '.embed-media-settings' ).scrollTop( 0 ); }, updateUrl: function() { - this.$( '.thumbnail img' ).attr( 'src', this.model.get('url' ) ); + this.$( '.image img' ).attr( 'src', this.model.get('url' ) ); this.$( '.url' ).val( this.model.get('url' ) ); }, + toggleLinkSettings: function() { + if ( this.model.get( 'link' ) === 'none' ) { + this.$( '.link-settings' ).addClass('hidden'); + } else { + this.$( '.link-settings' ).removeClass('hidden'); + } + }, + + showAdvanced: function( event ) { + event.preventDefault(); + $( event.target ).closest('.advanced') + .find( '.hidden' ).removeClass( 'hidden' ); + $( event.target ).remove(); + }, + editAttachment: function( event ) { var editState = this.controller.states.get( 'edit-image' ); @@ -6032,6 +6072,11 @@ editState.set( 'image', this.model.attachment ); this.controller.setState( 'edit-image' ); } + }, + + replaceAttachment: function( event ) { + event.preventDefault(); + this.controller.setState( 'replace-image' ); } }); diff --git a/src/wp-includes/js/tinymce/plugins/wpeditimage/plugin.js b/src/wp-includes/js/tinymce/plugins/wpeditimage/plugin.js index 893d925c58..9f76d4c34c 100644 --- a/src/wp-includes/js/tinymce/plugins/wpeditimage/plugin.js +++ b/src/wp-includes/js/tinymce/plugins/wpeditimage/plugin.js @@ -114,7 +114,7 @@ tinymce.PluginManager.add( 'wpeditimage', function( editor ) { } function extractImageData( imageNode ) { - var classes, metadata, captionBlock, caption, + var classes, metadata, captionBlock, caption, link, dom = editor.dom; // default attributes @@ -123,25 +123,27 @@ tinymce.PluginManager.add( 'wpeditimage', function( editor ) { url: false, height: '', width: '', - size: 'none', + size: false, caption: '', alt: '', align: 'none', link: false, - linkUrl: '' + linkUrl: '', + linkClassName: '', + linkTargetBlank: false, + linkRel: '', + title: '', + className: '' }; metadata.url = dom.getAttrib( imageNode, 'src' ); metadata.alt = dom.getAttrib( imageNode, 'alt' ); + metadata.title = dom.getAttrib( imageNode, 'title' ); metadata.width = parseInt( dom.getAttrib( imageNode, 'width' ), 10 ); metadata.height = parseInt( dom.getAttrib( imageNode, 'height' ), 10 ); + metadata.className = imageNode.className; - //TODO: probably should capture attributes on both the and the so that they can be restored - // when the image and/or caption are updated - // maybe use getAttribs() - - // extract meta data from classes (candidate for turning into a method) - classes = imageNode.className.split( ' ' ); + classes = metadata.className.split( ' ' ); tinymce.each( classes, function( name ) { if ( /^wp-image/.test( name ) ) { @@ -157,7 +159,7 @@ tinymce.PluginManager.add( 'wpeditimage', function( editor ) { } } ); - // extract caption + // Extract caption captionBlock = dom.getParents( imageNode, '.wp-caption' ); if ( captionBlock.length ) { @@ -173,15 +175,19 @@ tinymce.PluginManager.add( 'wpeditimage', function( editor ) { caption = dom.select( 'dd.wp-caption-dd', captionBlock ); if ( caption.length ) { caption = caption[0]; - // need to do some more thinking about this + metadata.caption = editor.serializer.serialize( caption ) .replace( /]*>/g, '$&\n' ).replace( /^

/, '' ).replace( /<\/p>$/, '' ); } } - // extract linkTo + // Extract linkTo if ( imageNode.parentNode && imageNode.parentNode.nodeName === 'A' ) { - metadata.linkUrl = dom.getAttrib( imageNode.parentNode, 'href' ); + link = imageNode.parentNode; + metadata.linkUrl = dom.getAttrib( link, 'href' ); + metadata.linkTargetBlank = dom.getAttrib( link, 'target' ) === '_blank' ? true : false; + metadata.linkRel = dom.getAttrib( link, 'rel' ); + metadata.linkClassName = link.className; } return metadata; @@ -223,7 +229,7 @@ tinymce.PluginManager.add( 'wpeditimage', function( editor ) { nodeToReplace = imageNode.parentNode; } } - // uniqueId isn't super exciting, so maybe we want to use something else + uid = editor.dom.uniqueId( 'wp_' ); editor.dom.setAttrib( node, 'data-wp-replace-id', uid ); editor.dom.replace( node, nodeToReplace ); @@ -246,7 +252,7 @@ tinymce.PluginManager.add( 'wpeditimage', function( editor ) { function createImageAndLink( imageData, mode ) { var classes = [], - props; + attrs, linkAttrs; mode = mode ? mode : 'node'; @@ -261,27 +267,46 @@ tinymce.PluginManager.add( 'wpeditimage', function( editor ) { } } - props = { + attrs = { src: imageData.url, width: imageData.width, height: imageData.height, - alt: imageData.alt + alt: imageData.alt, + title: imageData.title || null }; if ( classes.length ) { - props['class'] = classes.join( ' ' ); + attrs['class'] = classes.join( ' ' ); } if ( imageData.linkUrl ) { - if ( mode === 'node' ) { - return editor.dom.create( 'a', { href: imageData.linkUrl }, editor.dom.createHTML( 'img', props ) ); - } else if ( mode === 'html' ) { - return editor.dom.createHTML( 'a', { href: imageData.linkUrl }, editor.dom.createHTML( 'img', props ) ); + + linkAttrs = { + href: imageData.linkUrl + }; + + if ( imageData.linkRel ) { + linkAttrs.rel = imageData.linkRel; } + + if ( imageData.linkTargetBlank ) { + linkAttrs.target = '_blank'; + } + + if ( imageData.linkClassName ) { + linkAttrs['class'] = imageData.linkClassName; + } + + if ( mode === 'node' ) { + return editor.dom.create( 'a', linkAttrs, editor.dom.createHTML( 'img', attrs ) ); + } else if ( mode === 'html' ) { + return editor.dom.createHTML( 'a', linkAttrs, editor.dom.createHTML( 'img', attrs ) ); + } + } else if ( mode === 'node' ) { - return editor.dom.create( 'img', props ); + return editor.dom.create( 'img', attrs ); } else if ( mode === 'html' ) { - return editor.dom.createHTML( 'img', props ); + return editor.dom.createHTML( 'img', attrs ); } } diff --git a/src/wp-includes/media-template.php b/src/wp-includes/media-template.php index 3751ad7995..40472c6c13 100644 --- a/src/wp-includes/media-template.php +++ b/src/wp-includes/media-template.php @@ -638,101 +638,133 @@ function wp_print_media_templates() {