Make WordPress Core

Changeset 27608


Ignore:
Timestamp:
03/19/2014 05:30:27 AM (11 years ago)
Author:
wonderboymusic
Message:

Create a new file, media-audiovideo.js, to house all of the audio and video JS code in core.

UX Changes:

  • Don't add a menu item for "Add Audio|Video Source"
  • In the Audio|Video Details modal, add buttons and some suggestive text for adding alternate playback sources
  • Don't show "Create Audio|Video Playlist" menu items until the user has uploaded audio or video files

See #27437.

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

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/js/media-editor.js

    r27542 r27608  
    1212
    1313    /**
     14     * A helper mixin function to avoid truthy and falsey values being
     15     *   passed as an input that expects booleans. If key is undefined in the map,
     16     *   but has a default value, set it.
     17     *
     18     * @param {object} attrs Map of props from a shortcode or settings.
     19     * @param {string} key The key within the passed map to check for a value.
     20     * @returns {mixed|undefined} The original or coerced value of key within attrs
     21     */
     22    wp.media.coerce = function ( attrs, key ) {
     23        if ( _.isUndefined( attrs[ key ] ) && ! _.isUndefined( this.defaults[ key ] ) ) {
     24            attrs[ key ] = this.defaults[ key ];
     25        } else if ( 'true' === attrs[ key ] ) {
     26            attrs[ key ] = true;
     27        } else if ( 'false' === attrs[ key ] ) {
     28            attrs[ key ] = false;
     29        }
     30        return attrs[ key ];
     31    };
     32
     33    /**
    1434     * wp.media.string
    1535     * @namespace
     
    275295    };
    276296
    277     /**
    278      * @mixin
    279      */
    280     wp.media.mixin = {
    281         /**
    282          * A helper function to avoid truthy and falsey values being
    283          *   passed as an input that expects booleans. If key is undefined in the map,
    284          *   but has a default value, set it.
    285          *
    286          * @param {object} attrs Map of props from a shortcode or settings.
    287          * @param {string} key The key within the passed map to check for a value.
    288          * @returns {mixed|undefined} The original or coerced value of key within attrs
    289          */
    290         coerce: function ( attrs, key ) {
    291             if ( _.isUndefined( attrs[ key ] ) && ! _.isUndefined( this.defaults[ key ] ) ) {
    292                 attrs[ key ] = this.defaults[ key ];
    293             } else if ( 'true' === attrs[ key ] ) {
    294                 attrs[ key ] = true;
    295             } else if ( 'false' === attrs[ key ] ) {
    296                 attrs[ key ] = false;
    297             }
    298             return attrs[ key ];
    299         },
    300 
    301         pauseAllPlayers: function () {
    302             var p;
    303             if ( window.mejs && window.mejs.players ) {
    304                 for ( p in window.mejs.players ) {
    305                     window.mejs.players[p].pause();
    306                 }
    307             }
    308         },
    309 
    310         ua: {
    311             is : function (browser) {
    312                 var passes = false, ua = window.navigator.userAgent;
    313 
    314                 switch ( browser ) {
    315                     case 'oldie':
    316                         passes = ua.match(/MSIE [6-8]/gi) !== null;
    317                     break;
    318                     case 'ie':
    319                         passes = ua.match(/MSIE/gi) !== null;
    320                     break;
    321                     case 'ff':
    322                         passes = ua.match(/firefox/gi) !== null;
    323                     break;
    324                     case 'opera':
    325                         passes = ua.match(/OPR/) !== null;
    326                     break;
    327                     case 'safari':
    328                         passes = ua.match(/safari/gi) !== null && ua.match(/chrome/gi) === null;
    329                     break;
    330                     case 'chrome':
    331                         passes = ua.match(/safari/gi) && ua.match(/chrome/gi) !== null;
    332                     break;
    333                 }
    334 
    335                 return passes;
    336             }
    337         },
    338 
    339         compat :{
    340             'opera' : {
    341                 audio: ['ogg', 'wav'],
    342                 video: ['ogg', 'webm']
    343             },
    344             'chrome' : {
    345                 audio: ['ogg', 'mpeg', 'x-ms-wma'],
    346                 video: ['ogg', 'webm', 'mp4', 'm4v', 'mpeg']
    347             },
    348             'ff' : {
    349                 audio: ['ogg', 'mpeg'],
    350                 video: ['ogg', 'webm']
    351             },
    352             'safari' : {
    353                 audio: ['mpeg', 'wav'],
    354                 video: ['mp4', 'm4v', 'mpeg', 'x-ms-wmv', 'quicktime']
    355             },
    356             'ie' : {
    357                 audio: ['mpeg'],
    358                 video: ['mp4', 'm4v', 'mpeg']
    359             }
    360         },
    361 
    362         isCompatible: function ( media ) {
    363             if ( ! media.find( 'source' ).length ) {
    364                 return false;
    365             }
    366 
    367             var ua = this.ua, test = false, found = false, sources;
    368 
    369             if ( ua.is( 'oldIE' ) ) {
    370                 return false;
    371             }
    372 
    373             sources = media.find( 'source' );
    374 
    375             _.find( this.compat, function (supports, browser) {
    376                 if ( ua.is( browser ) ) {
    377                     found = true;
    378                     _.each( sources, function (elem) {
    379                         var audio = new RegExp( 'audio\/(' + supports.audio.join('|') + ')', 'gi' ),
    380                             video = new RegExp( 'video\/(' + supports.video.join('|') + ')', 'gi' );
    381 
    382                         if ( elem.type.match( video ) !== null || elem.type.match( audio ) !== null ) {
    383                             test = true;
    384                         }
    385                     } );
    386                 }
    387 
    388                 return test || found;
    389             } );
    390 
    391             return test;
    392         },
    393 
    394         /**
    395          * Override the MediaElement method for removing a player.
    396          *  MediaElement tries to pull the audio/video tag out of
    397          *  its container and re-add it to the DOM.
    398          */
    399         removePlayer: function() {
    400             var t = this.player, featureIndex, feature;
    401 
    402             // invoke features cleanup
    403             for ( featureIndex in t.options.features ) {
    404                 feature = t.options.features[featureIndex];
    405                 if ( t['clean' + feature] ) {
    406                     try {
    407                         t['clean' + feature](t);
    408                     } catch (e) {}
    409                 }
    410             }
    411 
    412             if ( ! t.isDynamic ) {
    413                 t.$node.remove();
    414             }
    415 
    416             if ( 'native' !== t.media.pluginType ) {
    417                 t.media.remove();
    418             }
    419 
    420             delete window.mejs.players[t.id];
    421 
    422             t.container.remove();
    423             t.globalUnbind();
    424             delete t.node.player;
    425         },
    426 
    427         /**
    428          * Allows any class that has set 'player' to a MediaElementPlayer
    429          *  instance to remove the player when listening to events.
    430          *
    431          *  Examples: modal closes, shortcode properties are removed, etc.
    432          */
    433         unsetPlayer : function() {
    434             if ( this.player ) {
    435                 wp.media.mixin.pauseAllPlayers();
    436                 wp.media.mixin.removePlayer.apply( this );
    437                 this.player = false;
    438             }
    439         }
    440     };
    441 
    442297    wp.media.collection = function(attributes) {
    443298        var collections = {};
    444299
    445300        return _.extend( attributes, {
    446             coerce : wp.media.mixin.coerce,
     301            coerce : wp.media.coerce,
    447302            /**
    448303             * Retrieve attachments based on the properties of the passed shortcode
     
    670525    });
    671526
    672     wp.media.playlist = new wp.media.collection({
    673         tag: 'playlist',
    674         type : 'audio',
    675         editTitle : wp.media.view.l10n.editPlaylistTitle,
    676         defaults : {
    677             id: wp.media.view.settings.post.id,
    678             style: 'light',
    679             tracklist: true,
    680             tracknumbers: true,
    681             images: true,
    682             artists: true
    683         }
    684     });
    685 
    686     wp.media['video-playlist'] = new wp.media.collection({
    687         tag: 'video-playlist',
    688         type : 'video',
    689         editTitle : wp.media.view.l10n.editVideoPlaylistTitle,
    690         defaults : {
    691             id: wp.media.view.settings.post.id,
    692             style: 'light',
    693             tracklist: false,
    694             tracknumbers: false,
    695             images: true
    696         }
    697     });
    698 
    699     /**
    700      * @namespace
    701      */
    702     wp.media.audio = {
    703         coerce : wp.media.mixin.coerce,
    704 
    705         defaults : {
    706             id : wp.media.view.settings.post.id,
    707             src      : '',
    708             loop     : false,
    709             autoplay : false,
    710             preload  : 'none'
    711         },
    712 
    713         edit : function (data) {
    714             var frame, shortcode = wp.shortcode.next( 'audio', data ).shortcode;
    715             frame = wp.media({
    716                 frame: 'audio',
    717                 state: 'audio-details',
    718                 metadata: _.defaults(
    719                     shortcode.attrs.named,
    720                     wp.media.audio.defaults
    721                 )
    722             });
    723 
    724             return frame;
    725         },
    726 
    727         shortcode : function (shortcode) {
    728             var self = this;
    729 
    730             _.each( wp.media.audio.defaults, function( value, key ) {
    731                 shortcode[ key ] = self.coerce( shortcode, key );
    732 
    733                 if ( value === shortcode[ key ] ) {
    734                     delete shortcode[ key ];
    735                 }
    736             });
    737 
    738             return wp.shortcode.string({
    739                 tag:     'audio',
    740                 attrs:   shortcode
    741             });
    742         }
    743     };
    744 
    745     /**
    746      * @namespace
    747      */
    748     wp.media.video = {
    749         coerce : wp.media.mixin.coerce,
    750 
    751         defaults : {
    752             id : wp.media.view.settings.post.id,
    753             src : '',
    754             poster : '',
    755             loop : false,
    756             autoplay : false,
    757             preload : 'metadata',
    758             content : ''
    759         },
    760 
    761         edit : function (data) {
    762             var frame,
    763                 defaults = this.defaults,
    764                 shortcode = wp.shortcode.next( 'video', data ).shortcode,
    765                 attrs;
    766 
    767             attrs = shortcode.attrs.named;
    768             attrs.content = shortcode.content;
    769 
    770             frame = wp.media({
    771                 frame: 'video',
    772                 state: 'video-details',
    773                 metadata: _.defaults( attrs, defaults )
    774             });
    775 
    776             return frame;
    777         },
    778 
    779         shortcode : function (shortcode) {
    780             var self = this, content = shortcode.content;
    781             delete shortcode.content;
    782 
    783             _.each( this.defaults, function( value, key ) {
    784                 shortcode[ key ] = self.coerce( shortcode, key );
    785 
    786                 if ( value === shortcode[ key ] ) {
    787                     delete shortcode[ key ];
    788                 }
    789             });
    790 
    791             return wp.shortcode.string({
    792                 tag:     'video',
    793                 attrs:   shortcode,
    794                 content: content
    795             });
    796         }
    797     };
    798 
    799527    /**
    800528     * wp.media.featuredImage
     
    12801008                        options.state = 'gallery';
    12811009                        options.title = wp.media.view.l10n.createGalleryTitle;
    1282                     } else if ( elem.hasClass( 'playlist' ) ) {
    1283                         options.state = 'playlist';
    1284                         options.title = wp.media.view.l10n.createPlaylistTitle;
    1285                     } else if ( elem.hasClass( 'video-playlist' ) ) {
    1286                         options.state = 'video-playlist';
    1287                         options.title = wp.media.view.l10n.createVideoPlaylistTitle;
    12881010                    }
    12891011
    12901012                    wp.media.editor.open( editor, options );
    1291                 })
    1292                 .on( 'click', '.wp-switch-editor', wp.media.mixin.pauseAllPlayers );
     1013                });
    12931014
    12941015            // Initialize and render the Editor drag-and-drop uploader.
  • trunk/src/wp-includes/js/media-models.js

    r27536 r27608  
    4040
    4141        delete attributes.frame;
     42
     43        media.frame = frame;
    4244
    4345        return frame;
     
    450452            this.set( 'width', size.width );
    451453            this.set( 'height', size.height );
    452         }
    453     });
    454 
    455     /**
    456      * wp.media.model.PostMedia
    457      *
    458      * @constructor
    459      * @augments Backbone.Model
    460      **/
    461     media.model.PostMedia = Backbone.Model.extend({
    462         initialize: function() {
    463             this.attachment = false;
    464         },
    465 
    466         setSource: function ( attachment ) {
    467             this.attachment = attachment;
    468             this.extension = attachment.get('filename' ).split('.').pop();
    469 
    470             if ( this.get( 'src' ) && this.extension === this.get( 'src' ).split('.').pop() ) {
    471                 this.unset( 'src' );
    472             }
    473 
    474             if ( _.contains( wp.media.view.settings.embedExts, this.extension ) ) {
    475                 this.set( this.extension, this.attachment.get( 'url' ) );
    476             } else {
    477                 this.unset( this.extension );
    478             }
    479         },
    480 
    481         changeAttachment: function( attachment ) {
    482             var self = this;
    483 
    484             this.setSource( attachment );
    485 
    486             this.unset( 'src' );
    487             _.each( _.without( wp.media.view.settings.embedExts, this.extension ), function (ext) {
    488                 self.unset( ext );
    489             } );
    490454        }
    491455    });
  • trunk/src/wp-includes/js/media-views.js

    r27538 r27608  
    762762        initialize: function( options ) {
    763763            this.image = options.image;
    764             media.controller.State.prototype.initialize.apply( this, arguments );
    765         }
    766     });
    767 
    768     /**
    769      * wp.media.controller.AudioDetails
    770      *
    771      * @constructor
    772      * @augments wp.media.controller.State
    773      * @augments Backbone.Model
    774      */
    775     media.controller.AudioDetails = media.controller.State.extend({
    776         defaults: _.defaults({
    777             id: 'audio-details',
    778             toolbar: 'audio-details',
    779             title: l10n.audioDetailsTitle,
    780             content: 'audio-details',
    781             menu: 'audio-details',
    782             router: false,
    783             attachment: false,
    784             priority: 60,
    785             editing: false
    786         }, media.controller.Library.prototype.defaults ),
    787 
    788         initialize: function( options ) {
    789             this.media = options.media;
    790             media.controller.State.prototype.initialize.apply( this, arguments );
    791         }
    792     });
    793 
    794     /**
    795      * wp.media.controller.VideoDetails
    796      *
    797      * @constructor
    798      * @augments wp.media.controller.State
    799      * @augments Backbone.Model
    800      */
    801     media.controller.VideoDetails = media.controller.State.extend({
    802         defaults: _.defaults({
    803             id: 'video-details',
    804             toolbar: 'video-details',
    805             title: l10n.videoDetailsTitle,
    806             content: 'video-details',
    807             menu: 'video-details',
    808             router: false,
    809             attachment: false,
    810             priority: 60,
    811             editing: false
    812         }, media.controller.Library.prototype.defaults ),
    813 
    814         initialize: function( options ) {
    815             this.media = options.media;
    816764            media.controller.State.prototype.initialize.apply( this, arguments );
    817765        }
     
    19311879
    19321880        createStates: function() {
    1933             var options = this.options;
     1881            var options = this.options, counts;
    19341882
    19351883            // Add the default states.
     
    19911939                    collectionType: 'gallery',
    19921940                    title:          l10n.addToGalleryTitle
    1993                 }),
    1994 
    1995                 new media.controller.Library({
    1996                     id:         'playlist',
    1997                     title:      l10n.createPlaylistTitle,
    1998                     priority:   60,
    1999                     toolbar:    'main-playlist',
    2000                     filterable: 'uploaded',
    2001                     multiple:   'add',
    2002                     editable:   false,
    2003 
    2004                     library:  media.query( _.defaults({
    2005                         type: 'audio'
    2006                     }, options.library ) )
    2007                 }),
    2008 
    2009                 // Playlist states.
    2010                 new media.controller.CollectionEdit({
    2011                     type:           'audio',
    2012                     collectionType: 'playlist',
    2013                     title:          l10n.editPlaylistTitle,
    2014                     SettingsView:   media.view.Settings.Playlist,
    2015                     library:        options.selection,
    2016                     editing:        options.editing,
    2017                     menu:           'playlist',
    2018                     dragInfoText:   l10n.playlistDragInfo,
    2019                     dragInfo:       false
    2020                 }),
    2021 
    2022                 new media.controller.CollectionAdd({
    2023                     type: 'audio',
    2024                     collectionType: 'playlist',
    2025                     title: l10n.addToPlaylistTitle
    2026                 }),
    2027 
    2028                 new media.controller.Library({
    2029                     id:         'video-playlist',
    2030                     title:      l10n.createVideoPlaylistTitle,
    2031                     priority:   60,
    2032                     toolbar:    'main-video-playlist',
    2033                     filterable: 'uploaded',
    2034                     multiple:   'add',
    2035                     editable:   false,
    2036 
    2037                     library:  media.query( _.defaults({
    2038                         type: 'video'
    2039                     }, options.library ) )
    2040                 }),
    2041 
    2042                 // Video Playlist states.
    2043                 new media.controller.CollectionEdit({
    2044                     type:           'video',
    2045                     collectionType: 'video-playlist',
    2046                     title:          l10n.editVideoPlaylistTitle,
    2047                     SettingsView:   media.view.Settings.Playlist,
    2048                     library:        options.selection,
    2049                     editing:        options.editing,
    2050                     menu:           'video-playlist',
    2051                     dragInfoText:   l10n.videoPlaylistDragInfo,
    2052                     dragInfo:       false
    2053                 }),
    2054 
    2055                 new media.controller.CollectionAdd({
    2056                     type:           'video',
    2057                     collectionType: 'video-playlist',
    2058                     title:          l10n.addToVideoPlaylistTitle
    20591941                })
    20601942            ]);
    20611943
     1944            counts = media.playlist.counts();
     1945
     1946            if ( counts.audio ) {
     1947                this.states.add( media.playlist.states(options) );
     1948            }
     1949
     1950            if ( counts.video ) {
     1951                this.states.add( media.playlist.videoStates(options) );
     1952            }
    20621953
    20631954            if ( media.view.settings.post.featuredImageId ) {
     
    27472638
    27482639    /**
    2749      * wp.media.view.MediaFrame.MediaDetails
    2750      *
    2751      * @constructor
    2752      * @augments wp.media.view.MediaFrame.Select
    2753      * @augments wp.media.view.MediaFrame
    2754      * @augments wp.media.view.Frame
    2755      * @augments wp.media.View
    2756      * @augments wp.Backbone.View
    2757      * @augments Backbone.View
    2758      * @mixes wp.media.controller.StateMachine
    2759      */
    2760     media.view.MediaFrame.MediaDetails = media.view.MediaFrame.Select.extend({
    2761         defaults: {
    2762             id:      'media',
    2763             url:     '',
    2764             menu:    'media-details',
    2765             content: 'media-details',
    2766             toolbar: 'media-details',
    2767             type:    'link',
    2768             priority: 120
    2769         },
    2770 
    2771         initialize: function( options ) {
    2772             this.DetailsView = options.DetailsView;
    2773             this.cancelText = options.cancelText;
    2774             this.addText = options.addText;
    2775 
    2776             this.media = new media.model.PostMedia( options.metadata );
    2777             this.options.selection = new media.model.Selection( this.media.attachment, { multiple: false } );
    2778             media.view.MediaFrame.Select.prototype.initialize.apply( this, arguments );
    2779         },
    2780 
    2781         bindHandlers: function() {
    2782             var menu = this.defaults.menu;
    2783 
    2784             media.view.MediaFrame.Select.prototype.bindHandlers.apply( this, arguments );
    2785 
    2786             this.on( 'menu:create:' + menu, this.createMenu, this );
    2787             this.on( 'content:render:' + menu, this.renderDetailsContent, this );
    2788             this.on( 'menu:render:' + menu, this.renderMenu, this );
    2789             this.on( 'toolbar:render:' + menu, this.renderDetailsToolbar, this );
    2790         },
    2791 
    2792         renderDetailsContent: function() {
    2793             var view = new this.DetailsView({
    2794                 controller: this,
    2795                 model: this.state().media,
    2796                 attachment: this.state().media.attachment
    2797             }).render();
    2798 
    2799             this.content.set( view );
    2800         },
    2801 
    2802         renderMenu: function( view ) {
    2803             var lastState = this.lastState(),
    2804                 previous = lastState && lastState.id,
    2805                 frame = this;
    2806 
    2807             view.set({
    2808                 cancel: {
    2809                     text:     this.cancelText,
    2810                     priority: 20,
    2811                     click:    function() {
    2812                         if ( previous ) {
    2813                             frame.setState( previous );
    2814                         } else {
    2815                             frame.close();
    2816                         }
    2817                     }
    2818                 },
    2819                 separateCancel: new media.View({
    2820                     className: 'separator',
    2821                     priority: 40
    2822                 })
    2823             });
    2824 
    2825         },
    2826 
    2827         renderDetailsToolbar: function() {
    2828             this.toolbar.set( new media.view.Toolbar({
    2829                 controller: this,
    2830                 items: {
    2831                     select: {
    2832                         style:    'primary',
    2833                         text:     l10n.update,
    2834                         priority: 80,
    2835 
    2836                         click: function() {
    2837                             var controller = this.controller,
    2838                                 state = controller.state();
    2839 
    2840                             controller.close();
    2841 
    2842                             state.trigger( 'update', controller.media.toJSON() );
    2843 
    2844                             // Restore and reset the default state.
    2845                             controller.setState( controller.options.state );
    2846                             controller.reset();
    2847                         }
    2848                     }
    2849                 }
    2850             }) );
    2851         },
    2852 
    2853         renderReplaceToolbar: function() {
    2854             this.toolbar.set( new media.view.Toolbar({
    2855                 controller: this,
    2856                 items: {
    2857                     replace: {
    2858                         style:    'primary',
    2859                         text:     l10n.replace,
    2860                         priority: 80,
    2861 
    2862                         click: function() {
    2863                             var controller = this.controller,
    2864                                 state = controller.state(),
    2865                                 selection = state.get( 'selection' ),
    2866                                 attachment = selection.single();
    2867 
    2868                             controller.media.changeAttachment( attachment );
    2869 
    2870                             state.trigger( 'replace', controller.media.toJSON() );
    2871 
    2872                             // Restore and reset the default state.
    2873                             controller.setState( controller.options.state );
    2874                             controller.reset();
    2875                         }
    2876                     }
    2877                 }
    2878             }) );
    2879         },
    2880 
    2881         renderAddSourceToolbar: function() {
    2882             this.toolbar.set( new media.view.Toolbar({
    2883                 controller: this,
    2884                 items: {
    2885                     replace: {
    2886                         style:    'primary',
    2887                         text:     this.addText,
    2888                         priority: 80,
    2889 
    2890                         click: function() {
    2891                             var controller = this.controller,
    2892                                 state = controller.state(),
    2893                                 selection = state.get( 'selection' ),
    2894                                 attachment = selection.single();
    2895 
    2896                             controller.media.setSource( attachment );
    2897 
    2898                             state.trigger( 'add-source', controller.media.toJSON() );
    2899 
    2900                             // Restore and reset the default state.
    2901                             controller.setState( controller.options.state );
    2902                             controller.reset();
    2903                         }
    2904                     }
    2905                 }
    2906             }) );
    2907         }
    2908     });
    2909 
    2910     /**
    2911      * wp.media.view.MediaFrame.AudioDetails
    2912      *
    2913      * @constructor
    2914      * @augments wp.media.view.MediaFrame.MediaDetails
    2915      * @augments wp.media.view.MediaFrame.Select
    2916      * @augments wp.media.view.MediaFrame
    2917      * @augments wp.media.view.Frame
    2918      * @augments wp.media.View
    2919      * @augments wp.Backbone.View
    2920      * @augments Backbone.View
    2921      * @mixes wp.media.controller.StateMachine
    2922      */
    2923     media.view.MediaFrame.AudioDetails = media.view.MediaFrame.MediaDetails.extend({
    2924         defaults: {
    2925             id:      'audio',
    2926             url:     '',
    2927             menu:    'audio-details',
    2928             content: 'audio-details',
    2929             toolbar: 'audio-details',
    2930             type:    'link',
    2931             title:    l10n.audioDetailsTitle,
    2932             priority: 120
    2933         },
    2934 
    2935         initialize: function( options ) {
    2936             options.DetailsView = media.view.AudioDetails;
    2937             options.cancelText = l10n.audioDetailsCancel;
    2938             options.addText = l10n.audioAddSourceTitle;
    2939 
    2940             media.view.MediaFrame.MediaDetails.prototype.initialize.call( this, options );
    2941         },
    2942 
    2943         bindHandlers: function() {
    2944             media.view.MediaFrame.MediaDetails.prototype.bindHandlers.apply( this, arguments );
    2945 
    2946             this.on( 'toolbar:render:replace-audio', this.renderReplaceToolbar, this );
    2947             this.on( 'toolbar:render:add-audio-source', this.renderAddSourceToolbar, this );
    2948         },
    2949 
    2950         createStates: function() {
    2951             this.states.add([
    2952                 new media.controller.AudioDetails( {
    2953                     media: this.media,
    2954                     editable: false,
    2955                     menu: 'audio-details'
    2956                 } ),
    2957 
    2958                 new media.controller.MediaLibrary( {
    2959                     type: 'audio',
    2960                     id: 'replace-audio',
    2961                     title: l10n.audioReplaceTitle,
    2962                     toolbar: 'replace-audio',
    2963                     media: this.media,
    2964                     menu: 'audio-details'
    2965                 } ),
    2966 
    2967                 new media.controller.MediaLibrary( {
    2968                     type: 'audio',
    2969                     id: 'add-audio-source',
    2970                     title: l10n.audioAddSourceTitle,
    2971                     toolbar: 'add-audio-source',
    2972                     media: this.media,
    2973                     menu: 'audio-details'
    2974                 } )
    2975             ]);
    2976         }
    2977     });
    2978 
    2979     /**
    2980      * wp.media.view.MediaFrame.VideoDetails
    2981      *
    2982      * @constructor
    2983      * @augments wp.media.view.MediaFrame.MediaDetails
    2984      * @augments wp.media.view.MediaFrame.Select
    2985      * @augments wp.media.view.MediaFrame
    2986      * @augments wp.media.view.Frame
    2987      * @augments wp.media.View
    2988      * @augments wp.Backbone.View
    2989      * @augments Backbone.View
    2990      * @mixes wp.media.controller.StateMachine
    2991      */
    2992     media.view.MediaFrame.VideoDetails = media.view.MediaFrame.MediaDetails.extend({
    2993         defaults: {
    2994             id:      'video',
    2995             url:     '',
    2996             menu:    'video-details',
    2997             content: 'video-details',
    2998             toolbar: 'video-details',
    2999             type:    'link',
    3000             title:    l10n.videoDetailsTitle,
    3001             priority: 120
    3002         },
    3003 
    3004         initialize: function( options ) {
    3005             options.DetailsView = media.view.VideoDetails;
    3006             options.cancelText = l10n.videoDetailsCancel;
    3007             options.addText = l10n.videoAddSourceTitle;
    3008 
    3009             media.view.MediaFrame.MediaDetails.prototype.initialize.call( this, options );
    3010         },
    3011 
    3012         bindHandlers: function() {
    3013             media.view.MediaFrame.MediaDetails.prototype.bindHandlers.apply( this, arguments );
    3014 
    3015             this.on( 'toolbar:render:replace-video', this.renderReplaceToolbar, this );
    3016             this.on( 'toolbar:render:add-video-source', this.renderAddSourceToolbar, this );
    3017             this.on( 'toolbar:render:select-poster-image', this.renderSelectPosterImageToolbar, this );
    3018             this.on( 'toolbar:render:add-track', this.renderAddTrackToolbar, this );
    3019         },
    3020 
    3021         createStates: function() {
    3022             this.states.add([
    3023                 new media.controller.VideoDetails({
    3024                     media: this.media,
    3025                     editable: false,
    3026                     menu: 'video-details'
    3027                 }),
    3028 
    3029                 new media.controller.MediaLibrary( {
    3030                     type: 'video',
    3031                     id: 'replace-video',
    3032                     title: l10n.videoReplaceTitle,
    3033                     toolbar: 'replace-video',
    3034                     media: this.media,
    3035                     menu: 'video-details'
    3036                 } ),
    3037 
    3038                 new media.controller.MediaLibrary( {
    3039                     type: 'video',
    3040                     id: 'add-video-source',
    3041                     title: l10n.videoAddSourceTitle,
    3042                     toolbar: 'add-video-source',
    3043                     media: this.media,
    3044                     menu: 'video-details'
    3045                 } ),
    3046 
    3047                 new media.controller.MediaLibrary( {
    3048                     type: 'image',
    3049                     id: 'select-poster-image',
    3050                     title: l10n.videoSelectPosterImageTitle,
    3051                     toolbar: 'select-poster-image',
    3052                     media: this.media,
    3053                     menu: 'video-details'
    3054                 } ),
    3055 
    3056                 new media.controller.MediaLibrary( {
    3057                     type: 'text',
    3058                     id: 'add-track',
    3059                     title: l10n.videoAddTrackTitle,
    3060                     toolbar: 'add-track',
    3061                     media: this.media,
    3062                     menu: 'video-details'
    3063                 } )
    3064             ]);
    3065         },
    3066 
    3067         renderSelectPosterImageToolbar: function() {
    3068             this.toolbar.set( new media.view.Toolbar({
    3069                 controller: this,
    3070                 items: {
    3071                     replace: {
    3072                         style:    'primary',
    3073                         text:     l10n.videoSelectPosterImageTitle,
    3074                         priority: 80,
    3075 
    3076                         click: function() {
    3077                             var controller = this.controller,
    3078                                 state = controller.state(),
    3079                                 selection = state.get( 'selection' ),
    3080                                 attachment = selection.single();
    3081 
    3082                             controller.media.set( 'poster', attachment.get( 'url' ) );
    3083 
    3084                             state.trigger( 'set-poster-image', controller.media.toJSON() );
    3085 
    3086                             // Restore and reset the default state.
    3087                             controller.setState( controller.options.state );
    3088                             controller.reset();
    3089                         }
    3090                     }
    3091                 }
    3092             }) );
    3093         },
    3094 
    3095         renderAddTrackToolbar: function() {
    3096             this.toolbar.set( new media.view.Toolbar({
    3097                 controller: this,
    3098                 items: {
    3099                     replace: {
    3100                         style:    'primary',
    3101                         text:     l10n.videoAddTrackTitle,
    3102                         priority: 80,
    3103 
    3104                         click: function() {
    3105                             var controller = this.controller,
    3106                                 state = controller.state(),
    3107                                 selection = state.get( 'selection' ),
    3108                                 attachment = selection.single(),
    3109                                 content = controller.media.get( 'content' );
    3110 
    3111                             if ( -1 === content.indexOf( attachment.get( 'url' ) ) ) {
    3112                                 content += [
    3113                                     '<track srclang="en" label="English"kind="subtitles" src="',
    3114                                     attachment.get( 'url' ),
    3115                                     '" />'
    3116                                 ].join('');
    3117 
    3118                                 controller.media.set( 'content', content );
    3119                             }
    3120 
    3121                             state.trigger( 'add-track', controller.media.toJSON() );
    3122 
    3123                             // Restore and reset the default state.
    3124                             controller.setState( controller.options.state );
    3125                             controller.reset();
    3126                         }
    3127                     }
    3128                 }
    3129             }) );
    3130         }
    3131     });
    3132 
    3133     /**
    31342640     * wp.media.view.Modal
    31352641     *
     
    66646170
    66656171    /**
    6666      * wp.media.view.AudioDetails
    6667      *
    6668      * @contructor
    6669      * @augments wp.media.view.MediaDetails
    6670      * @augments wp.media.view.Settings.AttachmentDisplay
    6671      * @augments wp.media.view.Settings
    6672      * @augments wp.media.View
    6673      * @augments wp.Backbone.View
    6674      * @augments Backbone.View
    6675      */
    6676     media.view.AudioDetails = media.view.MediaDetails.extend({
    6677         className: 'audio-details',
    6678         template:  media.template('audio-details'),
    6679 
    6680         setMedia: function() {
    6681             var audio = this.$('.wp-audio-shortcode');
    6682 
    6683             if ( audio.find( 'source' ).length ) {
    6684                 if ( audio.is(':hidden') ) {
    6685                     audio.show();
    6686                 }
    6687                 this.media = media.view.MediaDetails.prepareSrc( audio.get(0) );
    6688             } else {
    6689                 audio.hide();
    6690                 this.media = false;
    6691             }
    6692 
    6693             return this;
    6694         }
    6695     });
    6696 
    6697     /**
    6698      * wp.media.view.VideoDetails
    6699      *
    6700      * @contructor
    6701      * @augments wp.media.view.MediaDetails
    6702      * @augments wp.media.view.Settings.AttachmentDisplay
    6703      * @augments wp.media.view.Settings
    6704      * @augments wp.media.View
    6705      * @augments wp.Backbone.View
    6706      * @augments Backbone.View
    6707      */
    6708     media.view.VideoDetails = media.view.MediaDetails.extend({
    6709         className: 'video-details',
    6710         template:  media.template('video-details'),
    6711 
    6712         setMedia: function() {
    6713             var video = this.$('.wp-video-shortcode');
    6714 
    6715             if ( video.find( 'source' ).length ) {
    6716                 if ( video.is(':hidden') ) {
    6717                     video.show();
    6718                 }
    6719 
    6720                 if ( ! video.hasClass('youtube-video') ) {
    6721                     this.media = media.view.MediaDetails.prepareSrc( video.get(0) );
    6722                 } else {
    6723                     this.media = video.get(0);
    6724                 }
    6725             } else {
    6726                 video.hide();
    6727                 this.media = false;
    6728             }
    6729 
    6730             return this;
    6731         }
    6732     });
    6733 
    6734     /**
    67356172     * wp.media.view.Spinner
    67366173     *
  • trunk/src/wp-includes/js/mediaelement/wp-mediaelement.css

    r27534 r27608  
    2727.media-embed-details .embed-media-settings {
    2828    padding-top: 0;
     29    top: 28px;
    2930}
    3031
     
    4344.media-embed-details .setting a:hover {
    4445    color: #f00;
    45 }
    46 
    47 .media-embed-details .embed-media-settings {
    48     top: 0;
    4946}
    5047
  • trunk/src/wp-includes/media-template.php

    r27580 r27608  
    766766
    767767    <script type="text/html" id="tmpl-audio-details">
     768        <# var ext, html5types = { mp3: true, ogg: true }; #>
     769
    768770        <?php $audio_types = wp_get_audio_extensions(); ?>
    769771        <div class="media-embed media-embed-details">
    770772            <div class="embed-media-settings embed-audio-settings">
    771                 <div class="instructions media-instructions">{{{ wp.media.view.l10n.audioDetailsText }}}</div>
    772 
    773773                <?php wp_underscore_audio_template() ?>
    774774
    775                 <# if ( ! _.isEmpty( data.model.src ) ) { #>
     775                <# if ( ! _.isEmpty( data.model.src ) ) {
     776                    ext = data.model.src.split('.').pop();
     777                    if ( html5types[ ext ] ) {
     778                        delete html5types[ ext ];
     779                    }
     780                #>
    776781                <label class="setting">
    777782                    <span>SRC</span>
     
    783788
    784789                foreach ( $audio_types as $type ):
    785                 ?><# if ( ! _.isEmpty( data.model.<?php echo $type ?> ) ) { #>
     790                ?><# if ( ! _.isEmpty( data.model.<?php echo $type ?> ) ) {
     791                    if ( ! _.isUndefined( html5types.<?php echo $type ?> ) ) {
     792                        delete html5types.<?php echo $type ?>;
     793                    }
     794                #>
    786795                <label class="setting">
    787796                    <span><?php echo strtoupper( $type ) ?></span>
     
    791800                <# } #>
    792801                <?php endforeach ?>
     802
     803                <# if ( ! _.isEmpty( html5types ) ) { #>
     804                <div class="setting">
     805                    <span>{{{ wp.media.view.l10n.mediaHTML5Text }}}</span>
     806                    <div class="button-large">
     807                    <# _.each( html5types, function (value, type) { #>
     808                    <button class="button add-media-source">{{ type }}</button>
     809                    <# } ) #>
     810                    </div>
     811                </div>
     812                <# } #>
    793813
    794814                <div class="setting preload">
     
    816836
    817837    <script type="text/html" id="tmpl-video-details">
     838        <# var ext, html5types = { mp4: true, ogv: true, webm: true }; #>
     839
    818840        <?php $video_types = wp_get_video_extensions(); ?>
    819841        <div class="media-embed media-embed-details">
    820842            <div class="embed-media-settings embed-video-settings">
    821                 <div class="instructions media-instructions">{{{ wp.media.view.l10n.videoDetailsText }}}</div>
    822843                <div class="wp-video-holder">
    823844                <#
     
    833854                <?php wp_underscore_video_template() ?>
    834855
    835                 <# if ( ! _.isEmpty( data.model.src ) ) { #>
     856                <# if ( ! _.isEmpty( data.model.src ) ) {
     857                    ext = data.model.src.split('.').pop();
     858                    if ( html5types[ ext ] ) {
     859                        delete html5types[ ext ];
     860                    }
     861                #>
    836862                <label class="setting">
    837863                    <span>SRC</span>
     
    841867                <# } #>
    842868                <?php foreach ( $video_types as $type ):
    843                 ?><# if ( ! _.isEmpty( data.model.<?php echo $type ?> ) ) { #>
     869                ?><# if ( ! _.isEmpty( data.model.<?php echo $type ?> ) ) {
     870                    if ( ! _.isUndefined( html5types.<?php echo $type ?> ) ) {
     871                        delete html5types.<?php echo $type ?>;
     872                    }
     873                #>
    844874                <label class="setting">
    845875                    <span><?php echo strtoupper( $type ) ?></span>
     
    850880                <?php endforeach ?>
    851881                </div>
     882
     883                <# if ( ! _.isEmpty( html5types ) ) { #>
     884                <div class="setting">
     885                    <span>{{{ wp.media.view.l10n.mediaHTML5Text }}}</span>
     886                    <div class="button-large">
     887                    <# _.each( html5types, function (value, type) { #>
     888                    <button class="button add-media-source">{{ type }}</button>
     889                    <# } ) #>
     890                    </div>
     891                </div>
     892                <# } #>
     893
    852894                <# if ( ! _.isEmpty( data.model.poster ) ) { #>
    853895                <label class="setting">
  • trunk/src/wp-includes/media.php

    r27519 r27608  
    24012401        ),
    24022402        'defaultProps' => $props,
     2403        'attachmentCounts' => wp_count_attachments(),
    24032404        'embedExts'    => $exts,
    24042405        'embedMimes'   => $ext_mimes
     
    24962497        'suggestedHeight' => __( 'Suggested height is %d pixels.' ),
    24972498
     2499        'mediaHTML5Text'        => __( 'Add alternate sources for maximum HTML5 playback:' ),
     2500
    24982501        // Edit Audio
    24992502        'audioDetailsTitle'     => __( 'Audio Details' ),
     
    25012504        'audioAddSourceTitle'   => __( 'Add Audio Source' ),
    25022505        'audioDetailsCancel'    => __( 'Cancel Edit' ),
    2503         'audioDetailsText'      => __( '"Replace Audio" will remove all associated source files when you update. ' .
    2504             '"Add Audio Source" allows you to specify alternate sources for maximum native HTML5 audio playback.' ),
    25052506
    25062507        // Edit Video
     
    25092510        'videoAddSourceTitle'   => __( 'Add Video Source' ),
    25102511        'videoDetailsCancel'    => __( 'Cancel Edit' ),
    2511         'videoDetailsText'      => __( '"Replace Video" will remove all associated source files when you update. ' .
    2512             '"Add Video Source" allows you to specify alternate sources for maximum native HTML5 video playback.' ),
    25132512        'videoSelectPosterImageTitle' => _( 'Select Poster Image' ),
    25142513        'videoAddTrackTitle'    => __( 'Add Subtitles' ),
     
    25432542
    25442543    wp_enqueue_script( 'media-editor' );
     2544    wp_enqueue_script( 'media-audiovideo' );
    25452545    wp_enqueue_style( 'media-views' );
    25462546    wp_enqueue_style( 'imgareaselect' );
  • trunk/src/wp-includes/script-loader.php

    r27585 r27608  
    397397    $scripts->add( 'media-views',  "/wp-includes/js/media-views$suffix.js",  array( 'utils', 'media-models', 'wp-plupload', 'jquery-ui-sortable', 'wp-mediaelement', 'image-edit' ), false, 1 );
    398398    $scripts->add( 'media-editor', "/wp-includes/js/media-editor$suffix.js", array( 'shortcode', 'media-views' ), false, 1 );
     399    $scripts->add( 'media-audiovideo', "/wp-includes/js/media-audiovideo$suffix.js", array( 'media-editor' ), false, 1 );
    399400    $scripts->add( 'mce-view', "/wp-includes/js/mce-view$suffix.js", array( 'shortcode', 'media-models' ), false, 1 );
    400401
Note: See TracChangeset for help on using the changeset viewer.