diff --git a/src/wp-includes/functions.php b/src/wp-includes/functions.php index 3ac86a3e19..6fa978c099 100644 --- a/src/wp-includes/functions.php +++ b/src/wp-includes/functions.php @@ -1983,6 +1983,7 @@ function wp_get_mime_types() { 'rtx' => 'text/richtext', 'css' => 'text/css', 'htm|html' => 'text/html', + 'vtt' => 'text/vtt', // Audio formats 'mp3|m4a|m4b' => 'audio/mpeg', 'ra|ram' => 'audio/x-realaudio', diff --git a/src/wp-includes/js/media-editor.js b/src/wp-includes/js/media-editor.js index f065c0e8b0..bdb72abb32 100644 --- a/src/wp-includes/js/media-editor.js +++ b/src/wp-includes/js/media-editor.js @@ -609,26 +609,33 @@ poster : '', loop : false, autoplay : false, - preload : 'metadata' + preload : 'metadata', + content : '' }, edit : function (data) { - var frame, shortcode = wp.shortcode.next( 'video', data ).shortcode; + var frame, + defaults = this.defaults, + shortcode = wp.shortcode.next( 'video', data ).shortcode, + attrs; + + attrs = shortcode.attrs.named; + attrs.content = shortcode.content; + frame = wp.media({ frame: 'video', state: 'video-details', - metadata: _.defaults( - shortcode.attrs.named, - wp.media.video.defaults - ) + metadata: _.defaults( attrs, defaults ) }); return frame; }, shortcode : function (shortcode) { - var self = this; - _.each( wp.media.video.defaults, function( value, key ) { + var self = this, content = shortcode.content; + delete shortcode.content; + + _.each( this.defaults, function( value, key ) { shortcode[ key ] = self.coerce( shortcode, key ); if ( value === shortcode[ key ] ) { @@ -638,7 +645,8 @@ return wp.shortcode.string({ tag: 'video', - attrs: shortcode + attrs: shortcode, + content: content }); } }, wp.media.mixin); diff --git a/src/wp-includes/js/media-views.js b/src/wp-includes/js/media-views.js index 1bfe15a305..e0d181c472 100644 --- a/src/wp-includes/js/media-views.js +++ b/src/wp-includes/js/media-views.js @@ -1193,41 +1193,16 @@ media.controller.MediaLibrary = media.controller.Library.extend({ defaults: _.defaults({ filterable: 'uploaded', - multiple: false, priority: 80, syncSelection: false, - displaySettings: true + displaySettings: false }, media.controller.Library.prototype.defaults ), initialize: function( options ) { - var library, comparator; - this.media = options.media; this.set( 'library', media.query({ type: options.type }) ); media.controller.Library.prototype.initialize.apply( this, arguments ); - - library = this.get('library'); - comparator = library.comparator; - - // Overload the library's comparator to push items that are not in - // the mirrored query to the front of the aggregate collection. - library.comparator = function( a, b ) { - var aInQuery = !! this.mirroring.get( a.cid ), - bInQuery = !! this.mirroring.get( b.cid ); - - if ( ! aInQuery && bInQuery ) { - return -1; - } else if ( aInQuery && ! bInQuery ) { - return 1; - } else { - return comparator.apply( this, arguments ); - } - }; - - // Add all items in the selection to the library, so any featured - // images that are not initially loaded still appear. - library.observe( this.get('selection') ); } }); @@ -2952,6 +2927,7 @@ this.on( 'toolbar:render:replace-video', this.renderReplaceToolbar, this ); this.on( 'toolbar:render:add-video-source', this.renderAddSourceToolbar, this ); this.on( 'toolbar:render:select-poster-image', this.renderSelectPosterImageToolbar, this ); + this.on( 'toolbar:render:add-track', this.renderAddTrackToolbar, this ); }, createStates: function() { @@ -2987,6 +2963,15 @@ toolbar: 'select-poster-image', media: this.media, menu: 'video-details' + } ), + + new media.controller.MediaLibrary( { + type: 'text', + id: 'add-track', + title: l10n.videoAddTrackTitle, + toolbar: 'add-track', + media: this.media, + menu: 'video-details' } ) ]); }, @@ -3010,6 +2995,43 @@ state.trigger( 'set-poster-image', controller.media.toJSON() ); + // Restore and reset the default state. + controller.setState( controller.options.state ); + controller.reset(); + } + } + } + }) ); + }, + + renderAddTrackToolbar: function() { + this.toolbar.set( new media.view.Toolbar({ + controller: this, + items: { + replace: { + style: 'primary', + text: l10n.videoAddTrackTitle, + priority: 80, + + click: function() { + var controller = this.controller, + state = controller.state(), + selection = state.get( 'selection' ), + attachment = selection.single(), + content = controller.media.get( 'content' ); + + if ( -1 === content.indexOf( attachment.get( 'url' ) ) ) { + content += [ + '' + ].join(''); + + controller.media.set( 'content', content ); + } + + state.trigger( 'add-track', controller.media.toJSON() ); + // Restore and reset the default state. controller.setState( controller.options.state ); controller.reset(); @@ -6366,21 +6388,17 @@ this.on( 'media:setting:remove', this.render ); this.on( 'media:setting:remove', this.setPlayer ); this.events = _.extend( this.events, { - 'click .remove-setting' : 'removeSetting' + 'click .remove-setting' : 'removeSetting', + 'change .content-track' : 'setTracks', + 'click .remove-track' : 'setTracks' } ); media.view.Settings.AttachmentDisplay.prototype.initialize.apply( this, arguments ); }, prepare: function() { - var attachment = false; - - if ( this.model.attachment ) { - attachment = this.model.attachment.toJSON(); - } return _.defaults({ - model: this.model.toJSON(), - attachment: attachment + model: this.model.toJSON() }, this.options ); }, @@ -6404,12 +6422,26 @@ }, removeSetting : function (e) { - var setting = $( e.currentTarget ).parent(); + var wrap = $( e.currentTarget ).parent(), setting; - this.model.unset( setting.find( 'input' ).data( 'setting' ) ); + setting = wrap.find( 'input' ).data( 'setting' ); - setting.remove(); + if ( setting ) { + this.model.unset( setting ); + this.trigger( 'media:setting:remove', this ); + } + wrap.remove(); + }, + + setTracks : function () { + var tracks = ''; + + _.each( this.$('.content-track'), function (track) { + tracks += $( track ).val(); + } ); + + this.model.set( 'content', tracks ); this.trigger( 'media:setting:remove', this ); }, diff --git a/src/wp-includes/js/mediaelement/wp-mediaelement.css b/src/wp-includes/js/mediaelement/wp-mediaelement.css index 6e3bb4b3b2..cf498e959d 100644 --- a/src/wp-includes/js/mediaelement/wp-mediaelement.css +++ b/src/wp-includes/js/mediaelement/wp-mediaelement.css @@ -19,6 +19,11 @@ max-width: 400px; } +.media-embed-details .embed-media-settings .setting span { + max-width: 400px; + width: auto; +} + .media-embed-details .embed-media-settings { padding-top: 0; } @@ -28,8 +33,11 @@ max-width: 600px; } +.media-embed-details .setting p, .media-embed-details .setting a { color: #a00; + font-size: 10px; + text-transform: uppercase; } .media-embed-details .setting a:hover { diff --git a/src/wp-includes/js/tinymce/plugins/wpgallery/plugin.js b/src/wp-includes/js/tinymce/plugins/wpgallery/plugin.js index 018d91eb21..d33dbca088 100644 --- a/src/wp-includes/js/tinymce/plugins/wpgallery/plugin.js +++ b/src/wp-includes/js/tinymce/plugins/wpgallery/plugin.js @@ -97,11 +97,14 @@ tinymce.PluginManager.add('wpgallery', function( editor ) { frame.on( 'close', function () { frame.detach(); } ); - frame.state( 'video-details' ).on( 'update replace add-source select-poster-image', function ( selection ) { - var shortcode = wp.media.video.shortcode( selection ); - editor.dom.setAttrib( node, 'data-wp-media', window.encodeURIComponent( shortcode ) ); - frame.detach(); - } ); + frame.state( 'video-details' ).on( + 'update replace add-source select-poster-image add-track', + function ( selection ) { + var shortcode = wp.media.video.shortcode( selection ); + editor.dom.setAttrib( node, 'data-wp-media', window.encodeURIComponent( shortcode ) ); + frame.detach(); + } + ); frame.open(); } else if ( editor.dom.hasClass( node, 'wp-audio' ) ) { frame = wp.media.audio.edit( data ); diff --git a/src/wp-includes/media-template.php b/src/wp-includes/media-template.php index 641be2f679..31d650a759 100644 --- a/src/wp-includes/media-template.php +++ b/src/wp-includes/media-template.php @@ -690,7 +690,7 @@ function wp_print_media_templates() { <# } #> - {{{ wp.media.view.l10n.audioRemoveSource }}} + {{{ wp.media.view.l10n.remove }}} <# } #> @@ -779,13 +779,14 @@ function wp_print_media_templates() { ?><# if ( data.model. ) { #> <# } #> - + + {{{ data.model.content }}} + <# if ( ! _.isEmpty( data.model.src ) ) { #> <# } #> - {{{ wp.media.view.l10n.videoRemoveSource }}} + {{{ wp.media.view.l10n.remove }}} <# } #> @@ -802,7 +803,7 @@ function wp_print_media_templates() { <# } #>
@@ -824,6 +825,25 @@ function wp_print_media_templates() {
+ +
diff --git a/src/wp-includes/media.php b/src/wp-includes/media.php index ce0338b037..0aadf8a995 100644 --- a/src/wp-includes/media.php +++ b/src/wp-includes/media.php @@ -2395,7 +2395,8 @@ function wp_enqueue_media( $args = array() ) { 'cancel' => __( 'Cancel' ), 'update' => __( 'Update' ), 'replace' => __( 'Replace' ), - 'back' => __( 'Back' ), + 'remove' => __( 'Remove' ), + 'back' => __( 'Back' ), /* translators: This is a would-be plural string used in the media manager. If there is not a word you can use in your language to avoid issues with the lack of plural support here, turn it into "selected: %d" then translate it. @@ -2450,7 +2451,6 @@ function wp_enqueue_media( $args = array() ) { 'audioDetailsCancel' => __( 'Cancel Edit' ), 'audioDetailsText' => __( '"Replace Audio" will remove all associated source files when you update. ' . '"Add Audio Source" allows you to specify alternate sources for maximum native HTML5 audio playback.' ), - 'audioRemoveSource' => __( 'Remove Audio Source' ), // Edit Video 'videoDetailsTitle' => __( 'Video Details' ), @@ -2459,9 +2459,8 @@ function wp_enqueue_media( $args = array() ) { 'videoDetailsCancel' => __( 'Cancel Edit' ), 'videoDetailsText' => __( '"Replace Video" will remove all associated source files when you update. ' . '"Add Video Source" allows you to specify alternate sources for maximum native HTML5 video playback.' ), - 'videoRemoveSource' => __( 'Remove Video Source' ), 'videoSelectPosterImageTitle' => _( 'Select Poster Image' ), - 'videoRemovePoster' => __( 'Remove Poster Image' ), + 'videoAddTrackTitle' => __( 'Add Subtitles' ), // Playlist 'playlistDragInfo' => __( 'Drag and drop to reorder tracks.' ),