Make WordPress Core

Changeset 27481


Ignore:
Timestamp:
03/09/2014 10:31:36 AM (13 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.