From 4726669b3f08e4aca199c8c1e72b9e2422fd3803 Mon Sep 17 00:00:00 2001 From: Scott Taylor Date: Thu, 5 Mar 2015 05:59:10 +0000 Subject: [PATCH] Allow inline editing of `width` and `height` parameters while previewing an embed in the media modal: * Use `wp.shortcode()` instead of manually constructing a shortcode in `views/embed/link` * Allow a URL to transition to a shortcode (and vice versa) when returning an embed to TinyMCE * In `WP_Embed`, store the last URL and last set of attributes requested in class properties * `wp_ajax_parse_embed()`, allow `[embed]`s to have attributes. Return `attr` in the response. This is a first pass to allow broad testing with recent MCE view changes. See #31139. git-svn-id: https://develop.svn.wordpress.org/trunk@31620 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-admin/includes/ajax-actions.php | 15 +++++-- src/wp-includes/class-wp-embed.php | 10 ++++- src/wp-includes/css/media-views.css | 24 ++++++++++ src/wp-includes/js/mce-view.js | 21 ++++++--- src/wp-includes/js/media/views.js | 46 ++++++++++++++++---- src/wp-includes/js/media/views/embed/link.js | 46 ++++++++++++++++---- src/wp-includes/media-template.php | 10 +++++ 7 files changed, 144 insertions(+), 28 deletions(-) diff --git a/src/wp-admin/includes/ajax-actions.php b/src/wp-admin/includes/ajax-actions.php index 26d7e4770d..7678a7fd15 100644 --- a/src/wp-admin/includes/ajax-actions.php +++ b/src/wp-admin/includes/ajax-actions.php @@ -2708,13 +2708,21 @@ function wp_ajax_parse_embed() { } $shortcode = wp_unslash( $_POST['shortcode'] ); - $url = str_replace( '[embed]', '', str_replace( '[/embed]', '', $shortcode ) ); + + preg_match( '/' . get_shortcode_regex() . '/s', $shortcode, $matches ); + $atts = shortcode_parse_atts( $matches[3] ); + if ( ! empty( $atts[5] ) ) { + $url = $atts[5]; + } elseif ( ! empty( $atts['src'] ) ) { + $url = $atts['src']; + } + $parsed = false; setup_postdata( $post ); $wp_embed->return_false_on_fail = true; - if ( is_ssl() && preg_match( '%^\\[embed[^\\]]*\\]http://%i', $shortcode ) ) { + if ( is_ssl() && 0 === strpos( $url, 'http://' ) ) { // Admin is ssl and the user pasted non-ssl URL. // Check if the provider supports ssl embeds and use that for the preview. $ssl_shortcode = preg_replace( '%^(\\[embed[^\\]]*\\])http://%i', '$1https://', $shortcode ); @@ -2767,7 +2775,8 @@ function wp_ajax_parse_embed() { } wp_send_json_success( array( - 'body' => $parsed + 'body' => $parsed, + 'attr' => $wp_embed->last_attr ) ); } diff --git a/src/wp-includes/class-wp-embed.php b/src/wp-includes/class-wp-embed.php index 1cd4d6252c..9af3c224fe 100644 --- a/src/wp-includes/class-wp-embed.php +++ b/src/wp-includes/class-wp-embed.php @@ -11,6 +11,8 @@ class WP_Embed { public $post_ID; public $usecache = true; public $linkifunknown = true; + public $last_attr = array(); + public $last_url = ''; /** * When an URL cannot be embedded, return false instead of returning a link @@ -134,12 +136,18 @@ class WP_Embed { $url = $attr['src']; } - if ( empty( $url ) ) + $this->last_url = $url; + + if ( empty( $url ) ) { + $this->last_attr = $attr; return ''; + } $rawattr = $attr; $attr = wp_parse_args( $attr, wp_embed_defaults( $url ) ); + $this->last_attr = $attr; + // kses converts & into & and we need to undo this // See https://core.trac.wordpress.org/ticket/11311 $url = str_replace( '&', '&', $url ); diff --git a/src/wp-includes/css/media-views.css b/src/wp-includes/css/media-views.css index c0aadaadae..0e783b6fdb 100644 --- a/src/wp-includes/css/media-views.css +++ b/src/wp-includes/css/media-views.css @@ -1944,6 +1944,29 @@ clear: both; } +.embed-link-settings .setting { + display: none; +} + +.embed-link-dimensions:after { + content: ''; + display: block; + clear: both; +} + +.embed-link-dimensions .width, +.embed-link-dimensions .height { + float: left; + width: 125px; + clear: none; + margin-right: 10px; +} + +.embed-link-dimensions input { + width: auto; + max-width: 110px; +} + .image-details .embed-media-settings .setting { float: none; width: auto; @@ -1990,6 +2013,7 @@ .media-embed .setting span { display: block; width: 200px; + max-width: 100%; font-size: 13px; line-height: 24px; color: #666; diff --git a/src/wp-includes/js/mce-view.js b/src/wp-includes/js/mce-view.js index 8082c1a302..750de38f4e 100644 --- a/src/wp-includes/js/mce-view.js +++ b/src/wp-includes/js/mce-view.js @@ -819,21 +819,30 @@ window.wp = window.wp || {}; edit: function( text, update ) { var media = wp.media.embed, frame = media.edit( text, !! this.url ), - self = this; + self = this, + events = 'change:url change:width change:height'; this.pausePlayers(); - frame.state( 'embed' ).props.on( 'change:url', function( model, url ) { - if ( url ) { + frame.state( 'embed' ).props.on( events, function( model, url ) { + if ( url && model.get( 'url' ) ) { frame.state( 'embed' ).metadata = model.toJSON(); } } ); frame.state( 'embed' ).on( 'select', function() { - if ( self.url ) { - update( frame.state( 'embed' ).metadata.url ); + var data = frame.state( 'embed' ).metadata; + + if ( data.width ) { + delete self.url; } else { - update( media.shortcode( frame.state( 'embed' ).metadata ).string() ); + self.url = data.url; + } + + if ( self.url ) { + update( data.url ); + } else { + update( media.shortcode( data ).string() ); } } ); diff --git a/src/wp-includes/js/media/views.js b/src/wp-includes/js/media/views.js index 0ef4b5150d..450811b851 100644 --- a/src/wp-includes/js/media/views.js +++ b/src/wp-includes/js/media/views.js @@ -4597,13 +4597,12 @@ EmbedLink = Settings.extend({ initialize: function() { this.spinner = $(''); this.$el.append( this.spinner[0] ); - this.listenTo( this.model, 'change:url', this.updateoEmbed ); + this.listenTo( this.model, 'change:url change:width change:height', this.updateoEmbed ); }, - updateoEmbed: function() { + updateoEmbed: _.debounce( function() { var url = this.model.get( 'url' ); - this.$('.setting.title').show(); // clear out previous results this.$('.embed-container').hide().find('.embed-preview').html(''); @@ -4614,29 +4613,58 @@ EmbedLink = Settings.extend({ this.spinner.show(); - setTimeout( _.bind( this.fetch, this ), 500 ); - }, + this.fetch(); + }, 600 ), fetch: function() { + var embed; + // check if they haven't typed in 500 ms if ( $('#embed-url-field').val() !== this.model.get('url') ) { return; } + embed = new wp.shortcode({ + tag: 'embed', + attrs: _.pick( this.model.attributes, [ 'width', 'height', 'src' ] ), + content: this.model.get('url') + }); + wp.ajax.send( 'parse-embed', { data : { post_ID: wp.media.view.settings.post.id, - shortcode: '[embed]' + this.model.get('url') + '[/embed]' + shortcode: embed.string() } } ).done( _.bind( this.renderoEmbed, this ) ); }, renderoEmbed: function( response ) { - var html = ( response && response.body ) || ''; + var html = ( response && response.body ) || '', + attr = {}, + opts = { silent: true }; + + if ( response && response.attr ) { + attr = response.attr; + + _.each( [ 'width', 'height' ], function ( key ) { + var $el = this.$( '.setting.' + key ), + value = attr[ key ]; + + if ( value ) { + this.model.set( key, value, opts ); + $el.show().find( 'input' ).val( value ); + } else { + this.model.unset( key, opts ); + $el.hide().find( 'input' ).val( '' ); + } + }, this ); + } else { + this.model.unset( 'height', opts ); + this.model.unset( 'width', opts ); + } this.spinner.hide(); - - this.$('.setting.title').hide(); + this.$('.embed-container').show().find('.embed-preview').html( html ); } }); diff --git a/src/wp-includes/js/media/views/embed/link.js b/src/wp-includes/js/media/views/embed/link.js index b711d0468d..8c617d609a 100644 --- a/src/wp-includes/js/media/views/embed/link.js +++ b/src/wp-includes/js/media/views/embed/link.js @@ -20,13 +20,12 @@ EmbedLink = Settings.extend({ initialize: function() { this.spinner = $(''); this.$el.append( this.spinner[0] ); - this.listenTo( this.model, 'change:url', this.updateoEmbed ); + this.listenTo( this.model, 'change:url change:width change:height', this.updateoEmbed ); }, - updateoEmbed: function() { + updateoEmbed: _.debounce( function() { var url = this.model.get( 'url' ); - this.$('.setting.title').show(); // clear out previous results this.$('.embed-container').hide().find('.embed-preview').html(''); @@ -37,29 +36,58 @@ EmbedLink = Settings.extend({ this.spinner.show(); - setTimeout( _.bind( this.fetch, this ), 500 ); - }, + this.fetch(); + }, 600 ), fetch: function() { + var embed; + // check if they haven't typed in 500 ms if ( $('#embed-url-field').val() !== this.model.get('url') ) { return; } + embed = new wp.shortcode({ + tag: 'embed', + attrs: _.pick( this.model.attributes, [ 'width', 'height', 'src' ] ), + content: this.model.get('url') + }); + wp.ajax.send( 'parse-embed', { data : { post_ID: wp.media.view.settings.post.id, - shortcode: '[embed]' + this.model.get('url') + '[/embed]' + shortcode: embed.string() } } ).done( _.bind( this.renderoEmbed, this ) ); }, renderoEmbed: function( response ) { - var html = ( response && response.body ) || ''; + var html = ( response && response.body ) || '', + attr = {}, + opts = { silent: true }; + + if ( response && response.attr ) { + attr = response.attr; + + _.each( [ 'width', 'height' ], function ( key ) { + var $el = this.$( '.setting.' + key ), + value = attr[ key ]; + + if ( value ) { + this.model.set( key, value, opts ); + $el.show().find( 'input' ).val( value ); + } else { + this.model.unset( key, opts ); + $el.hide().find( 'input' ).val( '' ); + } + }, this ); + } else { + this.model.unset( 'height', opts ); + this.model.unset( 'width', opts ); + } this.spinner.hide(); - - this.$('.setting.title').hide(); + this.$('.embed-container').show().find('.embed-preview').html( html ); } }); diff --git a/src/wp-includes/media-template.php b/src/wp-includes/media-template.php index c7ec89acfc..d5dae3f184 100644 --- a/src/wp-includes/media-template.php +++ b/src/wp-includes/media-template.php @@ -819,6 +819,16 @@ function wp_print_media_templates() { +