WordPress.org

Make WordPress Core

Changeset 27481


Ignore:
Timestamp:
03/09/2014 10:31:36 AM (6 years ago)
Author:
wonderboymusic
Message:

Video editing in the media modal:

  • Add a state: Add Subititles
  • Add text/vtt to the list of allowed mime-types, files end in .vtt. .srt files are served as text/plain.
  • The content body of a video shortcode should be used for adding <track> elements only. This happens dynamically in the modal. If added by hand, they can still be parsed and managed.

See #27016.

Location:
trunk/src/wp-includes
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/functions.php

    r27422 r27481  
    19841984    'css' => 'text/css',
    19851985    'htm|html' => 'text/html',
     1986    'vtt' => 'text/vtt',
    19861987    // Audio formats
    19871988    'mp3|m4a|m4b' => 'audio/mpeg',
  • trunk/src/wp-includes/js/media-editor.js

    r27445 r27481  
    610610            loop : false,
    611611            autoplay : false,
    612             preload : 'metadata'
     612            preload : 'metadata',
     613            content : ''
    613614        },
    614615
    615616        edit : function (data) {
    616             var frame, shortcode = wp.shortcode.next( 'video', data ).shortcode;
     617            var frame,
     618                defaults = this.defaults,
     619                shortcode = wp.shortcode.next( 'video', data ).shortcode,
     620                attrs;
     621
     622            attrs = shortcode.attrs.named;
     623            attrs.content = shortcode.content;
     624
    617625            frame = wp.media({
    618626                frame: 'video',
    619627                state: 'video-details',
    620                 metadata: _.defaults(
    621                     shortcode.attrs.named,
    622                     wp.media.video.defaults
    623                 )
     628                metadata: _.defaults( attrs, defaults )
    624629            });
    625630
     
    628633
    629634        shortcode : function (shortcode) {
    630             var self = this;
    631             _.each( wp.media.video.defaults, function( value, key ) {
     635            var self = this, content = shortcode.content;
     636            delete shortcode.content;
     637
     638            _.each( this.defaults, function( value, key ) {
    632639                shortcode[ key ] = self.coerce( shortcode, key );
    633640
     
    639646            return wp.shortcode.string({
    640647                tag:     'video',
    641                 attrs:   shortcode
     648                attrs:   shortcode,
     649                content: content
    642650            });
    643651        }
  • trunk/src/wp-includes/js/media-views.js

    r27480 r27481  
    11941194        defaults: _.defaults({
    11951195            filterable: 'uploaded',
    1196             multiple:   false,
    11971196            priority:   80,
    11981197            syncSelection: false,
    1199             displaySettings: true
     1198            displaySettings: false
    12001199        }, media.controller.Library.prototype.defaults ),
    12011200
    12021201        initialize: function( options ) {
    1203             var library, comparator;
    1204 
    12051202            this.media = options.media;
    12061203            this.set( 'library', media.query({ type: options.type }) );
    12071204
    12081205            media.controller.Library.prototype.initialize.apply( this, arguments );
    1209 
    1210             library    = this.get('library');
    1211             comparator = library.comparator;
    1212 
    1213             // Overload the library's comparator to push items that are not in
    1214             // the mirrored query to the front of the aggregate collection.
    1215             library.comparator = function( a, b ) {
    1216                 var aInQuery = !! this.mirroring.get( a.cid ),
    1217                     bInQuery = !! this.mirroring.get( b.cid );
    1218 
    1219                 if ( ! aInQuery && bInQuery ) {
    1220                     return -1;
    1221                 } else if ( aInQuery && ! bInQuery ) {
    1222                     return 1;
    1223                 } else {
    1224                     return comparator.apply( this, arguments );
    1225                 }
    1226             };
    1227 
    1228             // Add all items in the selection to the library, so any featured
    1229             // images that are not initially loaded still appear.
    1230             library.observe( this.get('selection') );
    12311206        }
    12321207    });
     
    29532928            this.on( 'toolbar:render:add-video-source', this.renderAddSourceToolbar, this );
    29542929            this.on( 'toolbar:render:select-poster-image', this.renderSelectPosterImageToolbar, this );
     2930            this.on( 'toolbar:render:add-track', this.renderAddTrackToolbar, this );
    29552931        },
    29562932
     
    29882964                    media: this.media,
    29892965                    menu: 'video-details'
     2966                } ),
     2967
     2968                new media.controller.MediaLibrary( {
     2969                    type: 'text',
     2970                    id: 'add-track',
     2971                    title: l10n.videoAddTrackTitle,
     2972                    toolbar: 'add-track',
     2973                    media: this.media,
     2974                    menu: 'video-details'
    29902975                } )
    29912976            ]);
     
    30102995
    30112996                            state.trigger( 'set-poster-image', controller.media.toJSON() );
     2997
     2998                            // Restore and reset the default state.
     2999                            controller.setState( controller.options.state );
     3000                            controller.reset();
     3001                        }
     3002                    }
     3003                }
     3004            }) );
     3005        },
     3006
     3007        renderAddTrackToolbar: function() {
     3008            this.toolbar.set( new media.view.Toolbar({
     3009                controller: this,
     3010                items: {
     3011                    replace: {
     3012                        style:    'primary',
     3013                        text:     l10n.videoAddTrackTitle,
     3014                        priority: 80,
     3015
     3016                        click: function() {
     3017                            var controller = this.controller,
     3018                                state = controller.state(),
     3019                                selection = state.get( 'selection' ),
     3020                                attachment = selection.single(),
     3021                                content = controller.media.get( 'content' );
     3022
     3023                            if ( -1 === content.indexOf( attachment.get( 'url' ) ) ) {
     3024                                content += [
     3025                                    '<track srclang="en" label="English"kind="subtitles" src="',
     3026                                    attachment.get( 'url' ),
     3027                                    '" />'
     3028                                ].join('');
     3029
     3030                                controller.media.set( 'content', content );
     3031                            }
     3032
     3033                            state.trigger( 'add-track', controller.media.toJSON() );
    30123034
    30133035                            // Restore and reset the default state.
     
    63676389            this.on( 'media:setting:remove', this.setPlayer );
    63686390            this.events = _.extend( this.events, {
    6369                 'click .remove-setting' : 'removeSetting'
     6391                'click .remove-setting' : 'removeSetting',
     6392                'change .content-track' : 'setTracks',
     6393                'click .remove-track' : 'setTracks'
    63706394            } );
    63716395
     
    63746398
    63756399        prepare: function() {
    6376             var attachment = false;
    6377 
    6378             if ( this.model.attachment ) {
    6379                 attachment = this.model.attachment.toJSON();
    6380             }
    63816400            return _.defaults({
    6382                 model: this.model.toJSON(),
    6383                 attachment: attachment
     6401                model: this.model.toJSON()
    63846402            }, this.options );
    63856403        },
     
    64056423
    64066424        removeSetting : function (e) {
    6407             var setting = $( e.currentTarget ).parent();
    6408 
    6409             this.model.unset( setting.find( 'input' ).data( 'setting' ) );
    6410 
    6411             setting.remove();
    6412 
     6425            var wrap = $( e.currentTarget ).parent(), setting;
     6426
     6427            setting = wrap.find( 'input' ).data( 'setting' );
     6428
     6429            if ( setting ) {
     6430                this.model.unset( setting );
     6431                this.trigger( 'media:setting:remove', this );
     6432            }
     6433
     6434            wrap.remove();
     6435        },
     6436
     6437        setTracks : function () {
     6438            var tracks = '';
     6439
     6440            _.each( this.$('.content-track'), function (track) {
     6441                tracks += $( track ).val();
     6442            } );
     6443
     6444            this.model.set( 'content', tracks );
    64136445            this.trigger( 'media:setting:remove', this );
    64146446        },
  • trunk/src/wp-includes/js/mediaelement/wp-mediaelement.css

    r27480 r27481  
    2020}
    2121
     22.media-embed-details .embed-media-settings .setting span {
     23    max-width: 400px;
     24    width: auto;
     25}
     26
    2227.media-embed-details .embed-media-settings {
    2328    padding-top: 0;
     
    2934}
    3035
     36.media-embed-details .setting p,
    3137.media-embed-details .setting a {
    3238    color: #a00;
     39    font-size: 10px;
     40    text-transform: uppercase;
    3341}
    3442
  • trunk/src/wp-includes/js/tinymce/plugins/wpgallery/plugin.js

    r27478 r27481  
    9898                frame.detach();
    9999            } );
    100             frame.state( 'video-details' ).on( 'update replace add-source select-poster-image', function ( selection ) {
    101                 var shortcode = wp.media.video.shortcode( selection );
    102                 editor.dom.setAttrib( node, 'data-wp-media', window.encodeURIComponent( shortcode ) );
    103                 frame.detach();
    104             } );
     100            frame.state( 'video-details' ).on(
     101                'update replace add-source select-poster-image add-track',
     102                function ( selection ) {
     103                    var shortcode = wp.media.video.shortcode( selection );
     104                    editor.dom.setAttrib( node, 'data-wp-media', window.encodeURIComponent( shortcode ) );
     105                    frame.detach();
     106                }
     107            );
    105108            frame.open();
    106109        } else if ( editor.dom.hasClass( node, 'wp-audio' ) ) {
  • trunk/src/wp-includes/media-template.php

    r27480 r27481  
    691691                    <span>SRC</span>
    692692                    <input type="text" disabled="disabled" data-setting="src" value="{{ data.model.src }}" />
    693                     <a class="remove-setting">{{{ wp.media.view.l10n.audioRemoveSource }}}</a>
     693                    <a class="remove-setting">{{{ wp.media.view.l10n.remove }}}</a>
    694694                </label>
    695695                <# } #>
     
    701701                    <span><?php echo strtoupper( $type ) ?></span>
    702702                    <input type="text" disabled="disabled" data-setting="<?php echo $type ?>" value="{{ data.model.<?php echo $type ?> }}" />
    703                     <a class="remove-setting">{{{ wp.media.view.l10n.audioRemoveSource }}}</a>
     703                    <a class="remove-setting">{{{ wp.media.view.l10n.remove }}}</a>
    704704                </label>
    705705                <# } #>
     
    780780                    <source src="{{ data.model.<?php echo $type ?> }}" type="{{ wp.media.view.settings.embedMimes[ '<?php echo $type ?>' ] }}" />
    781781                    <# } #>
    782                     <?php endforeach;
    783                 ?></video>
     782                    <?php endforeach; ?>
     783                    {{{ data.model.content }}}
     784                </video>
    784785                <# if ( ! _.isEmpty( data.model.src ) ) { #>
    785786                <label class="setting">
    786787                    <span>SRC</span>
    787788                    <input type="text" disabled="disabled" data-setting="src" value="{{ data.model.src }}" />
    788                     <a class="remove-setting">{{{ wp.media.view.l10n.videoRemoveSource }}}</a>
     789                    <a class="remove-setting">{{{ wp.media.view.l10n.remove }}}</a>
    789790                </label>
    790791                <# } #>
     
    794795                    <span><?php echo strtoupper( $type ) ?></span>
    795796                    <input type="text" disabled="disabled" data-setting="<?php echo $type ?>" value="{{ data.model.<?php echo $type ?> }}" />
    796                     <a class="remove-setting">{{{ wp.media.view.l10n.videoRemoveSource }}}</a>
     797                    <a class="remove-setting">{{{ wp.media.view.l10n.remove }}}</a>
    797798                </label>
    798799                <# } #>
     
    803804                    <span><?php _e( 'Poster Image' ); ?></span>
    804805                    <input type="text" disabled="disabled" data-setting="poster" value="{{ data.model.poster }}" />
    805                     <a class="remove-setting">{{{ wp.media.view.l10n.videoRemovePoster }}}</a>
     806                    <a class="remove-setting">{{{ wp.media.view.l10n.remove }}}</a>
    806807                </label>
    807808                <# } #>
     
    825826                </label>
    826827                <div class="clear"></div>
     828
     829                <label class="setting" data-setting="content">
     830                    <span><?php _e( 'Tracks (subtitles, captions, descriptions, chapters or metadata)' ); ?></span>
     831                    <#
     832                    var content = '';
     833                    if ( ! _.isEmpty( data.model.content ) ) {
     834                        var tracks = jQuery( data.model.content ).filter( 'track' );
     835                        _.each( tracks.toArray(), function (track) {
     836                            content += track.outerHTML; #>
     837                        <p>
     838                            <input class="content-track" type="text" value="{{ track.outerHTML }}" />
     839                            <a class="remove-setting remove-track">{{{ wp.media.view.l10n.remove }}}</a>
     840                        </p>
     841                        <# } ); #>
     842                    <# } else { #>
     843                    <em>There are no associated subtitles.</em>
     844                    <# } #>
     845                    <textarea class="hidden content-setting">{{ content }}</textarea>
     846                </label>
    827847            </div>
    828848        </div>
  • trunk/src/wp-includes/media.php

    r27478 r27481  
    23962396        'update'      => __( 'Update' ),
    23972397        'replace'     => __( 'Replace' ),
    2398         'back'     => __( 'Back' ),
     2398        'remove'      => __( 'Remove' ),
     2399        'back'        => __( 'Back' ),
    23992400        /* translators: This is a would-be plural string used in the media manager.
    24002401           If there is not a word you can use in your language to avoid issues with the
     
    24512452        'audioDetailsText'      => __( '"Replace Audio" will remove all associated source files when you update. ' .
    24522453            '"Add Audio Source" allows you to specify alternate sources for maximum native HTML5 audio playback.' ),
    2453         'audioRemoveSource'     => __( 'Remove Audio Source' ),
    24542454
    24552455        // Edit Video
     
    24602460        'videoDetailsText'      => __( '"Replace Video" will remove all associated source files when you update. ' .
    24612461            '"Add Video Source" allows you to specify alternate sources for maximum native HTML5 video playback.' ),
    2462         'videoRemoveSource'     => __( 'Remove Video Source' ),
    24632462        'videoSelectPosterImageTitle' => _( 'Select Poster Image' ),
    2464         'videoRemovePoster'     => __( 'Remove Poster Image' ),
     2463        'videoAddTrackTitle'    => __( 'Add Subtitles' ),
    24652464
    24662465        // Playlist
Note: See TracChangeset for help on using the changeset viewer.