diff --git a/src/js/media/views/embed/url.js b/src/js/media/views/embed/url.js index 701b2859518e1..6d2aee95989b7 100644 --- a/src/js/media/views/embed/url.js +++ b/src/js/media/views/embed/url.js @@ -14,7 +14,7 @@ var View = wp.media.View, * @augments Backbone.View */ EmbedUrl = View.extend(/** @lends wp.media.view.EmbedUrl.prototype */{ - tagName: 'span', + tagName: 'span', className: 'embed-url', events: { @@ -28,7 +28,13 @@ EmbedUrl = View.extend(/** @lends wp.media.view.EmbedUrl.prototype */{ this.input = this.$input[0]; this.spinner = $('')[0]; - this.$el.append([ this.input, this.spinner ]); + + this.error = $('

')[0]; + + this.$error = $(this.error); + this.$error.hide(); + + this.$el.append([ this.input, this.spinner, this.error ]); this.listenTo( this.model, 'change:url', this.render ); @@ -37,6 +43,8 @@ EmbedUrl = View.extend(/** @lends wp.media.view.EmbedUrl.prototype */{ this.model.trigger( 'change:url' ); }, this ), 500 ); } + + this.updateUrl = _.debounce( this.updateUrl, 500 ); }, /** * @return {wp.media.view.EmbedUrl} Returns itself to allow chaining. @@ -62,8 +70,35 @@ EmbedUrl = View.extend(/** @lends wp.media.view.EmbedUrl.prototype */{ }, url: function( event ) { - var url = event.target.value || ''; - this.model.set( 'url', url.trim() ); + var $el = $( event.target ); + var url = $el.val() || ''; + var valid = this.isValidUrlInput( event.target ); + this.updateUrl( url, valid ); + }, + + isValidUrlInput: function ( el ) { + var url = ( el.value || '' ).trim(); + try { + url = new URL( url ); + return [ 'http:', 'https:' ].includes(url.protocol); + } catch ( e ) { + return false; + } + }, + + updateUrl: function ( url, valid ) { + if ( valid ) { + this.model.set( 'url', url.trim() ); + this.$error.hide(); + } else { + if ( url.length > 0 ) { + this.model.set( 'url', '' ); + this.$error.find( 'p' ).text( l10n.invalidUrl ); + this.$error.show(); + } else { + this.$error.hide(); + } + } } }); diff --git a/src/wp-includes/css/media-views.css b/src/wp-includes/css/media-views.css index f78a946c260f7..ccc34657ba7f3 100644 --- a/src/wp-includes/css/media-views.css +++ b/src/wp-includes/css/media-views.css @@ -2118,6 +2118,10 @@ right: 26px; } +.media-frame .embed-url-error { + margin: 4px 0; +} + .media-frame .embed-loading .embed-url .spinner { visibility: visible; } diff --git a/src/wp-includes/media.php b/src/wp-includes/media.php index 8f6ec1cef4e26..a1d7687dd8c01 100644 --- a/src/wp-includes/media.php +++ b/src/wp-includes/media.php @@ -5076,6 +5076,7 @@ function wp_enqueue_media( $args = array() ) { // From URL. 'insertFromUrlTitle' => __( 'Insert from URL' ), + 'invalidUrl' => __( 'Please enter a valid URL.' ), // Featured Images. 'setFeaturedImageTitle' => $post_type_object->labels->featured_image, @@ -6446,4 +6447,3 @@ function wp_get_image_editor_output_format( $filename, $mime_type ) { */ return apply_filters( 'image_editor_output_format', $output_format, $filename, $mime_type ); } -