WordPress.org

Make WordPress Core

Ticket #26631: 26631.diff

File 26631.diff, 35.9 KB (added by wonderboymusic, 8 years ago)
  • src/wp-admin/js/media-upload.js

     
    3131                } else if ( h.indexOf('[gallery') !== -1 ) {
    3232                        if ( ed.plugins.wpgallery )
    3333                                h = ed.plugins.wpgallery._do_gallery(h);
     34                } else if ( h.indexOf('[playlist') !== -1 ) {
     35                        if ( ed.plugins.wpplaylist )
     36                                h = ed.plugins.wpplaylist._do_playlist(h);
    3437                } else if ( h.indexOf('[embed') === 0 ) {
    3538                        if ( ed.plugins.wordpress )
    3639                                h = ed.plugins.wordpress._setEmbed(h);
  • src/wp-includes/class-wp-editor.php

     
    193193                                self::$baseurl = includes_url('js/tinymce');
    194194                                self::$mce_locale = $mce_locale = ( '' == get_locale() ) ? 'en' : strtolower( substr(get_locale(), 0, 2) ); // only ISO 639-1
    195195                                $no_captions = (bool) apply_filters( 'disable_captions', '' );
    196                                 $plugins = array( 'inlinepopups', 'tabfocus', 'paste', 'media', 'fullscreen', 'wordpress', 'wpeditimage', 'wpgallery', 'wplink', 'wpdialogs' );
     196                                $plugins = array( 'inlinepopups', 'tabfocus', 'paste', 'media', 'fullscreen', 'wordpress', 'wpeditimage', 'wpgallery', 'wpplaylist', 'wplink', 'wpdialogs' );
    197197                                $first_run = true;
    198198                                $ext_plugins = '';
    199199
  • src/wp-includes/css/editor.css

     
    13411341}
    13421342
    13431343#wp_editbtns,
    1344 #wp_gallerybtns {
     1344#wp_gallerybtns,
     1345#wp_playlistbtns {
    13451346        padding: 2px;
    13461347        position: absolute;
    13471348        display: none;
     
    13511352#wp_editimgbtn,
    13521353#wp_delimgbtn,
    13531354#wp_editgallery,
    1354 #wp_delgallery {
     1355#wp_delgallery,
     1356#wp_editplaylist,
     1357#wp_delplaylist {
    13551358        border-color: #999;
    13561359        background-color: #eee;
    13571360        margin: 2px;
     
    13651368#wp_editimgbtn:hover,
    13661369#wp_delimgbtn:hover,
    13671370#wp_editgallery:hover,
    1368 #wp_delgallery:hover {
     1371#wp_delgallery:hover,
     1372#wp_editplaylist:hover,
     1373#wp_delplaylist:hover {
    13691374        border-color: #555;
    13701375        background-color: #ccc;
    13711376}
  • src/wp-includes/css/media-views.css

     
    174174        overflow: auto;
    175175        min-height: 300px;
    176176        background: #fff;
    177         -webkit-font-smoothing: subpixel-antialiased; 
     177        -webkit-font-smoothing: subpixel-antialiased;
    178178}
    179179
    180180.media-modal-icon {
     
    575575        box-shadow: 0 4px 4px -4px rgba( 0, 0, 0, 0.1 );
    576576}
    577577
    578 .media-frame .media-toolbar .add-to-gallery {
     578.media-frame .media-toolbar .add-to-gallery, .media-frame .media-toolbar .add-to-playlist {
    579579        display: none;
    580580}
    581581
     
    13831383        margin: 1.4em 0 0.4em;
    13841384}
    13851385
    1386 .gallery-settings {
     1386.gallery-settings, .playlist-settings {
    13871387        overflow: hidden;
    13881388}
    13891389
     
    16511651        .media-modal-close {
    16521652                right: 10px;
    16531653        }
    1654        
     1654
    16551655        /* Text inputs need to be 16px, or they force zooming on iOS */
    16561656        .media-frame input[type="text"],
    16571657        .media-frame input[type="password"],
     
    16991699        .media-frame-title {
    17001700                display: none;
    17011701        }
    1702        
     1702
    17031703        .media-frame-toolbar {
    17041704                position: absolute;
    17051705                bottom: 0px;
     
    17241724        .attachment-details h3 {
    17251725                margin-top: 45px;
    17261726        }
    1727                
     1727
    17281728        /* Shorten right-side links so they don't overlap the close button */
    17291729        .media-menu a:nth-child(2),
    17301730        .media-menu a:last-child {
     
    17501750                top: 84px;
    17511751                left: 0;
    17521752        }
    1753        
     1753
    17541754        .media-frame-content {
    17551755                left: 0;
    17561756                top: 118px;
     
    17591759        .media-frame .attachments-browser {
    17601760                padding-bottom: 300px;
    17611761        }
    1762        
     1762
    17631763        .media-sidebar {
    17641764                border-bottom: 1px solid #dddddd;
    17651765        }
    1766        
     1766
    17671767        .media-modal {
    17681768                width: auto;
    17691769        }
     
    18321832                border-top: none;
    18331833        }
    18341834
    1835         .gallery-settings h3 {
     1835        .gallery-settings h3, .playlist-settings h3 {
    18361836                margin-top: 45px;
    18371837        }
    18381838
     
    18691869        .media-frame-content {
    18701870                top: 78px;
    18711871        }
    1872        
     1872
    18731873        .attachments-browser .attachments {
    18741874                top: 2px;
    18751875        }
  • src/wp-includes/js/media-editor.js

     
    377377                };
    378378        }());
    379379
     380        wp.media.playlist = (function() {
     381                var playlists = {};
     382
     383                return {
     384                        defaults: {
     385                                order:      'ASC',
     386                                id:         wp.media.view.settings.post.id,
     387                                orderby:    'menu_order ID'
     388                        },
     389
     390                        attachments: function( shortcode ) {
     391                                var shortcodeString = shortcode.string(),
     392                                        result = playlists[ shortcodeString ],
     393                                        attrs, args, query, others;
     394
     395                                delete playlists[ shortcodeString ];
     396
     397                                if ( result )
     398                                        return result;
     399
     400                                // Fill the default shortcode attributes.
     401                                attrs = _.defaults( shortcode.attrs.named, wp.media.playlist.defaults );
     402                                args  = _.pick( attrs, 'orderby', 'order' );
     403
     404                                args.type    = 'audio';
     405                                args.perPage = -1;
     406
     407                                // Mark the `orderby` override attribute.
     408                                if( undefined !== attrs.orderby )
     409                                        attrs._orderByField = attrs.orderby;
     410
     411                                if ( 'rand' === attrs.orderby )
     412                                        attrs._orderbyRandom = true;
     413
     414                                // Map the `orderby` attribute to the corresponding model property.
     415                                if ( ! attrs.orderby || /^menu_order(?: ID)?$/i.test( attrs.orderby ) )
     416                                        args.orderby = 'menuOrder';
     417
     418                                // Map the `ids` param to the correct query args.
     419                                if ( attrs.ids ) {
     420                                        args.post__in = attrs.ids.split(',');
     421                                        args.orderby  = 'post__in';
     422                                } else if ( attrs.include ) {
     423                                        args.post__in = attrs.include.split(',');
     424                                }
     425
     426                                if ( attrs.exclude )
     427                                        args.post__not_in = attrs.exclude.split(',');
     428
     429                                if ( ! args.post__in )
     430                                        args.uploadedTo = attrs.id;
     431
     432                                // Collect the attributes that were not included in `args`.
     433                                others = _.omit( attrs, 'id', 'ids', 'include', 'exclude', 'orderby', 'order' );
     434
     435                                query = wp.media.query( args );
     436                                query.playlist = new Backbone.Model( others );
     437                                return query;
     438                        },
     439
     440                        shortcode: function( attachments ) {
     441                                var props = attachments.props.toJSON(),
     442                                        attrs = _.pick( props, 'orderby', 'order' ),
     443                                        shortcode, clone;
     444
     445                                if ( attachments.playlist )
     446                                        _.extend( attrs, attachments.playlist.toJSON() );
     447
     448                                // Convert all playlist shortcodes to use the `ids` property.
     449                                // Ignore `post__in` and `post__not_in`; the attachments in
     450                                // the collection will already reflect those properties.
     451                                attrs.ids = attachments.pluck('id');
     452
     453                                // Copy the `uploadedTo` post ID.
     454                                if ( props.uploadedTo )
     455                                        attrs.id = props.uploadedTo;
     456
     457                                // Check if the playlist is randomly ordered.
     458                                delete attrs.orderby;
     459
     460                                if ( attrs._orderbyRandom )
     461                                        attrs.orderby = 'rand';
     462                                else if ( attrs._orderByField && attrs._orderByField != 'rand' )
     463                                        attrs.orderby = attrs._orderByField;
     464
     465                                delete attrs._orderbyRandom;
     466                                delete attrs._orderByField;
     467
     468                                // If the `ids` attribute is set and `orderby` attribute
     469                                // is the default value, clear it for cleaner output.
     470                                if ( attrs.ids && 'post__in' === attrs.orderby )
     471                                        delete attrs.orderby;
     472
     473                                // Remove default attributes from the shortcode.
     474                                _.each( wp.media.playlist.defaults, function( value, key ) {
     475                                        if ( value === attrs[ key ] )
     476                                                delete attrs[ key ];
     477                                });
     478
     479                                shortcode = new wp.shortcode({
     480                                        tag:    'playlist',
     481                                        attrs:  attrs,
     482                                        type:   'single'
     483                                });
     484
     485                                // Use a cloned version of the playlist.
     486                                clone = new wp.media.model.Attachments( attachments.models, {
     487                                        props: props
     488                                });
     489                                clone.playlist = attachments.playlist;
     490                                playlists[ shortcode.string() ] = clone;
     491
     492                                return shortcode;
     493                        },
     494
     495                        edit: function( content ) {
     496                                var shortcode = wp.shortcode.next( 'playlist', content ),
     497                                        defaultPostId = wp.media.playlist.defaults.id,
     498                                        attachments, selection;
     499
     500                                // Bail if we didn't match the shortcode or all of the content.
     501                                if ( ! shortcode || shortcode.content !== content )
     502                                        return;
     503
     504                                // Ignore the rest of the match object.
     505                                shortcode = shortcode.shortcode;
     506
     507                                if ( _.isUndefined( shortcode.get('id') ) && ! _.isUndefined( defaultPostId ) )
     508                                        shortcode.set( 'id', defaultPostId );
     509
     510                                attachments = wp.media.playlist.attachments( shortcode );
     511
     512                                selection = new wp.media.model.Selection( attachments.models, {
     513                                        props:    attachments.props.toJSON(),
     514                                        multiple: true
     515                                });
     516
     517                                selection.playlist = attachments.playlist;
     518
     519                                // Fetch the query's attachments, and then break ties from the
     520                                // query to allow for sorting.
     521                                selection.more().done( function() {
     522                                        // Break ties with the query.
     523                                        selection.props.set({ query: false });
     524                                        selection.unmirror();
     525                                        selection.props.unset('orderby');
     526                                });
     527
     528                                // Destroy the previous playlist frame.
     529                                if ( this.frame )
     530                                        this.frame.dispose();
     531
     532                                // Store the current playlist frame.
     533                                this.frame = wp.media({
     534                                        frame:     'post',
     535                                        state:     'playlist-edit',
     536                                        title:     wp.media.view.l10n.editPlaylistTitle,
     537                                        editing:   true,
     538                                        multiple:  true,
     539                                        selection: selection
     540                                }).open();
     541
     542                                return this.frame;
     543                        }
     544                };
     545        }());
     546
    380547        wp.media.featuredImage = {
    381548                get: function() {
    382549                        return wp.media.view.settings.post.featuredImageId;
     
    483650                                } else if ( h.indexOf('[gallery') !== -1 ) {
    484651                                        if ( ed.plugins.wpgallery )
    485652                                                h = ed.plugins.wpgallery._do_gallery(h);
     653                                } else if ( h.indexOf('[playlist') !== -1 ) {
     654                                        if ( ed.plugins.wpplaylist )
     655                                                h = ed.plugins.wpplaylist._do_playlist(h);
    486656                                } else if ( h.indexOf('[embed') === 0 ) {
    487657                                        if ( ed.plugins.wordpress )
    488658                                                h = ed.plugins.wordpress._setEmbed(h);
     
    534704                                this.insert( wp.media.gallery.shortcode( selection ).string() );
    535705                        }, this );
    536706
     707                        workflow.state('playlist-edit').on( 'update', function( selection ) {
     708                                this.insert( wp.media.playlist.shortcode( selection ).string() );
     709                        }, this );
     710
    537711                        workflow.state('embed').on( 'select', function() {
    538712                                var state = workflow.state(),
    539713                                        type = state.get('type'),
     
    707881                                if ( $this.hasClass( 'gallery' ) ) {
    708882                                        options.state = 'gallery';
    709883                                        options.title = wp.media.view.l10n.createGalleryTitle;
     884                                } else if ( $this.hasClass( 'playlist' ) ) {
     885                                        options.state = 'playlist';
     886                                        options.title = wp.media.view.l10n.createPlaylistTitle;
    710887                                }
    711888
    712889                                wp.media.editor.open( editor, options );
  • src/wp-includes/js/media-views.js

     
    688688                }
    689689        });
    690690
     691        // wp.media.controller.GalleryEdit
     692        // -------------------------------
     693        media.controller.PlaylistEdit = media.controller.Library.extend({
     694                defaults: {
     695                        id:         'playlist-edit',
     696                        multiple:   false,
     697                        describe:   true,
     698                        edge:       199,
     699                        editing:    false,
     700                        sortable:   true,
     701                        searchable: false,
     702                        toolbar:    'playlist-edit',
     703                        content:    'browse',
     704                        title:      l10n.editPlaylistTitle,
     705                        priority:   60,
     706                        dragInfo:   true,
     707
     708                        // Don't sync the selection, as the Edit Gallery library
     709                        // *is* the selection.
     710                        syncSelection: false
     711                },
     712
     713                initialize: function() {
     714                        // If we haven't been provided a `library`, create a `Selection`.
     715                        if ( ! this.get('library') )
     716                                this.set( 'library', new media.model.Selection() );
     717
     718                        // The single `Attachment` view to be used in the `Attachments` view.
     719                        if ( ! this.get('AttachmentView') )
     720                                this.set( 'AttachmentView', media.view.Attachment.EditLibrary );
     721                        media.controller.Library.prototype.initialize.apply( this, arguments );
     722                },
     723
     724                activate: function() {
     725                        var library = this.get('library');
     726
     727                        // Limit the library to audio only.
     728                        library.props.set( 'type', 'audio' );
     729
     730                        // Watch for uploaded attachments.
     731                        this.get('library').observe( wp.Uploader.queue );
     732
     733                        this.frame.on( 'content:render:browse', this.playlistSettings, this );
     734
     735                        media.controller.Library.prototype.activate.apply( this, arguments );
     736                },
     737
     738                deactivate: function() {
     739                        // Stop watching for uploaded attachments.
     740                        this.get('library').unobserve( wp.Uploader.queue );
     741
     742                        this.frame.off( 'content:render:browse', this.playlistSettings, this );
     743
     744                        media.controller.Library.prototype.deactivate.apply( this, arguments );
     745                },
     746
     747                playlistSettings: function( browser ) {
     748                        var library = this.get('library');
     749
     750                        if ( ! library || ! browser )
     751                                return;
     752
     753                        library.playlist = library.playlist || new Backbone.Model();
     754
     755                        browser.sidebar.set({
     756                                playlist: new media.view.Settings.Playlist({
     757                                        controller: this,
     758                                        model:      library.playlist,
     759                                        priority:   40
     760                                })
     761                        });
     762
     763                        browser.toolbar.set( 'reverse', {
     764                                text:     l10n.reverseOrder,
     765                                priority: 80,
     766
     767                                click: function() {
     768                                        library.reset( library.toArray().reverse() );
     769                                }
     770                        });
     771                }
     772        });
     773
     774        // wp.media.controller.GalleryAdd
     775        // ---------------------------------
     776        media.controller.PlaylistAdd = media.controller.Library.extend({
     777                defaults: _.defaults({
     778                        id:           'playlist-library',
     779                        filterable:   'uploaded',
     780                        multiple:     'add',
     781                        menu:         'playlist',
     782                        toolbar:      'playlist-add',
     783                        title:        l10n.addToPlaylistTitle,
     784                        priority:     100,
     785
     786                        // Don't sync the selection, as the Edit Gallery library
     787                        // *is* the selection.
     788                        syncSelection: false
     789                }, media.controller.Library.prototype.defaults ),
     790
     791                initialize: function() {
     792                        // If we haven't been provided a `library`, create a `Selection`.
     793                        if ( ! this.get('library') )
     794                                this.set( 'library', media.query({ type: 'audio' }) );
     795
     796                        media.controller.Library.prototype.initialize.apply( this, arguments );
     797                },
     798
     799                activate: function() {
     800                        var library = this.get('library'),
     801                                edit    = this.frame.state('playlist-edit').get('library');
     802
     803                        if ( this.editLibrary && this.editLibrary !== edit )
     804                                library.unobserve( this.editLibrary );
     805
     806                        // Accepts attachments that exist in the original library and
     807                        // that do not exist in gallery's library.
     808                        library.validator = function( attachment ) {
     809                                return !! this.mirroring.get( attachment.cid ) && ! edit.get( attachment.cid ) && media.model.Selection.prototype.validator.apply( this, arguments );
     810                        };
     811
     812                        // Reset the library to ensure that all attachments are re-added
     813                        // to the collection. Do so silently, as calling `observe` will
     814                        // trigger the `reset` event.
     815                        library.reset( library.mirroring.models, { silent: true });
     816                        library.observe( edit );
     817                        this.editLibrary = edit;
     818
     819                        media.controller.Library.prototype.activate.apply( this, arguments );
     820                }
     821        });
     822
    691823        // wp.media.controller.FeaturedImage
    692824        // ---------------------------------
    693825        media.controller.FeaturedImage = media.controller.Library.extend({
     
    13081440                                        menu:    'gallery'
    13091441                                }),
    13101442
    1311                                 new media.controller.GalleryAdd()
     1443                                new media.controller.GalleryAdd(),
     1444
     1445                                new media.controller.Library({
     1446                                        id:         'playlist',
     1447                                        title:      l10n.createPlaylistTitle,
     1448                                        priority:   40,
     1449                                        toolbar:    'main-playlist',
     1450                                        filterable: 'uploaded',
     1451                                        multiple:   'add',
     1452                                        editable:   false,
     1453
     1454                                        library:  media.query( _.defaults({
     1455                                                type: 'audio'
     1456                                        }, options.library ) )
     1457                                }),
     1458
     1459                                // Gallery states.
     1460                                new media.controller.PlaylistEdit({
     1461                                        library: options.selection,
     1462                                        editing: options.editing,
     1463                                        menu:    'playlist'
     1464                                }),
     1465
     1466                                new media.controller.PlaylistAdd()
    13121467                        ]);
    13131468
    13141469
     
    13201475                bindHandlers: function() {
    13211476                        media.view.MediaFrame.Select.prototype.bindHandlers.apply( this, arguments );
    13221477                        this.on( 'menu:create:gallery', this.createMenu, this );
     1478                        this.on( 'menu:create:playlist', this.createMenu, this );
    13231479                        this.on( 'toolbar:create:main-insert', this.createToolbar, this );
    13241480                        this.on( 'toolbar:create:main-gallery', this.createToolbar, this );
     1481                        this.on( 'toolbar:create:main-playlist', this.createToolbar, this );
    13251482                        this.on( 'toolbar:create:featured-image', this.featuredImageToolbar, this );
    13261483                        this.on( 'toolbar:create:main-embed', this.mainEmbedToolbar, this );
    13271484
    13281485                        var handlers = {
    13291486                                        menu: {
    13301487                                                'default': 'mainMenu',
    1331                                                 'gallery': 'galleryMenu'
     1488                                                'gallery': 'galleryMenu',
     1489                                                'playlist': 'playlistMenu'
    13321490                                        },
    13331491
    13341492                                        content: {
     
    13401498                                                'main-insert':      'mainInsertToolbar',
    13411499                                                'main-gallery':     'mainGalleryToolbar',
    13421500                                                'gallery-edit':     'galleryEditToolbar',
    1343                                                 'gallery-add':      'galleryAddToolbar'
     1501                                                'gallery-add':      'galleryAddToolbar',
     1502                                                'main-playlist':    'mainPlaylistToolbar',
     1503                                                'playlist-edit':    'playlistEditToolbar',
     1504                                                'playlist-add':     'playlistAddToolbar'
    13441505                                        }
    13451506                                };
    13461507
     
    13841545                        });
    13851546                },
    13861547
     1548                playlistMenu: function( view ) {
     1549                        var lastState = this.lastState(),
     1550                                previous = lastState && lastState.id,
     1551                                frame = this;
     1552
     1553                        view.set({
     1554                                cancel: {
     1555                                        text:     l10n.cancelPlaylistTitle,
     1556                                        priority: 20,
     1557                                        click:    function() {
     1558                                                if ( previous )
     1559                                                        frame.setState( previous );
     1560                                                else
     1561                                                        frame.close();
     1562                                        }
     1563                                },
     1564                                separateCancel: new media.View({
     1565                                        className: 'separator',
     1566                                        priority: 40
     1567                                })
     1568                        });
     1569                },
     1570
    13871571                // Content
    13881572                embedContent: function() {
    13891573                        var view = new media.view.Embed({
     
    14891673                        });
    14901674                },
    14911675
     1676                mainPlaylistToolbar: function( view ) {
     1677                        var controller = this;
     1678
     1679                        this.selectionStatusToolbar( view );
     1680
     1681                        view.set( 'playlist', {
     1682                                style:    'primary',
     1683                                text:     l10n.createNewPlaylist,
     1684                                priority: 60,
     1685                                requires: { selection: true },
     1686
     1687                                click: function() {
     1688                                        var selection = controller.state().get('selection'),
     1689                                                edit = controller.state('playlist-edit'),
     1690                                                models = selection.where({ type: 'audio' });
     1691
     1692                                        edit.set( 'library', new media.model.Selection( models, {
     1693                                                props:    selection.props.toJSON(),
     1694                                                multiple: true
     1695                                        }) );
     1696
     1697                                        this.controller.setState('playlist-edit');
     1698                                }
     1699                        });
     1700                },
     1701
    14921702                featuredImageToolbar: function( toolbar ) {
    14931703                        this.createSelectToolbar( toolbar, {
    14941704                                text:  l10n.setFeaturedImage,
     
    15511761                                        }
    15521762                                }
    15531763                        }) );
     1764                },
     1765
     1766                playlistEditToolbar: function() {
     1767                        var editing = this.state().get('editing');
     1768                        this.toolbar.set( new media.view.Toolbar({
     1769                                controller: this,
     1770                                items: {
     1771                                        insert: {
     1772                                                style:    'primary',
     1773                                                text:     editing ? l10n.updatePlaylist : l10n.insertPlaylist,
     1774                                                priority: 80,
     1775                                                requires: { library: true },
     1776
     1777                                                click: function() {
     1778                                                        var controller = this.controller,
     1779                                                                state = controller.state();
     1780
     1781                                                        controller.close();
     1782                                                        state.trigger( 'update', state.get('library') );
     1783
     1784                                                        // Restore and reset the default state.
     1785                                                        controller.setState( controller.options.state );
     1786                                                        controller.reset();
     1787                                                }
     1788                                        }
     1789                                }
     1790                        }) );
     1791                },
     1792
     1793                playlistAddToolbar: function() {
     1794                        this.toolbar.set( new media.view.Toolbar({
     1795                                controller: this,
     1796                                items: {
     1797                                        insert: {
     1798                                                style:    'primary',
     1799                                                text:     l10n.addToPlaylist,
     1800                                                priority: 80,
     1801                                                requires: { selection: true },
     1802
     1803                                                click: function() {
     1804                                                        var controller = this.controller,
     1805                                                                state = controller.state(),
     1806                                                                edit = controller.state('playlist-edit');
     1807
     1808                                                        edit.get('library').add( state.get('selection').models );
     1809                                                        state.trigger('reset');
     1810                                                        controller.setState('playlist-edit');
     1811                                                }
     1812                                        }
     1813                                }
     1814                        }) );
    15541815                }
    15551816        });
    15561817
     
    37133974        });
    37143975
    37153976        /**
     3977         * wp.media.view.Settings.Gallery
     3978         */
     3979        media.view.Settings.Playlist = media.view.Settings.extend({
     3980                className: 'playlist-settings',
     3981                template:  media.template('playlist-settings')
     3982        });
     3983
     3984        /**
    37163985         * wp.media.view.Attachment.Details
    37173986         */
    37183987        media.view.Attachment.Details = media.view.Attachment.extend({
  • 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() {
     
    4747
    4848        if ( max > hundredmb && file.size > hundredmb ) {
    4949                setTimeout(function(){
    50                        
     50
    5151                        if ( file.status < 3 && file.loaded === 0 ) { // not uploading
    5252                                wpFileError(file, pluploadL10n.big_upload_failed.replace('%1$s', '<a class="uploader-html" href="#">').replace('%2$s', '</a>'));
    5353                                up.stop(); // stops the whole queue
     
    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.
     
    171171                        success: function( ){
    172172                                var type,
    173173                                        item = jQuery('#media-item-' + fileObj.id);
    174                                
     174
    175175                                if ( type = jQuery('#type-of-' + fileObj.id).val() )
    176176                                        jQuery('#' + type + '-counter').text(jQuery('#' + type + '-counter').text()-0+1);
    177177
     
    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

     
    2525        jQuery('.progress', '#media-item-' + fileObj.id).show();
    2626
    2727        // Disable submit and enable cancel
    28         jQuery('#insert-gallery').prop('disabled', true);
     28        jQuery('#insert-gallery, #insert-playlist').prop('disabled', true);
    2929        jQuery('#cancel-upload').prop('disabled', false);
    3030}
    3131
    3232function uploadStart(fileObj) {
    3333        try {
    3434                if ( typeof topWin.tb_remove != 'undefined' )
    35                         topWin.jQuery('#TB_overlay').unbind('click', topWin.tb_remove); 
     35                        topWin.jQuery('#TB_overlay').unbind('click', topWin.tb_remove);
    3636        } catch(e){}
    3737
    3838        return true;
     
    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

     
    195195sug:"Suggestions",
    196196no_sug:"No suggestions",
    197197no_mpell:"No misspellings found.",
    198 learn_word:"Learn word" 
     198learn_word:"Learn word"
    199199},
    200200pagebreak:{
    201201desc:"Insert Page Break"
     
    464464add_audio:"Add Audio",
    465465editgallery:"Edit Gallery",
    466466delgallery:"Delete Gallery",
     467editplaylist:"Edit Playlist",
     468delplaylist:"Delete Playlist",
    467469wp_fullscreen_desc:"Distraction Free Writing mode (Alt + Shift + W)"
    468470});
    469471
  • src/wp-includes/js/tinymce/langs/wp-langs.php

     
    510510                'add_audio' => __('Add Audio'),
    511511                'editgallery' => __('Edit Gallery'),
    512512                'delgallery' => __('Delete Gallery'),
     513                'editplaylist' => __('Edit Playlist'),
     514                'delplaylist' => __('Delete Playlist'),
    513515                'wp_fullscreen_desc' => __('Distraction Free Writing mode (Alt + Shift + W)')
    514516        );
    515517
  • src/wp-includes/js/tinymce/plugins/wordpress/editor_plugin_src.js

     
    380380
    381381                _hideButtons : function() {
    382382                        var DOM = tinymce.DOM;
    383                         DOM.hide( DOM.select('#wp_editbtns, #wp_gallerybtns') );
     383                        DOM.hide( DOM.select('#wp_editbtns, #wp_gallerybtns, #wp_playlistbtns') );
    384384                },
    385385
    386386                // Resizes the iframe by a relative height value
  • src/wp-includes/js/tinymce/plugins/wpeditimage/editor_plugin_src.js

     
    264264                                ed.plugins.wordpress._hideButtons();
    265265                        });
    266266                },
    267                
     267
    268268                _editImage : function() {
    269269                        var ed = tinymce.activeEditor, url = this.url, el = ed.selection.getNode(), vp, H, W, cls = el.className;
    270270
  • src/wp-includes/js/tinymce/plugins/wpplaylist/editor_plugin_src.js

     
     1/* global tinymce */
     2(function() {
     3        tinymce.create('tinymce.plugins.wpPlaylist', {
     4
     5                init : function(ed, url) {
     6                        var t = this;
     7
     8                        t.url = url;
     9                        t.editor = ed;
     10                        t._createButtons();
     11
     12                        // Register the command so that it can be invoked by using tinyMCE.activeEditor.execCommand('...');
     13                        ed.addCommand('WP_Playlist', function() {
     14                                if ( tinymce.isIE )
     15                                        ed.selection.moveToBookmark( ed.wpPlaylistBookmark );
     16
     17                                var el = ed.selection.getNode(),
     18                                        playlist = wp.media.playlist,
     19                                        frame;
     20
     21                                // Check if the `wp.media.playlist` API exists.
     22                                if ( typeof wp === 'undefined' || ! wp.media || ! wp.media.playlist )
     23                                        return;
     24
     25                                // Make sure we've selected a playlist node.
     26                                if ( el.nodeName != 'IMG' || ed.dom.getAttrib(el, 'class').indexOf('wp-playlist') == -1 )
     27                                        return;
     28
     29                                frame = playlist.edit( '[' + ed.dom.getAttrib( el, 'title' ) + ']' );
     30
     31                                frame.state('playlist-edit').on( 'update', function( selection ) {
     32                                        var shortcode = playlist.shortcode( selection ).string().slice( 1, -1 );
     33                                        ed.dom.setAttrib( el, 'title', shortcode );
     34                                });
     35                        });
     36
     37                        ed.onInit.add(function(ed) {
     38                                // iOS6 doesn't show the buttons properly on click, show them on 'touchstart'
     39                                if ( 'ontouchstart' in window ) {
     40                                        ed.dom.events.add(ed.getBody(), 'touchstart', function(e){
     41                                                var target = e.target;
     42
     43                                                if ( target.nodeName == 'IMG' && ed.dom.hasClass(target, 'wp-playlist') ) {
     44                                                        ed.selection.select(target);
     45                                                        ed.dom.events.cancel(e);
     46                                                        ed.plugins.wordpress._hideButtons();
     47                                                        ed.plugins.wordpress._showButtons(target, 'wp_playlistbtns');
     48                                                }
     49                                        });
     50                                }
     51                        });
     52
     53                        ed.onMouseDown.add(function(ed, e) {
     54                                if ( e.target.nodeName == 'IMG' && ed.dom.hasClass(e.target, 'wp-playlist') ) {
     55                                        ed.plugins.wordpress._hideButtons();
     56                                        ed.plugins.wordpress._showButtons(e.target, 'wp_playlistbtns');
     57                                }
     58                        });
     59
     60                        ed.onBeforeSetContent.add(function(ed, o) {
     61                                o.content = t._do_playlist(o.content);
     62                        });
     63
     64                        ed.onPostProcess.add(function(ed, o) {
     65                                if (o.get)
     66                                        o.content = t._get_playlist(o.content);
     67                        });
     68                },
     69
     70                _do_playlist : function(co) {
     71                        return co.replace(/\[playlist([^\]]*)\]/g, function(a,b){
     72                                return '<img src="'+tinymce.baseURL+'/plugins/wpgallery/img/t.gif" class="wp-playlist mceItem" title="playlist'+tinymce.DOM.encode(b)+'" />';
     73                        });
     74                },
     75
     76                _get_playlist : function(co) {
     77
     78                        function getAttr(s, n) {
     79                                n = new RegExp(n + '=\"([^\"]+)\"', 'g').exec(s);
     80                                return n ? tinymce.DOM.decode(n[1]) : '';
     81                        }
     82
     83                        return co.replace(/(?:<p[^>]*>)*(<img[^>]+>)(?:<\/p>)*/g, function(a,im) {
     84                                var cls = getAttr(im, 'class');
     85
     86                                if ( cls.indexOf('wp-playlist') != -1 )
     87                                        return '<p>['+tinymce.trim(getAttr(im, 'title'))+']</p>';
     88
     89                                return a;
     90                        });
     91                },
     92
     93                _createButtons : function() {
     94                        var t = this, ed = tinymce.activeEditor, DOM = tinymce.DOM, editButton, dellButton, isRetina;
     95
     96                        // t.url hack
     97                        t.url = tinymce.baseURL + '/plugins/wpgallery';
     98
     99                        if ( DOM.get('wp_playlistbtns') )
     100                                return;
     101
     102                        isRetina = ( window.devicePixelRatio && window.devicePixelRatio > 1 ) || // WebKit, Opera
     103                                ( window.matchMedia && window.matchMedia('(min-resolution:130dpi)').matches ); // Firefox, IE10, Opera
     104
     105                        DOM.add(document.body, 'div', {
     106                                id : 'wp_playlistbtns',
     107                                style : 'display:none;'
     108                        });
     109
     110                        editButton = DOM.add('wp_playlistbtns', 'img', {
     111                                src : isRetina ? t.url+'/img/edit-2x.png' : t.url+'/img/edit.png',
     112                                id : 'wp_editplaylist',
     113                                width : '24',
     114                                height : '24',
     115                                title : ed.getLang('wordpress.editplaylist')
     116                        });
     117
     118                        tinymce.dom.Event.add( editButton, 'mousedown', function() {
     119                                var ed = tinymce.activeEditor;
     120                                ed.wpPlaylistBookmark = ed.selection.getBookmark('simple');
     121                                ed.execCommand('WP_Playlist');
     122                                ed.plugins.wordpress._hideButtons();
     123                        });
     124
     125                        dellButton = DOM.add('wp_playlistbtns', 'img', {
     126                                src : isRetina ? t.url+'/img/delete-2x.png' : t.url+'/img/delete.png',
     127                                id : 'wp_delplaylist',
     128                                width : '24',
     129                                height : '24',
     130                                title : ed.getLang('wordpress.delplaylist')
     131                        });
     132
     133                        tinymce.dom.Event.add(dellButton, 'mousedown', function(e) {
     134                                var ed = tinymce.activeEditor, el = ed.selection.getNode();
     135
     136                                if ( el.nodeName == 'IMG' && ed.dom.hasClass(el, 'wp-playlist') ) {
     137                                        ed.dom.remove(el);
     138
     139                                        ed.execCommand('mceRepaint');
     140                                        ed.dom.events.cancel(e);
     141                                }
     142
     143                                ed.plugins.wordpress._hideButtons();
     144                        });
     145                },
     146
     147                getInfo : function() {
     148                        return {
     149                                longname : 'Playlist Settings',
     150                                author : 'WordPress',
     151                                authorurl : 'http://wordpress.org',
     152                                infourl : '',
     153                                version : '1.0'
     154                        };
     155                }
     156        });
     157
     158        tinymce.PluginManager.add('wpplaylist', tinymce.plugins.wpPlaylist);
     159})();
  • src/wp-includes/js/tinymce/themes/advanced/skins/wp_theme/content.css

     
    133133        height: 250px;
    134134}
    135135
     136img.wp-playlist {
     137        border: 1px dashed #888;
     138        background: #f00;
     139        background-size: 40px 40px;
     140        width: 100%;
     141        height: 250px;
     142}
     143
    136144img.wp-oembed {
    137145        border: 1px dashed #888;
    138146        background: #f7f5f2 url("img/embedded.png") no-repeat scroll center center;
     
    154162                background-image: url("img/mce-nextpage-2x.png");
    155163        }
    156164
    157         img.wp-gallery {
     165        img.wp-gallery, img.wp-playlist {
    158166                background-image: url("img/gallery-2x.png");
    159167        }
    160168}
  • 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        </script>
     422
    414423        <script type="text/html" id="tmpl-embed-link-settings">
    415424                <label class="setting">
    416425                        <span><?php _e('Title'); ?></span>
  • src/wp-includes/media.php

     
    846846}
    847847
    848848/**
     849 * The Playlist shortcode.
     850 *
     851 * This implements the functionality of the Playlist Shortcode for displaying
     852 * WordPress audio files on a post.
     853 *
     854 * @since 3.9.0
     855 *
     856 * @param array $attr Attributes of the shortcode.
     857 * @return string HTML content to display gallery.
     858 */
     859function wp_playlist_shortcode( $attr ) {
     860        $post = get_post();
     861
     862        static $instance = 0;
     863        $instance++;
     864
     865        if ( ! empty( $attr['ids'] ) ) {
     866                // 'ids' is explicitly ordered, unless you specify otherwise.
     867                if ( empty( $attr['orderby'] ) )
     868                        $attr['orderby'] = 'post__in';
     869                $attr['include'] = $attr['ids'];
     870        }
     871
     872        // Allow plugins/themes to override the default gallery template.
     873        $output = apply_filters( 'post_playlist', '', $attr );
     874        if ( $output != '' )
     875                return $output;
     876
     877        // We're trusting author input, so let's at least make sure it looks like a valid orderby statement
     878        if ( isset( $attr['orderby'] ) ) {
     879                $attr['orderby'] = sanitize_sql_orderby( $attr['orderby'] );
     880                if ( ! $attr['orderby'] )
     881                        unset( $attr['orderby'] );
     882        }
     883
     884        extract( shortcode_atts( array(
     885                'order'      => 'ASC',
     886                'orderby'    => 'menu_order ID',
     887                'id'         => $post ? $post->ID : 0,
     888                'include'    => '',
     889                'exclude'    => '',
     890        ), $attr, 'playlist' ) );
     891
     892        $id = intval( $id );
     893        if ( 'RAND' == $order )
     894                $orderby = 'none';
     895
     896        if ( ! empty( $include ) ) {
     897                $_attachments = get_posts( array( 'include' => $include, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'audio', 'order' => $order, 'orderby' => $orderby ) );
     898
     899                $attachments = array();
     900                foreach ( $_attachments as $key => $val ) {
     901                        $attachments[$val->ID] = $_attachments[$key];
     902                }
     903        } elseif ( ! empty( $exclude ) ) {
     904                $attachments = get_children( array('post_parent' => $id, 'exclude' => $exclude, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'audio', 'order' => $order, 'orderby' => $orderby ) );
     905        } else {
     906                $attachments = get_children( array('post_parent' => $id, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'audio', 'order' => $order, 'orderby' => $orderby) );
     907        }
     908
     909        if ( empty( $attachments ) )
     910                return '';
     911
     912        if ( is_feed() ) {
     913                $output = "\n";
     914                foreach ( $attachments as $att_id => $attachment )
     915                        $output .= wp_get_attachment_link( $att_id, $size, true ) . "\n";
     916
     917                return $output;
     918        }
     919
     920        $output = 'THISISMYPLAYLIST';
     921
     922        return $output;
     923}
     924
     925add_shortcode( 'playlist', 'wp_playlist_shortcode' );
     926
     927/**
    849928 * Provide a No-JS Flash fallback as a last resort for audio / video
    850929 *
    851930 * @since 3.6.0
     
    19031982                'mediaLibraryTitle'  => __( 'Media Library' ),
    19041983                'insertMediaTitle'   => __( 'Insert Media' ),
    19051984                'createNewGallery'   => __( 'Create a new gallery' ),
     1985                'createNewPlaylist'   => __( 'Create a new playlist' ),
    19061986                'returnToLibrary'    => __( '&#8592; Return to library' ),
    19071987                'allMediaItems'      => __( 'All media items' ),
    19081988                'noItemsFound'       => __( 'No items found.' ),
     
    19262006                'addToGallery'       => __( 'Add to gallery' ),
    19272007                'addToGalleryTitle'  => __( 'Add to Gallery' ),
    19282008                'reverseOrder'       => __( 'Reverse order' ),
     2009
     2010                // Playlist
     2011                'createPlaylistTitle' => __( 'Create Playlist' ),
     2012                'editPlaylistTitle'   => __( 'Edit Playlist' ),
     2013                'cancelPlaylistTitle' => __( '&#8592; Cancel Playlist' ),
     2014                'insertPlaylist'      => __( 'Insert playlist' ),
     2015                'updatePlaylist'      => __( 'Update playlist' ),
     2016                'addToPlaylist'       => __( 'Add to playlist' ),
     2017                'addToPlaylistTitle'  => __( 'Add to Playlist' ),
    19292018        );
    19302019
    19312020        $settings = apply_filters( 'media_view_settings', $settings, $post );