Ticket #26631: 26631.5.diff
| File 26631.5.diff, 53.3 KB (added by , 13 years ago) |
|---|
-
src/wp-content/themes/twentyfourteen/functions.php
111 111 'max_posts' => 6, 112 112 ) ); 113 113 114 add_post_type_support( 'attachment:audio', 'thumbnail' ); 115 add_post_type_support( 'attachment:video', 'thumbnail' ); 116 add_theme_support( 'post-thumbnails', array( 'post', 'attachment:audio', 'attachment:video' ) ); 117 114 118 // This theme uses its own gallery styles. 115 119 add_filter( 'use_default_gallery_style', '__return_false' ); 116 120 } -
src/wp-includes/class-wp-editor.php
232 232 'wordpress', 233 233 'wpeditimage', 234 234 'wpgallery', 235 'wpplaylist', 235 236 'wplink', 236 237 'wpdialogs', 237 238 ) ) ); -
src/wp-includes/css/editor.css
472 472 } 473 473 474 474 #wp_editbtns, 475 #wp_gallerybtns { 475 #wp_gallerybtns, 476 #wp_playlistbtns { 476 477 padding: 2px; 477 478 position: absolute; 478 479 display: none; … … 482 483 #wp_editimgbtn, 483 484 #wp_delimgbtn, 484 485 #wp_editgallery, 485 #wp_delgallery { 486 #wp_delgallery, 487 #wp_editplaylist, 488 #wp_delplaylist { 486 489 border-color: #999; 487 490 background-color: #eee; 488 491 margin: 2px; … … 496 499 #wp_editimgbtn:hover, 497 500 #wp_delimgbtn:hover, 498 501 #wp_editgallery:hover, 499 #wp_delgallery:hover { 502 #wp_delgallery:hover, 503 #wp_editplaylist:hover, 504 #wp_delplaylist:hover { 500 505 border-color: #555; 501 506 background-color: #ccc; 502 507 } -
src/wp-includes/css/media-views.css
589 589 box-shadow: 0 4px 4px -4px rgba( 0, 0, 0, 0.1 ); 590 590 } 591 591 592 .media-frame .media-toolbar .add-to-gallery {592 .media-frame .media-toolbar .add-to-gallery, .media-frame .media-toolbar .add-to-playlist { 593 593 display: none; 594 594 } 595 595 … … 1410 1410 margin: 1.4em 0 0.4em; 1411 1411 } 1412 1412 1413 .gallery-settings {1413 .gallery-settings, .playlist-settings { 1414 1414 overflow: hidden; 1415 1415 } 1416 1416 … … 1686 1686 .media-modal-close { 1687 1687 right: 10px; 1688 1688 } 1689 1689 1690 1690 /* Text inputs need to be 16px, or they force zooming on iOS */ 1691 1691 .media-frame input[type="text"], 1692 1692 .media-frame input[type="password"], … … 1734 1734 .media-frame-title { 1735 1735 display: none; 1736 1736 } 1737 1737 1738 1738 .media-frame-toolbar { 1739 1739 position: absolute; 1740 1740 bottom: 0px; … … 1759 1759 .attachment-details h3 { 1760 1760 margin-top: 45px; 1761 1761 } 1762 1762 1763 1763 /* Shorten right-side links so they don't overlap the close button */ 1764 1764 .media-menu a:nth-child(2), 1765 1765 .media-menu a:last-child { … … 1785 1785 top: 84px; 1786 1786 left: 0; 1787 1787 } 1788 1788 1789 1789 .media-frame-content { 1790 1790 left: 0; 1791 1791 top: 118px; … … 1794 1794 .media-frame .attachments-browser { 1795 1795 padding-bottom: 300px; 1796 1796 } 1797 1797 1798 1798 .media-sidebar { 1799 1799 border-bottom: 1px solid #dddddd; 1800 1800 } 1801 1801 1802 1802 .media-modal { 1803 1803 width: auto; 1804 1804 } … … 1867 1867 border-top: none; 1868 1868 } 1869 1869 1870 .gallery-settings h3 {1870 .gallery-settings h3, .playlist-settings h3 { 1871 1871 margin-top: 45px; 1872 1872 } 1873 1873 … … 1904 1904 .media-frame-content { 1905 1905 top: 78px; 1906 1906 } 1907 1907 1908 1908 .attachments-browser .attachments { 1909 1909 top: 2px; 1910 1910 } -
src/wp-includes/js/media-editor.js
8 8 * 9 9 * @static 10 10 */ 11 var workflows = {} ;11 var workflows = {}, cache = {}; 12 12 13 13 /** 14 14 * wp.media.string … … 273 273 return html; 274 274 } 275 275 }; 276 277 276 /** 278 * wp.media. gallery277 * wp.media.collection 279 278 * @namespace 280 279 */ 281 wp.media.gallery = (function() { 282 /** 283 * 284 * @static 285 * @type object 286 */ 287 var galleries = {}; 280 wp.media.collection = { 281 attachments : function ( prop, type ) { 282 return function( shortcode ) { 283 var shortcodeString = shortcode.string(), 284 result = cache[ shortcodeString ], 285 attrs, args, query, others; 288 286 289 return { 290 /** 291 * Default gallery properties 292 * 293 * @global wp.media.view.settings 294 * @readonly 295 */ 296 defaults: { 297 order: 'ASC', 298 id: wp.media.view.settings.post.id, 299 itemtag: 'dl', 300 icontag: 'dt', 301 captiontag: 'dd', 302 columns: '3', 303 link: 'post', 304 size: 'thumbnail', 305 orderby: 'menu_order ID' 306 }, 307 /** 308 * Retrieve attachments based on the properties of the passed shortcode 309 * 310 * @global wp.media.query 311 * 312 * @param {wp.shortcode} shortcode An instance of wp.shortcode(). 313 * @returns {wp.media.model.Attachments} A Backbone.Collection containing 314 * the images belonging to a gallery. The 'gallery' prop is a Backbone.Model 315 * containing the 'props' for the gallery. 316 */ 317 attachments: function( shortcode ) { 318 var shortcodeString = shortcode.string(), 319 result = galleries[ shortcodeString ], 320 attrs, args, query, others; 287 delete cache[ shortcodeString ]; 321 288 322 delete galleries[ shortcodeString ]; 323 324 if ( result ) { 325 return result; 289 if ( result ) { 290 return result; 326 291 } 327 292 328 // Fill the default shortcode attributes.329 attrs = _.defaults( shortcode.attrs.named, wp.media.gallery.defaults );330 args = _.pick( attrs, 'orderby', 'order' );293 // Fill the default shortcode attributes. 294 attrs = _.defaults( shortcode.attrs.named, this.defaults ); 295 args = _.pick( attrs, 'orderby', 'order' ); 331 296 332 args.type = 'image';333 args.perPage = -1;297 args.type = type; 298 args.perPage = -1; 334 299 335 // Mark the `orderby` override attribute.336 if( undefined !== attrs.orderby ) {337 attrs._orderByField = attrs.orderby;300 // Mark the `orderby` override attribute. 301 if ( undefined !== attrs.orderby ) { 302 attrs._orderByField = attrs.orderby; 338 303 } 304 339 305 if ( 'rand' === attrs.orderby ) { 340 306 attrs._orderbyRandom = true; 341 307 } … … 365 331 others = _.omit( attrs, 'id', 'ids', 'include', 'exclude', 'orderby', 'order' ); 366 332 367 333 query = wp.media.query( args ); 368 query .gallery= new Backbone.Model( others );334 query[ prop ] = new Backbone.Model( others ); 369 335 return query; 370 }, 371 /** 372 * Triggered when clicking 'Insert Gallery' or 'Update Gallery' 373 * 374 * @global wp.shortcode 375 * @global wp.media.model.Attachments 376 * 377 * @param {wp.media.model.Attachments} attachments A Backbone.Collection containing 378 * the images belonging to a gallery. The 'gallery' prop is a Backbone.Model 379 * containing the 'props' for the gallery. 380 * @returns {wp.shortcode} 381 */ 382 shortcode: function( attachments ) { 383 var props = attachments.props.toJSON(), 384 attrs = _.pick( props, 'orderby', 'order' ), 385 shortcode, clone; 336 }; 337 }, 386 338 387 if ( attachments.gallery) {388 _.extend( attrs, attachments.gallery.toJSON() ); 389 } 339 shortcodeAttrs : function ( prop, attachments ) { 340 var props = attachments.props.toJSON(), 341 attrs = _.pick( props, 'orderby', 'order', 'style' ); 390 342 391 // Convert all gallery shortcodes to use the `ids` property. 392 // Ignore `post__in` and `post__not_in`; the attachments in 393 // the collection will already reflect those properties. 394 attrs.ids = attachments.pluck('id'); 343 if ( attachments[ prop ] ) { 344 _.extend( attrs, attachments[ prop ].toJSON() ); 345 } 395 346 396 // Copy the `uploadedTo` post ID.397 if ( props.uploadedTo ) { 398 attrs.id = props.uploadedTo; 399 } 347 // Convert all collection shortcodes to use the `ids` property. 348 // Ignore `post__in` and `post__not_in`; the attachments in 349 // the collection will already reflect those properties. 350 attrs.ids = attachments.pluck('id'); 400 351 401 // Check if the gallery is randomly ordered. 402 delete attrs.orderby; 352 // Copy the `uploadedTo` post ID. 353 if ( props.uploadedTo ) { 354 attrs.id = props.uploadedTo; 355 } 403 356 404 if ( attrs._orderbyRandom ) { 405 attrs.orderby = 'rand'; 406 } else if ( attrs._orderByField && attrs._orderByField != 'rand' ) { 407 attrs.orderby = attrs._orderByField; 408 } 357 // Check if the collection is randomly ordered. 358 delete attrs.orderby; 409 359 410 delete attrs._orderbyRandom; 411 delete attrs._orderByField; 360 if ( attrs._orderbyRandom ) { 361 attrs.orderby = 'rand'; 362 } else if ( attrs._orderByField && attrs._orderByField != 'rand' ) { 363 attrs.orderby = attrs._orderByField; 364 } 412 365 413 // If the `ids` attribute is set and `orderby` attribute 414 // is the default value, clear it for cleaner output. 415 if ( attrs.ids && 'post__in' === attrs.orderby ) { 416 delete attrs.orderby; 417 } 366 delete attrs._orderbyRandom; 367 delete attrs._orderByField; 418 368 419 // Remove default attributes from the shortcode. 420 _.each( wp.media.gallery.defaults, function( value, key ) { 421 if ( value === attrs[ key ] ) 422 delete attrs[ key ];423 });369 // If the `ids` attribute is set and `orderby` attribute 370 // is the default value, clear it for cleaner output. 371 if ( attrs.ids && 'post__in' === attrs.orderby ) { 372 delete attrs.orderby; 373 } 424 374 425 shortcode = new wp.shortcode({ 426 tag: 'gallery', 427 attrs: attrs, 428 type: 'single' 429 }); 375 // Remove default attributes from the shortcode. 376 _.each( this.defaults, function( value, key ) { 377 if ( value === attrs[ key ] ) { 378 delete attrs[ key ]; 379 } 380 }); 430 381 431 // Use a cloned version of the gallery. 432 clone = new wp.media.model.Attachments( attachments.models, { 433 props: props 434 }); 435 clone.gallery = attachments.gallery; 436 galleries[ shortcode.string() ] = clone; 382 return attrs; 383 }, 437 384 438 return shortcode; 439 }, 440 /** 441 * Triggered when double-clicking a Gallery shortcode placeholder 442 * in the editor 443 * 444 * @global wp.shortcode 445 * @global wp.media.model.Selection 446 * @global wp.media.view.l10n 447 * 448 * @param {string} content Content that is searched for possible 449 * shortcode markup matching the passed tag name, 450 * 451 * @this wp.media.gallery 452 * 453 * @returns {wp.media.view.MediaFrame.Select} A media workflow. 454 */ 455 edit: function( content ) { 456 var shortcode = wp.shortcode.next( 'gallery', content ), 457 defaultPostId = wp.media.gallery.defaults.id, 458 attachments, selection; 385 editSelection : function ( prop, shortcode ) { 386 var defaultPostId = wp.media[ prop ].defaults.id, 387 attachments, selection; 459 388 460 // Bail if we didn't match the shortcode or all of the content. 461 if ( ! shortcode || shortcode.content !== content ) { 462 return; 463 } 389 // Ignore the rest of the match object. 390 shortcode = shortcode.shortcode; 464 391 465 // Ignore the rest of the match object. 466 shortcode = shortcode.shortcode; 392 if ( _.isUndefined( shortcode.get('id') ) && ! _.isUndefined( defaultPostId ) ) { 393 shortcode.set( 'id', defaultPostId ); 394 } 467 395 468 if ( _.isUndefined( shortcode.get('id') ) && ! _.isUndefined( defaultPostId ) ) { 469 shortcode.set( 'id', defaultPostId ); 470 } 396 attachments = wp.media[ prop ].attachments( shortcode ); 471 397 472 attachments = wp.media.gallery.attachments( shortcode ); 398 selection = new wp.media.model.Selection( attachments.models, { 399 props: attachments.props.toJSON(), 400 multiple: true 401 }); 473 402 474 selection = new wp.media.model.Selection( attachments.models, { 475 props: attachments.props.toJSON(), 476 multiple: true 477 }); 403 selection[ prop ] = attachments[ prop ]; 478 404 479 selection.gallery = attachments.gallery; 405 // Fetch the query's attachments, and then break ties from the 406 // query to allow for sorting. 407 selection.more().done( function() { 408 // Break ties with the query. 409 selection.props.set({ query: false }); 410 selection.unmirror(); 411 selection.props.unset('orderby'); 412 }); 480 413 481 // Fetch the query's attachments, and then break ties from the 482 // query to allow for sorting. 483 selection.more().done( function() { 484 // Break ties with the query. 485 selection.props.set({ query: false }); 486 selection.unmirror(); 487 selection.props.unset('orderby'); 488 }); 414 return selection; 415 }, 489 416 490 // Destroy the previous gallery frame. 491 if ( this.frame ) { 492 this.frame.dispose(); 493 } 417 cacheShortcode : function ( prop, attachments, shortcode ) { 418 // Use a cloned version of the playlist. 419 var clone = new wp.media.model.Attachments( attachments.models, { 420 props: attachments.props.toJSON() 421 }); 422 clone[ prop ] = attachments[ prop ]; 423 cache[ shortcode.string() ] = clone; 494 424 495 // Store the current gallery frame. 496 this.frame = wp.media({ 497 frame: 'post', 498 state: 'gallery-edit', 499 title: wp.media.view.l10n.editGalleryTitle, 500 editing: true, 501 multiple: true, 502 selection: selection 503 }).open(); 425 return shortcode; 426 }, 504 427 505 return this.frame; 428 getEditFrame : function ( args ) { 429 // Destroy the previous gallery frame. 430 if ( this.frame ) { 431 this.frame.dispose(); 506 432 } 507 };508 }());509 433 434 // Store the current gallery frame. 435 this.frame = wp.media( _.extend( { 436 frame: 'post', 437 editing: true, 438 multiple: true, 439 }, args ) ).open(); 440 441 return this.frame; 442 }, 443 444 instance : function ( prop, args ) { 445 return { 446 attachments: this.attachments( prop, args.type ), 447 shortcode: function( attachments ) { 448 var shortcode = new wp.shortcode({ 449 tag: prop, 450 attrs: wp.media.collection.shortcodeAttrs( prop, attachments ), 451 type: 'single' 452 }); 453 454 return wp.media.collection.cacheShortcode( prop, attachments, shortcode ); 455 }, 456 edit: function( content ) { 457 var shortcode = wp.shortcode.next( prop, content ); 458 459 // Bail if we didn't match the shortcode or all of the content. 460 if ( ! shortcode || shortcode.content !== content ) { 461 return; 462 } 463 464 return wp.media.collection.getEditFrame( { 465 title: args.title, 466 state: prop + '-edit', 467 selection: wp.media.collection.editSelection( prop, shortcode ) 468 } ); 469 } 470 }; 471 } 472 }; 473 474 wp.media.gallery = (function() { 475 var gallery = { 476 defaults : { 477 itemtag: 'dl', 478 icontag: 'dt', 479 captiontag: 'dd', 480 columns: '3', 481 link: 'post', 482 size: 'thumbnail', 483 order: 'ASC', 484 id: wp.media.view.settings.post.id, 485 orderby : 'menu_order ID' 486 } 487 }; 488 489 return _.extend(gallery, wp.media.collection.instance( 'gallery', { 490 type : 'image', 491 title : wp.media.view.l10n.editGalleryTitle 492 })); 493 }()); 494 495 wp.media.playlist = (function() { 496 var playlist = { 497 defaults : { 498 id: wp.media.view.settings.post.id, 499 style: 'light', 500 tracklist: true, 501 tracknumbers: true 502 } 503 }; 504 505 return _.extend(playlist, wp.media.collection.instance( 'playlist', { 506 type : 'audio', 507 title : wp.media.view.l10n.editPlaylistTitle 508 })); 509 }()); 510 511 wp.media['video-playlist'] = (function() { 512 var playlist = { 513 defaults : { 514 id: wp.media.view.settings.post.id, 515 style: 'dark', 516 tracklist: false, 517 tracknumbers: false 518 } 519 }; 520 521 return _.extend(playlist, wp.media.collection.instance( 'video-playlist', { 522 type : 'video', 523 title : wp.media.view.l10n.editVideoPlaylistTitle 524 })); 525 }()); 526 510 527 /** 511 528 * wp.media.featuredImage 512 529 * @namespace … … 725 742 this.insert( wp.media.gallery.shortcode( selection ).string() ); 726 743 }, this ); 727 744 745 workflow.state('playlist-edit').on( 'update', function( selection ) { 746 this.insert( wp.media.playlist.shortcode( selection ).string() ); 747 }, this ); 748 749 workflow.state('video-playlist-edit').on( 'update', function( selection ) { 750 this.insert( wp.media['video-playlist'].shortcode( selection ).string() ); 751 }, this ); 752 728 753 workflow.state('embed').on( 'select', function() { 729 754 /** 730 755 * @this wp.media.editor … … 964 989 if ( elem.hasClass( 'gallery' ) ) { 965 990 options.state = 'gallery'; 966 991 options.title = wp.media.view.l10n.createGalleryTitle; 992 } else if ( elem.hasClass( 'playlist' ) ) { 993 options.state = 'playlist'; 994 options.title = wp.media.view.l10n.createPlaylistTitle; 995 } else if ( elem.hasClass( 'video-playlist' ) ) { 996 options.state = 'video-playlist'; 997 options.title = wp.media.view.l10n.createVideoPlaylistTitle; 967 998 } 968 999 969 1000 wp.media.editor.open( editor, options ); -
src/wp-includes/js/media-views.js
460 460 return; 461 461 } 462 462 463 console.log( this ); 464 463 465 view.set( this.id, menuItem ); 464 466 } 465 467 }); … … 752 754 }); 753 755 754 756 /** 755 * wp.media.controller.GalleryEdit756 *757 * @constructor758 * @augments wp.media.controller.Library759 * @augments wp.media.controller.State760 * @augments Backbone.Model761 */762 media.controller.GalleryEdit = media.controller.Library.extend({763 defaults: {764 id: 'gallery-edit',765 multiple: false,766 describe: true,767 edge: 199,768 editing: false,769 sortable: true,770 searchable: false,771 toolbar: 'gallery-edit',772 content: 'browse',773 title: l10n.editGalleryTitle,774 priority: 60,775 dragInfo: true,776 777 // Don't sync the selection, as the Edit Gallery library778 // *is* the selection.779 syncSelection: false780 },781 782 initialize: function() {783 // If we haven't been provided a `library`, create a `Selection`.784 if ( ! this.get('library') ) {785 this.set( 'library', new media.model.Selection() );786 }787 788 // The single `Attachment` view to be used in the `Attachments` view.789 if ( ! this.get('AttachmentView') ) {790 this.set( 'AttachmentView', media.view.Attachment.EditLibrary );791 }792 /**793 * call 'initialize' directly on the parent class794 */795 media.controller.Library.prototype.initialize.apply( this, arguments );796 },797 798 activate: function() {799 var library = this.get('library');800 801 // Limit the library to images only.802 library.props.set( 'type', 'image' );803 804 // Watch for uploaded attachments.805 this.get('library').observe( wp.Uploader.queue );806 807 this.frame.on( 'content:render:browse', this.gallerySettings, this );808 /**809 * call 'activate' directly on the parent class810 */811 media.controller.Library.prototype.activate.apply( this, arguments );812 },813 814 deactivate: function() {815 // Stop watching for uploaded attachments.816 this.get('library').unobserve( wp.Uploader.queue );817 818 this.frame.off( 'content:render:browse', this.gallerySettings, this );819 /**820 * call 'deactivate' directly on the parent class821 */822 media.controller.Library.prototype.deactivate.apply( this, arguments );823 },824 825 /**826 * @param {Object} browser827 */828 gallerySettings: function( browser ) {829 var library = this.get('library');830 831 if ( ! library || ! browser ) {832 return;833 }834 835 library.gallery = library.gallery || new Backbone.Model();836 837 browser.sidebar.set({838 gallery: new media.view.Settings.Gallery({839 controller: this,840 model: library.gallery,841 priority: 40842 })843 });844 845 browser.toolbar.set( 'reverse', {846 text: l10n.reverseOrder,847 priority: 80,848 849 click: function() {850 library.reset( library.toArray().reverse() );851 }852 });853 }854 });855 856 /**857 * wp.media.controller.GalleryAdd858 *859 * @constructor860 * @augments wp.media.controller.Library861 * @augments wp.media.controller.State862 * @augments Backbone.Model863 */864 media.controller.GalleryAdd = media.controller.Library.extend({865 defaults: _.defaults({866 id: 'gallery-library',867 filterable: 'uploaded',868 multiple: 'add',869 menu: 'gallery',870 toolbar: 'gallery-add',871 title: l10n.addToGalleryTitle,872 priority: 100,873 874 // Don't sync the selection, as the Edit Gallery library875 // *is* the selection.876 syncSelection: false877 }, media.controller.Library.prototype.defaults ),878 879 /**880 * If we haven't been provided a `library`, create a `Selection`.881 */882 initialize: function() {883 if ( ! this.get('library') ) {884 this.set( 'library', media.query({ type: 'image' }) );885 }886 /**887 * call 'initialize' directly on the parent class888 */889 media.controller.Library.prototype.initialize.apply( this, arguments );890 },891 892 activate: function() {893 var library = this.get('library'),894 edit = this.frame.state('gallery-edit').get('library');895 896 if ( this.editLibrary && this.editLibrary !== edit )897 library.unobserve( this.editLibrary );898 899 // Accepts attachments that exist in the original library and900 // that do not exist in gallery's library.901 library.validator = function( attachment ) {902 return !! this.mirroring.get( attachment.cid )903 && ! edit.get( attachment.cid )904 /**905 * call 'validator' directly on wp.media.model.Selection906 */907 && media.model.Selection.prototype.validator.apply( this, arguments );908 };909 910 // Reset the library to ensure that all attachments are re-added911 // to the collection. Do so silently, as calling `observe` will912 // trigger the `reset` event.913 library.reset( library.mirroring.models, { silent: true });914 library.observe( edit );915 this.editLibrary = edit;916 /**917 * call 'activate' directly on the parent class918 */919 media.controller.Library.prototype.activate.apply( this, arguments );920 }921 });922 923 /**924 757 * wp.media.controller.FeaturedImage 925 758 * 926 759 * @constructor … … 1005 838 } 1006 839 }); 1007 840 841 media.controller.CollectionEdit = function ( prop, args ) { 842 return media.controller.Library.extend({ 843 defaults : _.defaults(args.defaults || {}, { 844 id: prop + '-edit', 845 toolbar: prop + '-edit', 846 multiple: false, 847 describe: true, 848 edge: 199, 849 editing: false, 850 sortable: true, 851 searchable: false, 852 content: 'browse', 853 priority: 60, 854 dragInfo: true, 855 856 // Don't sync the selection, as the Edit {Collection} library 857 // *is* the selection. 858 syncSelection: false 859 }), 860 861 initialize: function() { 862 // If we haven't been provided a `library`, create a `Selection`. 863 if ( ! this.get('library') ) { 864 this.set( 'library', new media.model.Selection() ); 865 } 866 // The single `Attachment` view to be used in the `Attachments` view. 867 if ( ! this.get('AttachmentView') ) { 868 this.set( 'AttachmentView', media.view.Attachment.EditLibrary ); 869 } 870 media.controller.Library.prototype.initialize.apply( this, arguments ); 871 }, 872 873 activate: function() { 874 var library = this.get('library'); 875 876 // Limit the library to images only. 877 library.props.set( 'type', args.type ); 878 879 // Watch for uploaded attachments. 880 this.get('library').observe( wp.Uploader.queue ); 881 882 this.frame.on( 'content:render:browse', this.settings, this ); 883 884 media.controller.Library.prototype.activate.apply( this, arguments ); 885 }, 886 887 deactivate: function() { 888 // Stop watching for uploaded attachments. 889 this.get('library').unobserve( wp.Uploader.queue ); 890 891 this.frame.off( 'content:render:browse', this.settings, this ); 892 893 media.controller.Library.prototype.deactivate.apply( this, arguments ); 894 }, 895 896 settings: function( browser ) { 897 var library = this.get('library'), obj = {}; 898 899 if ( ! library || ! browser ) { 900 return; 901 } 902 903 library[ prop ] = library[ prop ] || new Backbone.Model(); 904 905 obj[ prop ] = new media.view.Settings[ args.settings ]({ 906 controller: this, 907 model: library[ prop ], 908 priority: 40 909 }); 910 911 browser.sidebar.set( obj ); 912 913 if ( args.dragInfoText ) { 914 browser.toolbar.set( 'dragInfo', new media.View({ 915 el: $( '<div class="instructions">' + args.dragInfoText + '</div>' )[0], 916 priority: -40 917 }) ); 918 } 919 920 browser.toolbar.set( 'reverse', { 921 text: l10n.reverseOrder, 922 priority: 80, 923 924 click: function() { 925 library.reset( library.toArray().reverse() ); 926 } 927 }); 928 } 929 }); 930 }; 931 932 media.controller.CollectionAdd = function ( prop, args ) { 933 return media.controller.Library.extend({ 934 defaults: _.defaults({ 935 id: prop + '-library', 936 filterable: 'uploaded', 937 multiple: 'add', 938 menu: prop, 939 toolbar: prop + '-add', 940 priority: 100, 941 syncSelection: false 942 }, args.defaults || {}, media.controller.Library.prototype.defaults ), 943 initialize: function() { 944 // If we haven't been provided a `library`, create a `Selection`. 945 if ( ! this.get('library') ) { 946 this.set( 'library', media.query({ type: args.type }) ); 947 } 948 media.controller.Library.prototype.initialize.apply( this, arguments ); 949 }, 950 951 activate: function() { 952 var library = this.get('library'), 953 edit = this.frame.state(prop + '-edit').get('library'); 954 955 if ( this.editLibrary && this.editLibrary !== edit ) { 956 library.unobserve( this.editLibrary ); 957 } 958 959 // Accepts attachments that exist in the original library and 960 // that do not exist in gallery's library. 961 library.validator = function( attachment ) { 962 return !! this.mirroring.get( attachment.cid ) && ! edit.get( attachment.cid ) && media.model.Selection.prototype.validator.apply( this, arguments ); 963 }; 964 965 // Reset the library to ensure that all attachments are re-added 966 // to the collection. Do so silently, as calling `observe` will 967 // trigger the `reset` event. 968 library.reset( library.mirroring.models, { silent: true }); 969 library.observe( edit ); 970 this.editLibrary = edit; 971 972 media.controller.Library.prototype.activate.apply( this, arguments ); 973 } 974 }); 975 }; 976 977 // wp.media.controller.GalleryEdit 978 // ------------------------------- 979 media.controller.GalleryEdit = media.controller.CollectionEdit( 'gallery', { 980 type: 'image', 981 settings: 'Gallery', 982 defaults: { 983 title: l10n.editGalleryTitle 984 } 985 }); 986 987 // wp.media.controller.GalleryAdd 988 // --------------------------------- 989 media.controller.GalleryAdd = media.controller.CollectionAdd( 'gallery', { 990 type: 'image', 991 defaults: { 992 title: l10n.addToGalleryTitle 993 } 994 }); 995 996 // wp.media.controller.PlaylistEdit 997 // ------------------------------- 998 media.controller.PlaylistEdit = media.controller.CollectionEdit( 'playlist', { 999 type: 'audio', 1000 settings: 'Playlist', 1001 dragInfoText: l10n.playlistDragInfo, 1002 defaults: { 1003 title: l10n.editPlaylistTitle, 1004 dragInfo : false 1005 } 1006 }); 1007 1008 // wp.media.controller.PlaylistAdd 1009 // --------------------------------- 1010 media.controller.PlaylistAdd = media.controller.CollectionAdd( 'playlist', { 1011 type: 'audio', 1012 defaults: { 1013 title: l10n.addToPlaylistTitle 1014 } 1015 }); 1016 1017 // wp.media.controller.VideoPlaylistEdit 1018 // ------------------------------- 1019 media.controller.VideoPlaylistEdit = media.controller.CollectionEdit( 'video-playlist', { 1020 type: 'video', 1021 settings: 'Playlist', 1022 dragInfoText: l10n.videoPlaylistDragInfo, 1023 defaults: { 1024 title: l10n.editVideoPlaylistTitle, 1025 dragInfo : false 1026 } 1027 }); 1028 1029 // wp.media.controller.VideoPlaylistAdd 1030 // --------------------------------- 1031 media.controller.VideoPlaylistAdd = media.controller.CollectionAdd( 'video-playlist', { 1032 type: 'video', 1033 defaults: { 1034 title: l10n.addToVideoPlaylistTitle 1035 } 1036 }); 1037 1008 1038 /** 1009 1039 * wp.media.controller.ReplaceImage 1010 1040 * … … 1758 1788 menu: 'gallery' 1759 1789 }), 1760 1790 1761 new media.controller.GalleryAdd() 1791 new media.controller.GalleryAdd(), 1792 1793 new media.controller.Library({ 1794 id: 'playlist', 1795 title: l10n.createPlaylistTitle, 1796 priority: 60, 1797 toolbar: 'main-playlist', 1798 filterable: 'uploaded', 1799 multiple: 'add', 1800 editable: false, 1801 1802 library: media.query( _.defaults({ 1803 type: 'audio' 1804 }, options.library ) ) 1805 }), 1806 1807 // Playlist states. 1808 new media.controller.PlaylistEdit({ 1809 library: options.selection, 1810 editing: options.editing, 1811 menu: 'playlist' 1812 }), 1813 1814 new media.controller.PlaylistAdd(), 1815 1816 new media.controller.Library({ 1817 id: 'video-playlist', 1818 title: l10n.createVideoPlaylistTitle, 1819 priority: 60, 1820 toolbar: 'main-video-playlist', 1821 filterable: 'uploaded', 1822 multiple: 'add', 1823 editable: false, 1824 1825 library: media.query( _.defaults({ 1826 type: 'video' 1827 }, options.library ) ) 1828 }), 1829 1830 // Video Playlist states. 1831 new media.controller.VideoPlaylistEdit({ 1832 library: options.selection, 1833 editing: options.editing, 1834 menu: 'video-playlist' 1835 }), 1836 1837 new media.controller.VideoPlaylistAdd() 1762 1838 ]); 1763 1839 1764 1840 … … 1773 1849 */ 1774 1850 media.view.MediaFrame.Select.prototype.bindHandlers.apply( this, arguments ); 1775 1851 this.on( 'menu:create:gallery', this.createMenu, this ); 1852 this.on( 'menu:create:playlist', this.createMenu, this ); 1853 this.on( 'menu:create:video-playlist', this.createMenu, this ); 1776 1854 this.on( 'toolbar:create:main-insert', this.createToolbar, this ); 1777 this.on( 'toolbar:create:main-gallery', this.createToolbar, this ); 1855 this.on( 'toolbar:create:main-gallery', this.createToolbar, this ); 1856 this.on( 'toolbar:create:main-playlist', this.createToolbar, this ); 1857 this.on( 'toolbar:create:main-video-playlist', this.createToolbar, this ); 1778 1858 this.on( 'toolbar:create:featured-image', this.featuredImageToolbar, this ); 1779 1859 this.on( 'toolbar:create:main-embed', this.mainEmbedToolbar, this ); 1780 1860 … … 1781 1861 var handlers = { 1782 1862 menu: { 1783 1863 'default': 'mainMenu', 1784 'gallery': 'galleryMenu' 1864 'gallery': 'galleryMenu', 1865 'playlist': 'playlistMenu', 1866 'video-playlist': 'videoPlaylistMenu' 1785 1867 }, 1786 1868 1787 1869 content: { … … 1793 1875 'main-insert': 'mainInsertToolbar', 1794 1876 'main-gallery': 'mainGalleryToolbar', 1795 1877 'gallery-edit': 'galleryEditToolbar', 1796 'gallery-add': 'galleryAddToolbar' 1878 'gallery-add': 'galleryAddToolbar', 1879 'main-playlist': 'mainPlaylistToolbar', 1880 'playlist-edit': 'playlistEditToolbar', 1881 'playlist-add': 'playlistAddToolbar', 1882 'main-video-playlist': 'mainVideoPlaylistToolbar', 1883 'video-playlist-edit': 'videoPlaylistEditToolbar', 1884 'video-playlist-add': 'videoPlaylistAddToolbar' 1797 1885 } 1798 1886 }; 1799 1887 … … 1842 1930 }); 1843 1931 }, 1844 1932 1933 playlistMenu: function( view ) { 1934 var lastState = this.lastState(), 1935 previous = lastState && lastState.id, 1936 frame = this; 1937 1938 view.set({ 1939 cancel: { 1940 text: l10n.cancelPlaylistTitle, 1941 priority: 20, 1942 click: function() { 1943 if ( previous ) 1944 frame.setState( previous ); 1945 else 1946 frame.close(); 1947 } 1948 }, 1949 separateCancel: new media.View({ 1950 className: 'separator', 1951 priority: 60 1952 }) 1953 }); 1954 }, 1955 1956 videoPlaylistMenu: function( view ) { 1957 var lastState = this.lastState(), 1958 previous = lastState && lastState.id, 1959 frame = this; 1960 1961 view.set({ 1962 cancel: { 1963 text: l10n.cancelVideoPlaylistTitle, 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: 80 1975 }) 1976 }); 1977 }, 1978 1845 1979 // Content 1846 1980 embedContent: function() { 1847 1981 var view = new media.view.Embed({ … … 1960 2094 }); 1961 2095 }, 1962 2096 2097 mainPlaylistToolbar: function( view ) { 2098 var controller = this; 2099 2100 this.selectionStatusToolbar( view ); 2101 2102 view.set( 'playlist', { 2103 style: 'primary', 2104 text: l10n.createNewPlaylist, 2105 priority: 100, 2106 requires: { selection: true }, 2107 2108 click: function() { 2109 var selection = controller.state().get('selection'), 2110 edit = controller.state('playlist-edit'), 2111 models = selection.where({ type: 'audio' }); 2112 2113 edit.set( 'library', new media.model.Selection( models, { 2114 props: selection.props.toJSON(), 2115 multiple: true 2116 }) ); 2117 2118 this.controller.setState('playlist-edit'); 2119 } 2120 }); 2121 }, 2122 2123 mainVideoPlaylistToolbar: function( view ) { 2124 var controller = this; 2125 2126 this.selectionStatusToolbar( view ); 2127 2128 view.set( 'video-playlist', { 2129 style: 'primary', 2130 text: l10n.createNewVideoPlaylist, 2131 priority: 100, 2132 requires: { selection: true }, 2133 2134 click: function() { 2135 var selection = controller.state().get('selection'), 2136 edit = controller.state('video-playlist-edit'), 2137 models = selection.where({ type: 'video' }); 2138 2139 edit.set( 'library', new media.model.Selection( models, { 2140 props: selection.props.toJSON(), 2141 multiple: true 2142 }) ); 2143 2144 this.controller.setState('video-playlist-edit'); 2145 } 2146 }); 2147 }, 2148 1963 2149 featuredImageToolbar: function( toolbar ) { 1964 2150 this.createSelectToolbar( toolbar, { 1965 2151 text: l10n.setFeaturedImage, … … 2028 2214 } 2029 2215 } 2030 2216 }) ); 2217 }, 2218 2219 playlistEditToolbar: function() { 2220 var editing = this.state().get('editing'); 2221 this.toolbar.set( new media.view.Toolbar({ 2222 controller: this, 2223 items: { 2224 insert: { 2225 style: 'primary', 2226 text: editing ? l10n.updatePlaylist : l10n.insertPlaylist, 2227 priority: 80, 2228 requires: { library: true }, 2229 2230 /** 2231 * @fires wp.media.controller.State#update 2232 */ 2233 click: function() { 2234 var controller = this.controller, 2235 state = controller.state(); 2236 2237 controller.close(); 2238 state.trigger( 'update', state.get('library') ); 2239 2240 // Restore and reset the default state. 2241 controller.setState( controller.options.state ); 2242 controller.reset(); 2243 } 2244 } 2245 } 2246 }) ); 2247 }, 2248 2249 playlistAddToolbar: function() { 2250 this.toolbar.set( new media.view.Toolbar({ 2251 controller: this, 2252 items: { 2253 insert: { 2254 style: 'primary', 2255 text: l10n.addToPlaylist, 2256 priority: 80, 2257 requires: { selection: true }, 2258 2259 /** 2260 * @fires wp.media.controller.State#reset 2261 */ 2262 click: function() { 2263 var controller = this.controller, 2264 state = controller.state(), 2265 edit = controller.state('playlist-edit'); 2266 2267 edit.get('library').add( state.get('selection').models ); 2268 state.trigger('reset'); 2269 controller.setState('playlist-edit'); 2270 } 2271 } 2272 } 2273 }) ); 2274 }, 2275 2276 videoPlaylistEditToolbar: function() { 2277 var editing = this.state().get('editing'); 2278 this.toolbar.set( new media.view.Toolbar({ 2279 controller: this, 2280 items: { 2281 insert: { 2282 style: 'primary', 2283 text: editing ? l10n.updateVideoPlaylist : l10n.insertVideoPlaylist, 2284 priority: 140, 2285 requires: { library: true }, 2286 2287 click: function() { 2288 var controller = this.controller, 2289 state = controller.state(); 2290 2291 controller.close(); 2292 state.trigger( 'update', state.get('library') ); 2293 2294 // Restore and reset the default state. 2295 controller.setState( controller.options.state ); 2296 controller.reset(); 2297 } 2298 } 2299 } 2300 }) ); 2301 }, 2302 2303 videoPlaylistAddToolbar: function() { 2304 this.toolbar.set( new media.view.Toolbar({ 2305 controller: this, 2306 items: { 2307 insert: { 2308 style: 'primary', 2309 text: l10n.addToVideoPlaylist, 2310 priority: 140, 2311 requires: { selection: true }, 2312 2313 click: function() { 2314 var controller = this.controller, 2315 state = controller.state(), 2316 edit = controller.state('video-playlist-edit'); 2317 2318 edit.get('library').add( state.get('selection').models ); 2319 state.trigger('reset'); 2320 controller.setState('video-playlist-edit'); 2321 } 2322 } 2323 } 2324 }) ); 2031 2325 } 2032 2033 2326 }); 2034 2327 2035 2328 media.view.MediaFrame.ImageDetails = media.view.MediaFrame.Select.extend({ … … 4849 5142 }); 4850 5143 4851 5144 /** 5145 * wp.media.view.Settings.Gallery 5146 */ 5147 media.view.Settings.Playlist = media.view.Settings.extend({ 5148 className: 'playlist-settings', 5149 template: media.template('playlist-settings') 5150 }); 5151 5152 /** 4852 5153 * wp.media.view.Attachment.Details 4853 5154 * 4854 5155 * @constructor -
src/wp-includes/js/mediaelement/wp-mediaelement.css
13 13 .me-cannotplay { 14 14 width: auto !important; 15 15 } 16 17 .wp-playlist { 18 border: 1px solid #ccc; 19 padding: 10px; 20 margin: 12px 0 18px; 21 font-size: 85%; 22 } 23 24 .wp-playlist .mejs-container { 25 margin: 0; 26 } 27 28 .wp-playlist .mejs-controls .mejs-button button { 29 outline: 0; 30 } 31 32 .wp-playlist-audio { 33 34 } 35 36 .wp-playlist-video { 37 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-current-item { 50 overflow: hidden; 51 margin-bottom: 10px; 52 } 53 54 .wp-playlist-current-item img { 55 float: left; 56 max-width: 60px; 57 height: auto; 58 margin-right: 10px; 59 } 60 61 .wp-playlist-caption { 62 } 63 64 .wp-caption-meta { 65 display: block; 66 } 67 68 .wp-caption-title { 69 font-size: 100%; 70 } 71 72 .wp-caption-album { 73 font-style: italic; 74 } 75 76 .wp-caption-artist { 77 font-size: 80%; 78 text-transform: uppercase; 79 } 80 81 .wp-caption-by { 82 font-size: 65%; 83 font-weight: bold; 84 } 85 86 .wp-playlist-item-length { 87 position: absolute; 88 right: 0; 89 top: 0; 90 } 91 92 .wp-playlist-tracks { 93 margin-top: 10px; 94 border-top: 1px solid #ccc; 95 } 96 97 .wp-playlist-item { 98 position: relative; 99 cursor: pointer; 100 border-bottom: 1px solid #ccc; 101 } 102 No newline at end of file -
src/wp-includes/js/plupload/handlers.js
22 22 .appendTo( jQuery('#media-items' ) ); 23 23 24 24 // Disable submit 25 jQuery('#insert-gallery ').prop('disabled', true);25 jQuery('#insert-gallery, #insert-playlist').prop('disabled', true); 26 26 } 27 27 28 28 function uploadStart() { … … 47 47 48 48 if ( max > hundredmb && file.size > hundredmb ) { 49 49 setTimeout(function(){ 50 50 51 51 if ( file.status < 3 && file.loaded === 0 ) { // not uploading 52 52 wpFileError(file, pluploadL10n.big_upload_failed.replace('%1$s', '<a class="uploader-html" href="#">').replace('%2$s', '</a>')); 53 53 up.stop(); // stops the whole queue … … 64 64 // Just one file, no need for collapsible part 65 65 if ( items.length == 1 ) { 66 66 items.addClass('open').find('.slidetoggle').show(); 67 jQuery('.insert-gallery ').hide();67 jQuery('.insert-gallery, .insert-playlist').hide(); 68 68 } else if ( items.length > 1 ) { 69 69 items.removeClass('open'); 70 // Only show Gallery buttonwhen 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(); 72 72 } 73 73 74 74 // Only show Save buttons when there is at least one file. … … 171 171 success: function( ){ 172 172 var type, 173 173 item = jQuery('#media-item-' + fileObj.id); 174 174 175 175 if ( type = jQuery('#type-of-' + fileObj.id).val() ) 176 176 jQuery('#' + type + '-counter').text(jQuery('#' + type + '-counter').text()-0+1); 177 177 … … 257 257 } 258 258 259 259 function uploadComplete() { 260 jQuery('#insert-gallery ').prop('disabled', false);260 jQuery('#insert-gallery, #insert-playlist').prop('disabled', false); 261 261 } 262 262 263 263 function switchUploader(s) { -
src/wp-includes/js/swfupload/handlers.js
25 25 jQuery('.progress', '#media-item-' + fileObj.id).show(); 26 26 27 27 // Disable submit and enable cancel 28 jQuery('#insert-gallery ').prop('disabled', true);28 jQuery('#insert-gallery, #insert-playlist').prop('disabled', true); 29 29 jQuery('#cancel-upload').prop('disabled', false); 30 30 } 31 31 … … 32 32 function uploadStart(fileObj) { 33 33 try { 34 34 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); 36 36 } catch(e){} 37 37 38 38 return true; … … 212 212 else 213 213 jQuery('.savebutton').hide(); 214 214 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 } 220 221 } 221 222 222 223 function uploadSuccess(fileObj, serverData) { … … 238 239 // If no more uploads queued, enable the submit button 239 240 if ( swfu.getStats().files_queued == 0 ) { 240 241 jQuery('#cancel-upload').prop('disabled', true); 241 jQuery('#insert-gallery ').prop('disabled', false);242 jQuery('#insert-gallery, #insert-playlist').prop('disabled', false); 242 243 } 243 244 } 244 245 -
src/wp-includes/js/tinymce/langs/wp-langs-en.js
478 478 add_audio: "Add Audio", 479 479 editgallery: "Edit Gallery", 480 480 delgallery: "Delete Gallery", 481 editplaylist: "Edit Playlist", 482 delplaylist: "Delete Playlist", 481 483 wp_fullscreen_desc: "Distraction Free Writing mode (Alt + Shift + W)" 482 484 }); 483 485 -
src/wp-includes/js/tinymce/skins/wordpress/wp-content.css
108 108 border-top: 3px dotted #bbb; 109 109 } 110 110 111 .mce-content-body img.wp-gallery { 111 .mce-content-body img.wp-gallery, 112 .mce-content-body img.wp-playlist, 113 .mce-content-body img.wp-video-playlist{ 112 114 border: 1px dashed #888; 113 115 background: #f2f2f2 url("images/gallery.png") no-repeat scroll center center; 114 116 width: 99%; … … 117 119 cursor: pointer; 118 120 } 119 121 120 .mce-content-body img.wp-gallery:hover { 122 .mce-content-body img.wp-playlist { 123 background: #f2f2f2; 124 } 125 126 .mce-content-body img.wp-video-playlist { 127 background-image: url("images/embedded.png"); 128 } 129 130 .mce-content-body img.wp-gallery:hover, .mce-content-body img.wp-playlist:hover { 121 131 background-color: #ededed; 122 132 border-style: solid; 123 133 } 124 134 125 .mce-content-body img.wp-gallery.wp-gallery-selected {135 .mce-content-body img.wp-gallery.wp-gallery-selected, .mce-content-body img.wp-playlist.wp-playlist-selected { 126 136 background-color: #d8d8d8; 127 137 border-style: solid; 128 138 } -
src/wp-includes/media-template.php
411 411 </label> 412 412 </script> 413 413 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="tracknums" /> 442 </label> 443 444 <label class="setting"> 445 <span><?php _e( 'Show Images' ); ?></span> 446 <input type="checkbox" data-setting="images" /> 447 </label> 448 </script> 449 414 450 <script type="text/html" id="tmpl-embed-link-settings"> 415 451 <label class="setting"> 416 452 <span><?php _e('Title'); ?></span> -
src/wp-includes/media.php
892 892 } 893 893 894 894 /** 895 * The Playlist shortcode. 896 * 897 * This implements the functionality of the Playlist Shortcode for displaying 898 * WordPress audio or video files on a post. 899 * 900 * @since 3.9.0 901 * 902 * @param array $attr Attributes of the shortcode. 903 * @return string $type Type of playlist. Defaults to audio, video is also supported 904 */ 905 function wp_get_playlist( $attr, $type ) { 906 $post = get_post(); 907 908 if ( ! in_array( $type, array( 'audio', 'video' ) ) ) { 909 return ''; 910 } 911 912 static $instance = 0; 913 $instance++; 914 915 if ( ! empty( $attr['ids'] ) ) { 916 // 'ids' is explicitly ordered, unless you specify otherwise. 917 if ( empty( $attr['orderby'] ) ) 918 $attr['orderby'] = 'post__in'; 919 $attr['include'] = $attr['ids']; 920 } 921 922 // Allow plugins/themes to override the default gallery template. 923 $output = apply_filters( 'post_playlist', '', $attr, $type ); 924 if ( $output != '' ) 925 return $output; 926 927 // We're trusting author input, so let's at least make sure it looks like a valid orderby statement 928 if ( isset( $attr['orderby'] ) ) { 929 $attr['orderby'] = sanitize_sql_orderby( $attr['orderby'] ); 930 if ( ! $attr['orderby'] ) 931 unset( $attr['orderby'] ); 932 } 933 934 extract( shortcode_atts( array( 935 'order' => 'ASC', 936 'orderby' => 'menu_order ID', 937 'id' => $post ? $post->ID : 0, 938 'include' => '', 939 'exclude' => '', 940 'style' => 'light', 941 'tracklist' => 'audio' === $type, 942 'tracknums' => 'audio' === $type, 943 'images' => true 944 ), $attr, 'playlist' ) ); 945 946 $id = intval( $id ); 947 if ( 'RAND' == $order ) 948 $orderby = 'none'; 949 950 if ( ! empty( $include ) ) { 951 $_attachments = get_posts( array( 'include' => $include, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => $type, 'order' => $order, 'orderby' => $orderby ) ); 952 953 $attachments = array(); 954 foreach ( $_attachments as $key => $val ) { 955 $attachments[$val->ID] = $_attachments[$key]; 956 } 957 } elseif ( ! empty( $exclude ) ) { 958 $attachments = get_children( array('post_parent' => $id, 'exclude' => $exclude, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => $type, 'order' => $order, 'orderby' => $orderby ) ); 959 } else { 960 $attachments = get_children( array('post_parent' => $id, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => $type, 'order' => $order, 'orderby' => $orderby) ); 961 } 962 963 if ( empty( $attachments ) ) 964 return ''; 965 966 if ( is_feed() ) { 967 $output = "\n"; 968 foreach ( $attachments as $att_id => $attachment ) 969 $output .= wp_get_attachment_link( $att_id, $size, true ) . "\n"; 970 971 return $output; 972 } 973 974 $supports_thumbs = ( current_theme_supports( 'post-thumbnails', "attachment:$type" ) && post_type_supports( "attachment:$type", 'thumbnail' ) ) || $images; 975 976 $data = compact( 'type', 'tracklist', 'tracknums', 'images', 'style' ); 977 $tracks = array(); 978 foreach ( $attachments as $attachment ) { 979 $url = wp_get_attachment_url( $attachment->ID ); 980 $ftype = wp_check_filetype( $url, wp_get_mime_types() ); 981 $track = array( 982 'type' => $type, 983 'src' => $url, 984 'type' => $ftype['ext'], 985 'title' => get_the_title( $attachment->ID ), 986 'caption' => wptexturize( $attachment->post_excerpt ), 987 'description' => wptexturize( $attachment->post_content ) 988 ); 989 990 $meta = wp_get_attachment_metadata( $attachment->ID ); 991 if ( ! empty( $meta ) ) { 992 $track['meta'] = array(); 993 994 $keys = array( 'title', 'artist', 'band', 'album', 'genre', 'year', 'length', 'length_formatted' ); 995 foreach ( $keys as $key ) { 996 if ( ! empty( $meta[ $key ] ) ) { 997 $track['meta'][ $key ] = $meta[ $key ]; 998 } 999 } 1000 } 1001 1002 if ( $supports_thumbs ) { 1003 $id = get_post_thumbnail_id( $attachment->ID ); 1004 if ( ! empty( $id ) ) { 1005 list( $src, $width, $height ) = wp_get_attachment_image_src( $id, 'full' ); 1006 $track['image'] = compact( 'src', 'width', 'height' ); 1007 } 1008 } 1009 1010 $tracks[] = $track; 1011 } 1012 $data['tracks'] = $tracks; 1013 1014 ob_start(); 1015 1016 if ( 1 === $instance ): 1017 wp_enqueue_style( 'wp-mediaelement' ); 1018 wp_enqueue_script( 'wp-playlist' ); 1019 ?> 1020 <script type="text/html" id="tmpl-wp-playlist-current-item"> 1021 <# if ( data.image ) { #> 1022 <img src="{{{ data.image.src }}}"/> 1023 <# } #> 1024 <# if ( data.meta.title ) { #> 1025 <div class="wp-playlist-caption"> 1026 <span class="wp-caption-meta wp-caption-title">“{{{ data.meta.title }}}”</span> 1027 <span class="wp-caption-meta wp-caption-album">{{{ data.meta.album }}}</span> 1028 <span class="wp-caption-meta wp-caption-artist">{{{ data.meta.artist }}}</span> 1029 </div> 1030 <# } else { #> 1031 <div class="wp-playlist-caption">{{{ data.caption }}}</div> 1032 <# } #> 1033 </script> 1034 <script type="text/html" id="tmpl-wp-playlist-item"> 1035 <div class="wp-playlist-item"> 1036 <# if ( data.meta.title ) { #> 1037 <div class="wp-playlist-caption"> 1038 {{{ data.index }}}. 1039 <span class="wp-caption-title">“{{{ data.meta.title }}}”</span> 1040 <span class="wp-caption-by"><?php _e( 'by' ) ?></span> 1041 <span class="wp-caption-artist">{{{ data.meta.artist }}}</span> 1042 </div> 1043 <# } else { #> 1044 <div class="wp-playlist-caption">{{{ data.index }}}. {{{ data.caption }}}</div> 1045 <# } #> 1046 <# if ( data.meta.length_formatted ) { #> 1047 <div class="wp-playlist-item-length">{{{ data.meta.length_formatted }}}</div> 1048 <# } #> 1049 </div> 1050 </script> 1051 <?php endif ?> 1052 <div class="wp-playlist wp-<?php echo $type ?>-playlist wp-playlist-<?php echo $style ?>"> 1053 <div class="wp-playlist-current-item"></div> 1054 <<?php echo $type ?> controls="controls" preload="metadata"></<?php echo $type ?>> 1055 <div class="wp-playlist-next"></div> 1056 <div class="wp-playlist-prev"></div> 1057 <noscript> 1058 1059 </noscript> 1060 <script type="application/json"><?php echo json_encode( $data ) ?></script> 1061 </div> 1062 <?php 1063 $output = ob_get_clean(); 1064 1065 return $output; 1066 } 1067 1068 function wp_playlist_shortcode( $attr ) { 1069 return wp_get_playlist( $attr, 'audio' ); 1070 } 1071 add_shortcode( 'playlist', 'wp_playlist_shortcode' ); 1072 1073 function wp_video_playlist_shortcode( $attr ) { 1074 return wp_get_playlist( $attr, 'video' ); 1075 } 1076 add_shortcode( 'video-playlist', 'wp_video_playlist_shortcode' ); 1077 1078 /** 895 1079 * Provide a No-JS Flash fallback as a last resort for audio / video 896 1080 * 897 1081 * @since 3.6.0 … … 1984 2168 'mediaLibraryTitle' => __( 'Media Library' ), 1985 2169 'insertMediaTitle' => __( 'Insert Media' ), 1986 2170 'createNewGallery' => __( 'Create a new gallery' ), 2171 'createNewPlaylist' => __( 'Create a new playlist' ), 2172 'createNewVideoPlaylist' => __( 'Create a new video playlist' ), 1987 2173 'returnToLibrary' => __( '← Return to library' ), 1988 2174 'allMediaItems' => __( 'All media items' ), 1989 2175 'noItemsFound' => __( 'No items found.' ), … … 2011 2197 // Edit Image 2012 2198 'imageDetailsTitle' => __( 'Image Details' ), 2013 2199 'imageReplaceTitle' => __( 'Replace Image' ), 2014 'imageDetailsCancel' => __( 'Cancel Edit' ) 2200 'imageDetailsCancel' => __( 'Cancel Edit' ), 2201 2202 // Playlist 2203 'playlistDragInfo' => __( 'Drag and drop to reorder tracks.' ), 2204 'createPlaylistTitle' => __( 'Create Playlist' ), 2205 'editPlaylistTitle' => __( 'Edit Playlist' ), 2206 'cancelPlaylistTitle' => __( '← Cancel Playlist' ), 2207 'insertPlaylist' => __( 'Insert playlist' ), 2208 'updatePlaylist' => __( 'Update playlist' ), 2209 'addToPlaylist' => __( 'Add to playlist' ), 2210 'addToPlaylistTitle' => __( 'Add to Playlist' ), 2211 2212 // Video Playlist 2213 'videoPlaylistDragInfo' => __( 'Drag and drop to reorder videos.' ), 2214 'createVideoPlaylistTitle' => __( 'Create Video Playlist' ), 2215 'editVideoPlaylistTitle' => __( 'Edit Video Playlist' ), 2216 'cancelVideoPlaylistTitle' => __( '← Cancel Video Playlist' ), 2217 'insertVideoPlaylist' => __( 'Insert Video playlist' ), 2218 'updateVideoPlaylist' => __( 'Update Video playlist' ), 2219 'addToVideoPlaylist' => __( 'Add to Video playlist' ), 2220 'addToVideoPlaylistTitle' => __( 'Add to Video Playlist' ), 2015 2221 ); 2016 2222 2017 2223 $settings = apply_filters( 'media_view_settings', $settings, $post ); -
src/wp-includes/script-loader.php
311 311 'pluginPath' => includes_url( 'js/mediaelement/', 'relative' ), 312 312 ) ); 313 313 314 $scripts->add( 'wp-playlist', "/wp-includes/js/mediaelement/wp-playlist.js", array( 'wp-util', 'backbone', 'mediaelement' ), false, 1 ); 315 314 316 $scripts->add( 'zxcvbn-async', "/wp-includes/js/zxcvbn-async$suffix.js", array(), '1.0' ); 315 317 did_action( 'init' ) && $scripts->localize( 'zxcvbn-async', '_zxcvbnSettings', array( 316 318 'src' => empty( $guessed_url ) ? includes_url( '/js/zxcvbn.min.js' ) : $scripts->base_url . '/wp-includes/js/zxcvbn.min.js',
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)