WordPress.org

Make WordPress Core

Ticket #26631: 26631.10.diff

File 26631.10.diff, 39.1 KB (added by wonderboymusic, 7 years ago)
  • src/wp-includes/css/media-views.css

     
    595595        box-shadow: 0 4px 4px -4px rgba( 0, 0, 0, 0.1 );
    596596}
    597597
    598 .media-frame .media-toolbar .add-to-gallery {
    599         display: none;
    600 }
    601 
    602598.media-frame-title h1 {
    603599        padding: 0 16px;
    604600        font-size: 22px;
     
    14271423        margin: 1.4em 0 0.4em;
    14281424}
    14291425
    1430 .gallery-settings {
     1426.collection-settings {
    14311427        overflow: hidden;
    14321428}
    14331429
     
    18861882                border-top: none;
    18871883        }
    18881884
    1889         .gallery-settings h3 {
     1885        .collection-settings h3 {
    18901886                margin-top: 45px;
    18911887        }
    18921888
  • src/wp-includes/js/media-editor.js

     
    319319                                }
    320320
    321321                                if ( -1 !== jQuery.inArray( prop, ['playlist', 'video-playlist'] ) ) {
    322                                         _.each(['tracknumbers', 'tracklist', 'images'], function (setting) {
     322                                        _.each(['tracknumbers', 'tracklist', 'images', 'artists'], function (setting) {
    323323                                                if ( 'undefined' === typeof attrs[setting] ) {
    324324                                                        attrs['_' + setting] = wp.media[ prop ].defaults[ setting ];
    325325                                                } else if ( 'true' === attrs[setting] || true === attrs[setting] ) {
     
    395395                        }
    396396
    397397                        if ( -1 !== jQuery.inArray( prop, ['playlist', 'video-playlist'] ) ) {
    398                                 _.each(['tracknumbers', 'tracklist', 'images'], function (setting) {
     398                                _.each(['tracknumbers', 'tracklist', 'images', 'artists'], function (setting) {
    399399                                        if ( attrs['_' + setting] ) {
    400400                                                attrs[setting] = true;
    401401                                        } else {
     
    558558                }));
    559559        }());
    560560
     561        wp.media.playlist = (function() {
     562                var playlist = {
     563                        defaults : {
     564                                id: wp.media.view.settings.post.id,
     565                                style: 'light',
     566                                tracklist: true,
     567                                tracknumbers: true,
     568                                images: true,
     569                                artists: true
     570                        }
     571                };
     572
     573                return _.extend(playlist, wp.media.collection.instance( 'playlist', {
     574                        type : 'audio',
     575                        title : wp.media.view.l10n.editPlaylistTitle
     576                }));
     577        }());
     578
     579        wp.media['video-playlist'] = (function() {
     580                var playlist = {
     581                        defaults : {
     582                                id: wp.media.view.settings.post.id,
     583                                style: 'light',
     584                                tracklist: false,
     585                                tracknumbers: false,
     586                                images: false
     587                        }
     588                };
     589
     590                return _.extend(playlist, wp.media.collection.instance( 'video-playlist', {
     591                        type : 'video',
     592                        title : wp.media.view.l10n.editVideoPlaylistTitle
     593                }));
     594        }());
     595
    561596        /**
    562597         * wp.media.featuredImage
    563598         * @namespace
     
    776811                                this.insert( wp.media.gallery.shortcode( selection ).string() );
    777812                        }, this );
    778813
     814                        workflow.state('playlist-edit').on( 'update', function( selection ) {
     815                                this.insert( wp.media.playlist.shortcode( selection ).string() );
     816                        }, this );
     817
     818                        workflow.state('video-playlist-edit').on( 'update', function( selection ) {
     819                                this.insert( wp.media['video-playlist'].shortcode( selection ).string() );
     820                        }, this );
     821
    779822                        workflow.state('embed').on( 'select', function() {
    780823                                /**
    781824                                 * @this wp.media.editor
     
    10151058                                if ( elem.hasClass( 'gallery' ) ) {
    10161059                                        options.state = 'gallery';
    10171060                                        options.title = wp.media.view.l10n.createGalleryTitle;
     1061                                } else if ( elem.hasClass( 'playlist' ) ) {
     1062                                        options.state = 'playlist';
     1063                                        options.title = wp.media.view.l10n.createPlaylistTitle;
     1064                                } else if ( elem.hasClass( 'video-playlist' ) ) {
     1065                                        options.state = 'video-playlist';
     1066                                        options.title = wp.media.view.l10n.createVideoPlaylistTitle;
    10181067                                }
    10191068
    10201069                                wp.media.editor.open( editor, options );
  • src/wp-includes/js/media-views.js

     
    941941                        title: l10n.addToGalleryTitle
    942942                }
    943943        });
     944
     945        // wp.media.controller.PlaylistEdit
     946        // -------------------------------
     947        media.controller.PlaylistEdit = media.controller.CollectionEdit( 'playlist', {
     948                type: 'audio',
     949                settings: 'Playlist',
     950                dragInfoText: l10n.playlistDragInfo,
     951                defaults: {
     952                        title: l10n.editPlaylistTitle,
     953                        dragInfo : false
     954                }
     955        });
     956
     957        // wp.media.controller.PlaylistAdd
     958        // ---------------------------------
     959        media.controller.PlaylistAdd = media.controller.CollectionAdd( 'playlist', {
     960                type: 'audio',
     961                defaults: {
     962                        title: l10n.addToPlaylistTitle
     963                }
     964        });
     965
     966        // wp.media.controller.VideoPlaylistEdit
     967        // -------------------------------
     968        media.controller.VideoPlaylistEdit = media.controller.CollectionEdit( 'video-playlist', {
     969                type: 'video',
     970                settings: 'Playlist',
     971                dragInfoText: l10n.videoPlaylistDragInfo,
     972                defaults: {
     973                        title: l10n.editVideoPlaylistTitle,
     974                        dragInfo : false
     975                }
     976        });
     977
     978        // wp.media.controller.VideoPlaylistAdd
     979        // ---------------------------------
     980        media.controller.VideoPlaylistAdd = media.controller.CollectionAdd( 'video-playlist', {
     981                type: 'video',
     982                defaults: {
     983                        title: l10n.addToVideoPlaylistTitle
     984                }
     985        });
     986
    944987        /**
    945988         * wp.media.controller.FeaturedImage
    946989         *
     
    17671810                                        menu:    'gallery'
    17681811                                }),
    17691812
    1770                                 new media.controller.GalleryAdd()
     1813                                new media.controller.GalleryAdd(),
     1814
     1815                                new media.controller.Library({
     1816                                        id:         'playlist',
     1817                                        title:      l10n.createPlaylistTitle,
     1818                                        priority:   60,
     1819                                        toolbar:    'main-playlist',
     1820                                        filterable: 'uploaded',
     1821                                        multiple:   'add',
     1822                                        editable:   false,
     1823
     1824                                        library:  media.query( _.defaults({
     1825                                                type: 'audio'
     1826                                        }, options.library ) )
     1827                                }),
     1828
     1829                                // Playlist states.
     1830                                new media.controller.PlaylistEdit({
     1831                                        library: options.selection,
     1832                                        editing: options.editing,
     1833                                        menu:    'playlist'
     1834                                }),
     1835
     1836                                new media.controller.PlaylistAdd(),
     1837
     1838                                new media.controller.Library({
     1839                                        id:         'video-playlist',
     1840                                        title:      l10n.createVideoPlaylistTitle,
     1841                                        priority:   60,
     1842                                        toolbar:    'main-video-playlist',
     1843                                        filterable: 'uploaded',
     1844                                        multiple:   'add',
     1845                                        editable:   false,
     1846
     1847                                        library:  media.query( _.defaults({
     1848                                                type: 'video'
     1849                                        }, options.library ) )
     1850                                }),
     1851
     1852                                // Video Playlist states.
     1853                                new media.controller.VideoPlaylistEdit({
     1854                                        library: options.selection,
     1855                                        editing: options.editing,
     1856                                        menu:    'video-playlist'
     1857                                }),
     1858
     1859                                new media.controller.VideoPlaylistAdd()
    17711860                        ]);
    17721861
    17731862
     
    17821871                         */
    17831872                        media.view.MediaFrame.Select.prototype.bindHandlers.apply( this, arguments );
    17841873                        this.on( 'menu:create:gallery', this.createMenu, this );
     1874                        this.on( 'menu:create:playlist', this.createMenu, this );
     1875                        this.on( 'menu:create:video-playlist', this.createMenu, this );
    17851876                        this.on( 'toolbar:create:main-insert', this.createToolbar, this );
    1786                         this.on( 'toolbar:create:main-gallery', this.createToolbar, this );
     1877                        this.on( 'toolbar:create:main-gallery', this.createToolbar, this );
     1878                        this.on( 'toolbar:create:main-playlist', this.createToolbar, this );
     1879                        this.on( 'toolbar:create:main-video-playlist', this.createToolbar, this );
    17871880                        this.on( 'toolbar:create:featured-image', this.featuredImageToolbar, this );
    17881881                        this.on( 'toolbar:create:main-embed', this.mainEmbedToolbar, this );
    17891882
     
    17901883                        var handlers = {
    17911884                                menu: {
    17921885                                        'default': 'mainMenu',
    1793                                         'gallery': 'galleryMenu'
     1886                                        'gallery': 'galleryMenu',
     1887                                        'playlist': 'playlistMenu',
     1888                                        'video-playlist': 'videoPlaylistMenu'
    17941889                                },
    17951890
    17961891                                content: {
     
    18021897                                        'main-insert':      'mainInsertToolbar',
    18031898                                        'main-gallery':     'mainGalleryToolbar',
    18041899                                        'gallery-edit':     'galleryEditToolbar',
    1805                                         'gallery-add':      'galleryAddToolbar'
     1900                                        'gallery-add':      'galleryAddToolbar',
     1901                                        'main-playlist':        'mainPlaylistToolbar',
     1902                                        'playlist-edit':        'playlistEditToolbar',
     1903                                        'playlist-add':         'playlistAddToolbar',
     1904                                        'main-video-playlist': 'mainVideoPlaylistToolbar',
     1905                                        'video-playlist-edit': 'videoPlaylistEditToolbar',
     1906                                        'video-playlist-add': 'videoPlaylistAddToolbar'
    18061907                                }
    18071908                        };
    18081909
     
    18521953                        });
    18531954                },
    18541955
     1956                playlistMenu: function( view ) {
     1957                        var lastState = this.lastState(),
     1958                                previous = lastState && lastState.id,
     1959                                frame = this;
     1960
     1961                        view.set({
     1962                                cancel: {
     1963                                        text:     l10n.cancelPlaylistTitle,
     1964                                        priority: 20,
     1965                                        click:    function() {
     1966                                                if ( previous )
     1967                                                        frame.setState( previous );
     1968                                                else
     1969                                                        frame.close();
     1970                                        }
     1971                                },
     1972                                separateCancel: new media.View({
     1973                                        className: 'separator',
     1974                                        priority: 60
     1975                                })
     1976                        });
     1977                },
     1978
     1979                videoPlaylistMenu: function( view ) {
     1980                        var lastState = this.lastState(),
     1981                                previous = lastState && lastState.id,
     1982                                frame = this;
     1983
     1984                        view.set({
     1985                                cancel: {
     1986                                        text:     l10n.cancelVideoPlaylistTitle,
     1987                                        priority: 20,
     1988                                        click:    function() {
     1989                                                if ( previous )
     1990                                                        frame.setState( previous );
     1991                                                else
     1992                                                        frame.close();
     1993                                        }
     1994                                },
     1995                                separateCancel: new media.View({
     1996                                        className: 'separator',
     1997                                        priority: 80
     1998                                })
     1999                        });
     2000                },
     2001
    18552002                // Content
    18562003                embedContent: function() {
    18572004                        var view = new media.view.Embed({
     
    19702117                        });
    19712118                },
    19722119
     2120                mainPlaylistToolbar: function( view ) {
     2121                        var controller = this;
     2122
     2123                        this.selectionStatusToolbar( view );
     2124
     2125                        view.set( 'playlist', {
     2126                                style:    'primary',
     2127                                text:     l10n.createNewPlaylist,
     2128                                priority: 100,
     2129                                requires: { selection: true },
     2130
     2131                                click: function() {
     2132                                        var selection = controller.state().get('selection'),
     2133                                                edit = controller.state('playlist-edit'),
     2134                                                models = selection.where({ type: 'audio' });
     2135
     2136                                        edit.set( 'library', new media.model.Selection( models, {
     2137                                                props:    selection.props.toJSON(),
     2138                                                multiple: true
     2139                                        }) );
     2140
     2141                                        this.controller.setState('playlist-edit');
     2142                                }
     2143                        });
     2144                },
     2145
     2146                mainVideoPlaylistToolbar: function( view ) {
     2147                        var controller = this;
     2148
     2149                        this.selectionStatusToolbar( view );
     2150
     2151                        view.set( 'video-playlist', {
     2152                                style:    'primary',
     2153                                text:     l10n.createNewVideoPlaylist,
     2154                                priority: 100,
     2155                                requires: { selection: true },
     2156
     2157                                click: function() {
     2158                                        var selection = controller.state().get('selection'),
     2159                                                edit = controller.state('video-playlist-edit'),
     2160                                                models = selection.where({ type: 'video' });
     2161
     2162                                        edit.set( 'library', new media.model.Selection( models, {
     2163                                                props:    selection.props.toJSON(),
     2164                                                multiple: true
     2165                                        }) );
     2166
     2167                                        this.controller.setState('video-playlist-edit');
     2168                                }
     2169                        });
     2170                },
     2171
    19732172                featuredImageToolbar: function( toolbar ) {
    19742173                        this.createSelectToolbar( toolbar, {
    19752174                                text:  l10n.setFeaturedImage,
     
    20382237                                        }
    20392238                                }
    20402239                        }) );
     2240                },
     2241
     2242                playlistEditToolbar: function() {
     2243                        var editing = this.state().get('editing');
     2244                        this.toolbar.set( new media.view.Toolbar({
     2245                                controller: this,
     2246                                items: {
     2247                                        insert: {
     2248                                                style:    'primary',
     2249                                                text:     editing ? l10n.updatePlaylist : l10n.insertPlaylist,
     2250                                                priority: 80,
     2251                                                requires: { library: true },
     2252
     2253                                                /**
     2254                                                 * @fires wp.media.controller.State#update
     2255                                                 */
     2256                                                click: function() {
     2257                                                        var controller = this.controller,
     2258                                                                state = controller.state();
     2259
     2260                                                        controller.close();
     2261                                                        state.trigger( 'update', state.get('library') );
     2262
     2263                                                        // Restore and reset the default state.
     2264                                                        controller.setState( controller.options.state );
     2265                                                        controller.reset();
     2266                                                }
     2267                                        }
     2268                                }
     2269                        }) );
     2270                },
     2271
     2272                playlistAddToolbar: function() {
     2273                        this.toolbar.set( new media.view.Toolbar({
     2274                                controller: this,
     2275                                items: {
     2276                                        insert: {
     2277                                                style:    'primary',
     2278                                                text:     l10n.addToPlaylist,
     2279                                                priority: 80,
     2280                                                requires: { selection: true },
     2281
     2282                                                /**
     2283                                                 * @fires wp.media.controller.State#reset
     2284                                                 */
     2285                                                click: function() {
     2286                                                        var controller = this.controller,
     2287                                                                state = controller.state(),
     2288                                                                edit = controller.state('playlist-edit');
     2289
     2290                                                        edit.get('library').add( state.get('selection').models );
     2291                                                        state.trigger('reset');
     2292                                                        controller.setState('playlist-edit');
     2293                                                }
     2294                                        }
     2295                                }
     2296                        }) );
     2297                },
     2298
     2299                videoPlaylistEditToolbar: function() {
     2300                        var editing = this.state().get('editing');
     2301                        this.toolbar.set( new media.view.Toolbar({
     2302                                controller: this,
     2303                                items: {
     2304                                        insert: {
     2305                                                style:    'primary',
     2306                                                text:     editing ? l10n.updateVideoPlaylist : l10n.insertVideoPlaylist,
     2307                                                priority: 140,
     2308                                                requires: { library: true },
     2309
     2310                                                click: function() {
     2311                                                        var controller = this.controller,
     2312                                                                state = controller.state();
     2313
     2314                                                        controller.close();
     2315                                                        state.trigger( 'update', state.get('library') );
     2316
     2317                                                        // Restore and reset the default state.
     2318                                                        controller.setState( controller.options.state );
     2319                                                        controller.reset();
     2320                                                }
     2321                                        }
     2322                                }
     2323                        }) );
     2324                },
     2325
     2326                videoPlaylistAddToolbar: function() {
     2327                        this.toolbar.set( new media.view.Toolbar({
     2328                                controller: this,
     2329                                items: {
     2330                                        insert: {
     2331                                                style:    'primary',
     2332                                                text:     l10n.addToVideoPlaylist,
     2333                                                priority: 140,
     2334                                                requires: { selection: true },
     2335
     2336                                                click: function() {
     2337                                                        var controller = this.controller,
     2338                                                                state = controller.state(),
     2339                                                                edit = controller.state('video-playlist-edit');
     2340
     2341                                                        edit.get('library').add( state.get('selection').models );
     2342                                                        state.trigger('reset');
     2343                                                        controller.setState('video-playlist-edit');
     2344                                                }
     2345                                        }
     2346                                }
     2347                        }) );
    20412348                }
    2042 
    20432349        });
    20442350
    20452351        media.view.MediaFrame.ImageDetails = media.view.MediaFrame.Select.extend({
     
    48645170         * @augments Backbone.View
    48655171         */
    48665172        media.view.Settings.Gallery = media.view.Settings.extend({
    4867                 className: 'gallery-settings',
     5173                className: 'collection-settings gallery-settings',
    48685174                template:  media.template('gallery-settings')
    48695175        });
    48705176
    48715177        /**
     5178         * wp.media.view.Settings.Playlist
     5179         *
     5180         * @constructor
     5181         * @augments wp.media.view.Settings
     5182         * @augments wp.media.View
     5183         * @augments wp.Backbone.View
     5184         * @augments Backbone.View
     5185         */
     5186        media.view.Settings.Playlist = media.view.Settings.extend({
     5187                className: 'collection-settings playlist-settings',
     5188                template:  media.template('playlist-settings')
     5189        });
     5190
     5191        /**
    48725192         * wp.media.view.Attachment.Details
    48735193         *
    48745194         * @constructor
  • src/wp-includes/js/mediaelement/wp-mediaelement.css

     
    1313.me-cannotplay {
    1414        width: auto !important;
    1515}
     16
     17.wp-playlist {
     18        border: 1px solid #ccc;
     19        padding: 10px;
     20        margin: 12px 0 18px;
     21        font-size: 85%;
     22        line-height: 160%;
     23}
     24
     25.wp-playlist audio,
     26.wp-playlist video {
     27        display: inline-block;
     28        max-width: 100%;
     29}
     30
     31.wp-playlist .mejs-container {
     32        margin: 0;
     33        width: 100%;
     34}
     35
     36.wp-playlist .mejs-controls .mejs-button button {
     37        outline: 0;
     38}
     39
     40.wp-playlist-light {
     41        background: #fff;
     42}
     43
     44.wp-playlist-dark {
     45        color: #fff;
     46        background: #000;
     47}
     48
     49.wp-playlist-caption {
     50        max-width: 85%;
     51        overflow: hidden;
     52        text-overflow: ellipsis;
     53        white-space: nowrap;
     54}
     55
     56.wp-caption-meta {
     57        display: block;
     58}
     59
     60.wp-caption-title {
     61        font-size: 100%;
     62}
     63
     64.wp-caption-album {
     65        font-style: italic;
     66        overflow: hidden;
     67        text-overflow: ellipsis;
     68        white-space: nowrap;
     69}
     70
     71.wp-caption-artist {
     72        font-size: 85%;
     73        text-transform: uppercase;
     74}
     75
     76.wp-caption-by {
     77        font-size: 65%;
     78        font-weight: bold;
     79}
     80
     81.wp-playlist-item-length {
     82        position: absolute;
     83        right: 0;
     84        top: 0;
     85}
     86
     87.wp-playlist-tracks {
     88        margin-top: 10px;
     89        border-top: 1px solid #ccc;
     90}
     91
     92.wp-playlist-item {
     93        position: relative;
     94        cursor: pointer;
     95        border-bottom: 1px solid #ccc;
     96}
     97
     98.wp-playlist-current-item {
     99        overflow: hidden;
     100        margin-bottom: 10px;
     101        height: 60px;
     102}
     103
     104.wp-playlist-current-item img {
     105        float: left;
     106        max-width: 60px;
     107        height: auto;
     108        margin-right: 10px;
     109}
     110
     111.wp-playlist-current-item .wp-caption-title,
     112.wp-playlist-current-item .wp-caption-artist {
     113        overflow: hidden;
     114        text-overflow: ellipsis;
     115        white-space: nowrap;
     116}
     117 No newline at end of file
  • src/wp-includes/js/mediaelement/wp-playlist.js

     
     1/*globals window, document, $, jQuery */
     2
     3(function ($, _, Backbone) {
     4        "use strict";
     5
     6        var WPPlaylistView = Backbone.View.extend({
     7                index : 0,
     8
     9                itemTemplate : wp.template('wp-playlist-item'),
     10
     11                initialize : function () {
     12                        var settings = {};
     13
     14                        this.data = $.parseJSON( this.$('script').html() );
     15                        this.playerNode = this.$( this.data.type );
     16
     17                        this.tracks = new Backbone.Collection( this.data.tracks );
     18                        this.current = this.tracks.first();
     19
     20                        if ( 'audio' === this.data.type ) {
     21                                this.currentTemplate = wp.template('wp-playlist-current-item');
     22                                this.currentNode = this.$( '.wp-playlist-current-item' );
     23                        }
     24
     25                        this.renderCurrent();
     26
     27                        if ( this.data.tracklist ) {
     28                                this.renderTracks();
     29                        }
     30
     31                        this.playerNode.attr( 'src', this.current.get('src') );
     32
     33                        _.bindAll( this, 'bindPlayer', 'ended', 'clickTrack' );
     34
     35                        if ( typeof _wpmejsSettings !== 'undefined' ) {
     36                                settings.pluginPath = _wpmejsSettings.pluginPath;
     37                        }
     38                        settings.success = this.bindPlayer;
     39
     40                        new MediaElementPlayer( this.playerNode.get(0), settings );
     41                },
     42
     43                renderCurrent : function () {
     44                        var dimensions;
     45                        if ( 'video' === this.data.type ) {
     46                                if ( this.data.images && this.current.get( 'image' ) ) {
     47                                        this.playerNode.attr( 'poster', this.current.get( 'image' ).src );
     48                                }
     49                                dimensions = this.current.get( 'dimensions' ).resized;
     50                                this.playerNode.attr( 'width', dimensions.width );
     51                                this.playerNode.attr( 'height', dimensions.height );
     52                        } else {
     53                                if ( ! this.data.images ) {
     54                                        this.current.set( 'image', false );
     55                                }
     56                                this.currentNode.html( this.currentTemplate( this.current.toJSON() ) );
     57                        }
     58                },
     59
     60                renderTracks : function () {
     61                        var that = this, i = 1, tracklist = $( '<div class="wp-playlist-tracks"></div>' );
     62                        this.tracks.each(function (model) {
     63                                if ( ! that.data.images ) {
     64                                        model.set( 'image', false );
     65                                }
     66                                model.set( 'artists', that.data.artists );
     67                                model.set( 'index', that.data.tracknumbers ? i : false );
     68                                tracklist.append( that.itemTemplate( model.toJSON() ) );
     69                                i += 1;
     70                        });
     71                        this.$el.append( tracklist );
     72                },
     73
     74                events : {
     75                        'click .wp-playlist-item' : 'clickTrack',
     76                        'click .wp-playlist-next' : 'next',
     77                        'click .wp-playlist-prev' : 'prev'
     78                },
     79
     80                bindPlayer : function (mejs) {
     81                        this.player = mejs;
     82                        this.player.addEventListener( 'ended', this.ended );
     83                },
     84
     85                clickTrack : function (e) {
     86                        this.index = this.$( '.wp-playlist-item' ).index( e.currentTarget );
     87                        this.setCurrent();
     88                },
     89
     90                ended : function () {
     91                        if ( this.index + 1 < this.tracks.length ) {
     92                                this.next();
     93                        } else {
     94                                this.index = 0;
     95                                this.current = this.tracks.at( this.index );
     96                                this.loadCurrent();
     97                        }
     98                },
     99
     100                next : function () {
     101                        this.index = this.index + 1 >= this.tracks.length ? 0 : this.index + 1;
     102                        this.setCurrent();
     103                },
     104
     105                prev : function () {
     106                        this.index = this.index - 1 < 0 ? this.tracks.length - 1 : this.index - 1;
     107                        this.setCurrent();
     108                },
     109
     110                loadCurrent : function () {
     111                        this.player.pause();
     112                        this.playerNode.attr( 'src', this.current.get( 'src' ) );
     113                        this.renderCurrent();
     114                        this.player.load();
     115                },
     116
     117                setCurrent : function () {
     118                        this.current = this.tracks.at( this.index );
     119                        this.loadCurrent();
     120                        this.player.play();
     121                }
     122        });
     123
     124    $(document).ready(function () {
     125                $('.wp-playlist').each(function () {
     126                        return new WPPlaylistView({ el: this });
     127                });
     128    });
     129
     130}(jQuery, _, Backbone));
     131 No newline at end of file
  • src/wp-includes/js/plupload/handlers.js

     
    2222                .appendTo( jQuery('#media-items' ) );
    2323
    2424        // Disable submit
    25         jQuery('#insert-gallery').prop('disabled', true);
     25        jQuery('#insert-gallery, #insert-playlist').prop('disabled', true);
    2626}
    2727
    2828function uploadStart() {
     
    6464        // Just one file, no need for collapsible part
    6565        if ( items.length == 1 ) {
    6666                items.addClass('open').find('.slidetoggle').show();
    67                 jQuery('.insert-gallery').hide();
     67                jQuery('.insert-gallery, .insert-playlist').hide();
    6868        } else if ( items.length > 1 ) {
    6969                items.removeClass('open');
    70                 // Only show Gallery button when there are at least two files.
    71                 jQuery('.insert-gallery').show();
     70                // Only show Gallery/Playlist buttons when there are at least two files.
     71                jQuery('.insert-gallery, .insert-playlist').show();
    7272        }
    7373
    7474        // Only show Save buttons when there is at least one file.
     
    257257}
    258258
    259259function uploadComplete() {
    260         jQuery('#insert-gallery').prop('disabled', false);
     260        jQuery('#insert-gallery, #insert-playlist').prop('disabled', false);
    261261}
    262262
    263263function switchUploader(s) {
  • src/wp-includes/js/swfupload/handlers.js

     
    212212        else
    213213                jQuery('.savebutton').hide();
    214214
    215         // Only show Gallery button when there are at least two files.
    216         if ( items.length > 1 )
    217                 jQuery('.insert-gallery').show();
    218         else
    219                 jQuery('.insert-gallery').hide();
     215        // Only show Gallery/Playlist buttons when there are at least two files.
     216        if ( items.length > 1 ) {
     217                jQuery('.insert-gallery, .insert-playlist').show();
     218        } else {
     219                jQuery('.insert-gallery, .insert-playlist').hide();
     220        }
    220221}
    221222
    222223function uploadSuccess(fileObj, serverData) {
     
    238239        // If no more uploads queued, enable the submit button
    239240        if ( swfu.getStats().files_queued == 0 ) {
    240241                jQuery('#cancel-upload').prop('disabled', true);
    241                 jQuery('#insert-gallery').prop('disabled', false);
     242                jQuery('#insert-gallery, #insert-playlist').prop('disabled', false);
    242243        }
    243244}
    244245
  • src/wp-includes/js/tinymce/langs/wp-langs-en.js

     
    478478                add_audio: "Add Audio",
    479479                editgallery: "Edit Gallery",
    480480                delgallery: "Delete Gallery",
     481                editplaylist: "Edit Playlist",
     482                delplaylist: "Delete Playlist",
    481483                wp_fullscreen_desc: "Distraction Free Writing mode (Alt + Shift + W)"
    482484        });
    483485
  • src/wp-includes/js/tinymce/plugins/wpgallery/plugin.js

     
    2525        }
    2626
    2727        function replaceAVShortcodes( content ) {
    28                 var testRegex = /\[(audio|video)[^\]]*\]/,
    29                         replaceRegex = /\[(audio|video)[^\]]*\]([\s\S]*?\[\/\1\])?/;
     28                var testRegex = /\[(video-playlist|audio|video|playlist)[^\]]*\]/,
     29                        replaceRegex = /\[(video-playlist|audio|video|playlist)[^\]]*\]([\s\S]*?\[\/\1\])?/;
    3030
    3131                while ( testRegex.test( content ) ) {
    3232                        content = content.replace( replaceRegex, replaceCallback );
     
    6060                }
    6161
    6262                // Check if the `wp.media.gallery` API exists.
    63                 if ( typeof wp === 'undefined' || ! wp.media || ! wp.media.gallery ) {
     63                if ( typeof wp === 'undefined' || ! wp.media ) {
    6464                        return;
    6565                }
    6666
    6767                // Make sure we've selected a gallery node.
    68                 if ( editor.dom.hasClass( node, 'wp-gallery' ) ) {
     68                if ( editor.dom.hasClass( node, 'wp-gallery' ) && wp.media.gallery ) {
    6969                        gallery = wp.media.gallery;
    7070                        data = window.decodeURIComponent( editor.dom.getAttrib( node, 'data-wp-media' ) );
    7171                        frame = gallery.edit( data );
     
    7474                                var shortcode = gallery.shortcode( selection ).string();
    7575                                editor.dom.setAttrib( node, 'data-wp-media', window.encodeURIComponent( shortcode ) );
    7676                        });
     77                } else if ( editor.dom.hasClass( node, 'wp-playlist' ) && wp.media.playlist ) {
     78                        data = window.decodeURIComponent( editor.dom.getAttrib( node, 'data-wp-media' ) );
     79                        frame = wp.media.playlist.edit( data );
     80
     81                        frame.state('playlist-edit').on( 'update', function( selection ) {
     82                                var shortcode = wp.media.playlist.shortcode( selection ).string();
     83                                editor.dom.setAttrib( node, 'data-wp-media', window.encodeURIComponent( shortcode ) );
     84                        });
     85                } else if ( editor.dom.hasClass( node, 'wp-video-playlist' ) && wp.media['video-playlist'] ) {
     86                        data = window.decodeURIComponent( editor.dom.getAttrib( node, 'data-wp-media' ) );
     87                        frame = wp.media['video-playlist'].edit( data );
     88
     89                        frame.state('video-playlist-edit').on( 'update', function( selection ) {
     90                                var shortcode = wp.media['video-playlist'].shortcode( selection ).string();
     91                                editor.dom.setAttrib( node, 'data-wp-media', window.encodeURIComponent( shortcode ) );
     92                        });
    7793                } else {
    7894                        // temp
    7995                        window.console && window.console.log( 'Edit AV shortcode ' + window.decodeURIComponent( editor.dom.getAttrib( node, 'data-wp-media' ) ) );
     
    138154                                event.name = 'video';
    139155                        } else if ( dom.hasClass( node, 'wp-audio' ) ) {
    140156                                event.name = 'audio';
     157                        } else if ( dom.hasClass( node, 'wp-playlist' ) ) {
     158                                event.name = 'playlist';
     159                        } else if ( dom.hasClass( node, 'wp-video-playlist' ) ) {
     160                                event.name = 'video-playlist';
    141161                        }
    142162                }
    143163        });
  • src/wp-includes/js/tinymce/skins/wordpress/images/playlist-audio.png

    Cannot display: file marked as a binary type.
    svn:mime-type = application/octet-stream
  • src/wp-includes/js/tinymce/skins/wordpress/images/playlist-video.png

    Property changes on: src/wp-includes/js/tinymce/skins/wordpress/images/playlist-audio.png
    ___________________________________________________________________
    Added: svn:mime-type
    ## -0,0 +1 ##
    +application/octet-stream
    \ No newline at end of property
    Cannot display: file marked as a binary type.
    svn:mime-type = application/octet-stream
  • src/wp-includes/js/tinymce/skins/wordpress/wp-content.css

    Property changes on: src/wp-includes/js/tinymce/skins/wordpress/images/playlist-video.png
    ___________________________________________________________________
    Added: svn:mime-type
    ## -0,0 +1 ##
    +application/octet-stream
    \ No newline at end of property
     
    143143        background-image: url("images/audio.png");
    144144}
    145145
     146.mce-content-body img.wp-media.wp-playlist {
     147        background-image: url("images/playlist-audio.png");
     148}
     149
     150.mce-content-body img.wp-media.wp-video-playlist {
     151        background-image: url("images/playlist-video.png");
     152}
     153
    146154#wp-image-toolbar {
    147155        position: absolute;
    148156}
  • src/wp-includes/media-template.php

     
    411411                </label>
    412412        </script>
    413413
     414        <script type="text/html" id="tmpl-playlist-settings">
     415                <h3><?php _e('Playlist Settings'); ?></h3>
     416
     417                <label class="setting">
     418                        <span><?php _e( 'Random Order' ); ?></span>
     419                        <input type="checkbox" data-setting="_orderbyRandom" />
     420                </label>
     421
     422                <label class="setting">
     423                        <span><?php _e('Style'); ?></span>
     424                        <select class="style" data-setting="style">
     425                                <option value="light">
     426                                        <?php esc_attr_e('Light'); ?>
     427                                </option>
     428                                <option value="dark">
     429                                        <?php esc_attr_e('Dark'); ?>
     430                                </option>
     431                        </select>
     432                </label>
     433
     434                <label class="setting">
     435                        <span><?php _e( 'Show Tracklist' ); ?></span>
     436                        <input type="checkbox" data-setting="_tracklist" />
     437                </label>
     438
     439                <label class="setting">
     440                        <span><?php _e( 'Show Track Numbers' ); ?></span>
     441                        <input type="checkbox" data-setting="_tracknumbers" />
     442                </label>
     443
     444                <label class="setting">
     445                        <span><?php _e( 'Show Artist Name in Tracklist' ); ?></span>
     446                        <input type="checkbox" data-setting="_artists" />
     447                </label>
     448
     449                <label class="setting">
     450                        <span><?php _e( 'Show Images' ); ?></span>
     451                        <input type="checkbox" data-setting="_images" />
     452                </label>
     453        </script>
     454
    414455        <script type="text/html" id="tmpl-embed-link-settings">
    415456                <label class="setting">
    416457                        <span><?php _e('Title'); ?></span>
  • src/wp-includes/media.php

     
    934934}
    935935
    936936/**
     937 * The Playlist shortcode.
     938 *
     939 * This implements the functionality of the Playlist Shortcode for displaying
     940 * a collection of WordPress audio or video files in a post.
     941 *
     942 * @since 3.9.0
     943 *
     944 * @param array $attr Attributes of the shortcode.
     945 * @return string $type Type of playlist. Defaults to audio, video is also supported
     946 */
     947function wp_get_playlist( $attr, $type ) {
     948        global $content_width;
     949        $post = get_post();
     950
     951        if ( ! in_array( $type, array( 'audio', 'video' ) ) ) {
     952                return '';
     953        }
     954
     955        static $instance = 0;
     956        $instance++;
     957
     958        if ( ! empty( $attr['ids'] ) ) {
     959                // 'ids' is explicitly ordered, unless you specify otherwise.
     960                if ( empty( $attr['orderby'] ) ) {
     961                        $attr['orderby'] = 'post__in';
     962                }
     963                $attr['include'] = $attr['ids'];
     964        }
     965
     966        // Allow plugins/themes to override the default gallery template.
     967        $output = apply_filters( 'post_playlist', '', $attr, $type );
     968        if ( $output != '' ) {
     969                return $output;
     970        }
     971
     972        // We're trusting author input, so let's at least make sure it looks like a valid orderby statement
     973        if ( isset( $attr['orderby'] ) ) {
     974                $attr['orderby'] = sanitize_sql_orderby( $attr['orderby'] );
     975                if ( ! $attr['orderby'] )
     976                        unset( $attr['orderby'] );
     977        }
     978
     979        extract( shortcode_atts( array(
     980                'order'         => 'ASC',
     981                'orderby'       => 'menu_order ID',
     982                'id'            => $post ? $post->ID : 0,
     983                'include'       => '',
     984                'exclude'   => '',
     985                'style'         => 'light',
     986                'tracklist' => 'audio' === $type,
     987                'tracknumbers' => 'audio' === $type,
     988                'images'        => true,
     989                'artists'       => true
     990        ), $attr, 'playlist' ) );
     991
     992        $id = intval( $id );
     993        if ( 'RAND' == $order ) {
     994                $orderby = 'none';
     995        }
     996
     997        $args = array(
     998                'post_status' => 'inherit',
     999                'post_type' => 'attachment',
     1000                'post_mime_type' => $type,
     1001                'order' => $order,
     1002                'orderby' => $orderby
     1003        );
     1004
     1005        if ( ! empty( $include ) ) {
     1006                $args['include'] = $include;
     1007                $_attachments = get_posts( $args );
     1008
     1009                $attachments = array();
     1010                foreach ( $_attachments as $key => $val ) {
     1011                        $attachments[$val->ID] = $_attachments[$key];
     1012                }
     1013        } elseif ( ! empty( $exclude ) ) {
     1014                $args['post_parent'] = $id;
     1015                $args['exclude'] = $exclude;
     1016                $attachments = get_children( $args );
     1017        } else {
     1018                $args['post_parent'] = $id;
     1019                $attachments = get_children( $args );
     1020        }
     1021
     1022        if ( empty( $attachments ) ) {
     1023                return '';
     1024        }
     1025
     1026        if ( is_feed() ) {
     1027                $output = "\n";
     1028                foreach ( $attachments as $att_id => $attachment ) {
     1029                        $output .= wp_get_attachment_link( $att_id ) . "\n";
     1030                }
     1031                return $output;
     1032        }
     1033
     1034        $supports_thumbs = ( current_theme_supports( 'post-thumbnails', "attachment:$type" ) && post_type_supports( "attachment:$type", 'thumbnail' ) )
     1035                || $images;
     1036
     1037        $outer = 22; // default padding and border of wrapper
     1038        $theme_width = $content_width - $outer;
     1039        $data = compact( 'type', 'style' );
     1040
     1041        // don't pass strings to JSON, will be truthy in JS
     1042        foreach ( array( 'tracklist', 'tracknumbers', 'images', 'artists' ) as $key ) {
     1043                $data[$key] = filter_var( $$key, FILTER_VALIDATE_BOOLEAN );
     1044        }
     1045
     1046        $tracks = array();
     1047        foreach ( $attachments as $attachment ) {
     1048                $url = wp_get_attachment_url( $attachment->ID );
     1049                $ftype = wp_check_filetype( $url, wp_get_mime_types() );
     1050                $track = array(
     1051                        'type' => $type,
     1052                        'src' => $url,
     1053                        'type' => $ftype['ext'],
     1054                        'title' => get_the_title( $attachment->ID ),
     1055                        'caption' => wptexturize( $attachment->post_excerpt ),
     1056                        'description' => wptexturize( $attachment->post_content )
     1057                );
     1058
     1059                $meta = wp_get_attachment_metadata( $attachment->ID );
     1060                if ( ! empty( $meta ) ) {
     1061                        $track['meta'] = array();
     1062
     1063                        $keys = array( 'title', 'artist', 'band', 'album', 'genre', 'year', 'length', 'length_formatted' );
     1064                        foreach ( $keys as $key ) {
     1065                                if ( ! empty( $meta[ $key ] ) ) {
     1066                                        $track['meta'][ $key ] = $meta[ $key ];
     1067                                }
     1068                        }
     1069
     1070                        if ( 'video' === $type ) {
     1071                                $width = empty( $meta['width'] ) ? 640 : $meta['width'];
     1072                                $height = empty( $meta['height'] ) ? 360 : $meta['height'];
     1073                                $theme_height = round( ( $height * $theme_width ) / $width );
     1074                                $track['dimensions'] = array(
     1075                                        'original' => compact( 'width', 'height' ),
     1076                                        'resized' => array(
     1077                                                'width' => $theme_width,
     1078                                                'height' => $theme_height
     1079                                        )
     1080                                );
     1081                        }
     1082                }
     1083
     1084                if ( $supports_thumbs ) {
     1085                        $id = get_post_thumbnail_id( $attachment->ID );
     1086                        if ( ! empty( $id ) ) {
     1087                                list( $src, $width, $height ) = wp_get_attachment_image_src( $id, 'full' );
     1088                                $track['image'] = compact( 'src', 'width', 'height' );
     1089                                list( $src, $width, $height ) = wp_get_attachment_image_src( $id, 'thumb' );
     1090                                $track['thumb'] = compact( 'src', 'width', 'height' );
     1091                        }
     1092                }
     1093
     1094                $tracks[] = $track;
     1095        }
     1096        $data['tracks'] = $tracks;
     1097
     1098        ob_start();
     1099
     1100        if ( 1 === $instance ):
     1101                wp_enqueue_style( 'wp-mediaelement' );
     1102                wp_enqueue_script( 'wp-playlist' );
     1103?>
     1104<!--[if lt IE 9]><script>document.createElement('<?php echo $type ?>');</script><![endif]-->
     1105<script type="text/html" id="tmpl-wp-playlist-current-item">
     1106        <# if ( data.image ) { #>
     1107        <img src="{{{ data.thumb.src }}}"/>
     1108        <# } #>
     1109        <# if ( data.meta.title ) { #>
     1110        <div class="wp-playlist-caption">
     1111                <span class="wp-caption-meta wp-caption-title">&#8220;{{{ data.meta.title }}}&#8221;</span>
     1112                <span class="wp-caption-meta wp-caption-album">{{{ data.meta.album }}}</span>
     1113                <span class="wp-caption-meta wp-caption-artist">{{{ data.meta.artist }}}</span>
     1114        </div>
     1115        <# } else { #>
     1116        <div class="wp-playlist-caption">{{{ data.caption }}}</div>
     1117        <# } #>
     1118</script>
     1119<script type="text/html" id="tmpl-wp-playlist-item">
     1120        <div class="wp-playlist-item">
     1121                <# if ( ( data.title || data.meta.title ) && ( ! data.artists || data.meta.artist ) ) { #>
     1122                <div class="wp-playlist-caption">
     1123                        {{{ data.index ? ( data.index + '.&nbsp;' ) : '' }}}
     1124                        <span class="wp-caption-title">&#8220;{{{ data.title ? data.title : data.meta.title }}}&#8221;</span>
     1125                        <# if ( data.artists ) { #>
     1126                        <span class="wp-caption-by"><?php _e( 'by' ) ?></span>
     1127                        <span class="wp-caption-artist">{{{ data.meta.artist }}}</span>
     1128                        <# } #>
     1129                </div>
     1130                <# } else { #>
     1131                <div class="wp-playlist-caption">{{{ data.index ? ( data.index + '.' ) : '' }}} {{{ data.caption ? data.caption : data.title }}}</div>
     1132                <# } #>
     1133                <# if ( data.meta.length_formatted ) { #>
     1134                <div class="wp-playlist-item-length">{{{ data.meta.length_formatted }}}</div>
     1135                <# } #>
     1136        </div>
     1137</script>
     1138        <?php endif ?>
     1139<div class="wp-playlist wp-<?php echo $type ?>-playlist wp-playlist-<?php echo $style ?>">
     1140        <?php if ( 'audio' === $type ): ?>
     1141        <div class="wp-playlist-current-item"></div>
     1142        <?php endif ?>
     1143        <<?php echo $type ?> controls="controls" preload="metadata" width="<?php echo $content_width - $outer ?>"></<?php echo $type ?>>
     1144        <div class="wp-playlist-next"></div>
     1145        <div class="wp-playlist-prev"></div>
     1146        <noscript>
     1147        <?php
     1148        $output = "\n";
     1149        foreach ( $attachments as $att_id => $attachment ) {
     1150                $output .= wp_get_attachment_link( $att_id ) . "\n";
     1151        }
     1152
     1153        echo $output;
     1154        ?>
     1155        </noscript>
     1156        <script type="application/json"><?php echo json_encode( $data ) ?></script>
     1157</div>
     1158        <?php
     1159        return ob_get_clean();
     1160}
     1161
     1162function wp_playlist_shortcode( $attr ) {
     1163        return wp_get_playlist( $attr, 'audio' );
     1164}
     1165add_shortcode( 'playlist', 'wp_playlist_shortcode' );
     1166
     1167function wp_video_playlist_shortcode( $attr ) {
     1168        return wp_get_playlist( $attr, 'video' );
     1169}
     1170add_shortcode( 'video-playlist', 'wp_video_playlist_shortcode' );
     1171
     1172/**
    9371173 * Provide a No-JS Flash fallback as a last resort for audio / video
    9381174 *
    9391175 * @since 3.6.0
     
    20442280                'mediaLibraryTitle'  => __( 'Media Library' ),
    20452281                'insertMediaTitle'   => __( 'Insert Media' ),
    20462282                'createNewGallery'   => __( 'Create a new gallery' ),
     2283                'createNewPlaylist'   => __( 'Create a new playlist' ),
     2284                'createNewVideoPlaylist'   => __( 'Create a new video playlist' ),
    20472285                'returnToLibrary'    => __( '&#8592; Return to library' ),
    20482286                'allMediaItems'      => __( 'All media items' ),
    20492287                'noItemsFound'       => __( 'No items found.' ),
     
    20712309                // Edit Image
    20722310                'imageDetailsTitle'     => __( 'Image Details' ),
    20732311                'imageReplaceTitle'     => __( 'Replace Image' ),
    2074                 'imageDetailsCancel'     => __( 'Cancel Edit' )
     2312                'imageDetailsCancel'    => __( 'Cancel Edit' ),
     2313
     2314                // Playlist
     2315                'playlistDragInfo'    => __( 'Drag and drop to reorder tracks.' ),
     2316                'createPlaylistTitle' => __( 'Create Playlist' ),
     2317                'editPlaylistTitle'   => __( 'Edit Playlist' ),
     2318                'cancelPlaylistTitle' => __( '&#8592; Cancel Playlist' ),
     2319                'insertPlaylist'      => __( 'Insert playlist' ),
     2320                'updatePlaylist'      => __( 'Update playlist' ),
     2321                'addToPlaylist'       => __( 'Add to playlist' ),
     2322                'addToPlaylistTitle'  => __( 'Add to Playlist' ),
     2323
     2324                // Video Playlist
     2325                'videoPlaylistDragInfo'    => __( 'Drag and drop to reorder videos.' ),
     2326                'createVideoPlaylistTitle' => __( 'Create Video Playlist' ),
     2327                'editVideoPlaylistTitle'   => __( 'Edit Video Playlist' ),
     2328                'cancelVideoPlaylistTitle' => __( '&#8592; Cancel Video Playlist' ),
     2329                'insertVideoPlaylist'      => __( 'Insert video playlist' ),
     2330                'updateVideoPlaylist'      => __( 'Update video playlist' ),
     2331                'addToVideoPlaylist'       => __( 'Add to video playlist' ),
     2332                'addToVideoPlaylistTitle'  => __( 'Add to Video Playlist' ),
    20752333        );
    20762334
    20772335        $settings = apply_filters( 'media_view_settings', $settings, $post );
  • src/wp-includes/script-loader.php

     
    315315                'pluginPath' => includes_url( 'js/mediaelement/', 'relative' ),
    316316        ) );
    317317
     318        $scripts->add( 'wp-playlist', "/wp-includes/js/mediaelement/wp-playlist.js", array( 'wp-util', 'backbone', 'mediaelement' ), false, 1 );
     319
    318320        $scripts->add( 'zxcvbn-async', "/wp-includes/js/zxcvbn-async$suffix.js", array(), '1.0' );
    319321        did_action( 'init' ) && $scripts->localize( 'zxcvbn-async', '_zxcvbnSettings', array(
    320322                'src' => empty( $guessed_url ) ? includes_url( '/js/zxcvbn.min.js' ) : $scripts->base_url . '/wp-includes/js/zxcvbn.min.js',