summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
authorScott Taylor <wonderboymusic@git.wordpress.org>2014-03-20 13:33:00 +0000
committerScott Taylor <wonderboymusic@git.wordpress.org>2014-03-20 13:33:00 +0000
commit5c0f7ae4fbcf6517ba586ddfa2c2d16f5db5f6ad (patch)
tree3d68b3b10ad91f902b75bd7a9662e048de650c30 /src
parent5bbb2d3951880b77659ab89595c3c0ca7d909815 (diff)
downloadwordpress-5c0f7ae4fbcf6517ba586ddfa2c2d16f5db5f6ad.tar.gz
wordpress-5c0f7ae4fbcf6517ba586ddfa2c2d16f5db5f6ad.zip
Unifying media controls and supporting playlists in the editor:
* Support a `caption` attribute for audio and video shortcodes * In `wp.media.audio|video`, rename `update` to `shortcode` to allow these models to share the same mixins as `wp.media.collection` subclasses * When sending an audio or video shortcode to the editor, create a default caption if the user hasn't entered one. This currently only displays in the editor, not on the front end. Captions aren't tied to a specific attachment here because external sources are supported. * In the `wp.mce.media` mixin, in the `edit` method, read `attr` instead of `data` when attempting to parse the encoded shortcode. `data` does not automatically update when the attribute changes. This was a blessing to debug. * Add `wp.mce.media.PlaylistView` to support playlist views in TinyMCE * Expose `WPPlaylistView` to global scope and suppress auto-parsing of playlist nodes when in the admin. Allow `WPPlaylistView` to be passed `metadata` on creation instead of requiring a JSON blob to be parsed. * Remove all of the playlist logic from the `wpgallery` TinyMCE plugin. * In `wp_prepare_attachment_for_js()` return more data for audio/video so that playlists can have parity in the admin/front end. See #27320. git-svn-id: https://develop.svn.wordpress.org/trunk@27640 602fd350-edb4-49c9-b593-d223f7449a82
Diffstat (limited to 'src')
-rw-r--r--src/wp-includes/js/media-audiovideo.js154
-rw-r--r--src/wp-includes/js/media-editor.js18
-rw-r--r--src/wp-includes/js/mediaelement/wp-playlist.js16
-rw-r--r--src/wp-includes/js/tinymce/plugins/wpgallery/plugin.js47
-rw-r--r--src/wp-includes/js/tinymce/skins/wordpress/wp-content.css18
-rw-r--r--src/wp-includes/media-template.php40
-rw-r--r--src/wp-includes/media.php43
-rw-r--r--src/wp-includes/script-loader.php2
8 files changed, 258 insertions, 80 deletions
diff --git a/src/wp-includes/js/media-audiovideo.js b/src/wp-includes/js/media-audiovideo.js
index 182cc158da..261be871bc 100644
--- a/src/wp-includes/js/media-audiovideo.js
+++ b/src/wp-includes/js/media-audiovideo.js
@@ -207,10 +207,11 @@
defaults : {
id : wp.media.view.settings.post.id,
- src : '',
- loop : false,
+ src : '',
+ loop : false,
autoplay : false,
- preload : 'none'
+ preload : 'none',
+ caption : ''
},
edit : function (data) {
@@ -227,7 +228,7 @@
return frame;
},
- update : function (model) {
+ shortcode : function (model) {
var self = this, content;
_.each( this.defaults, function( value, key ) {
@@ -266,7 +267,8 @@
loop : false,
autoplay : false,
preload : 'metadata',
- content : ''
+ content : '',
+ caption : ''
},
edit : function (data) {
@@ -287,7 +289,7 @@
return frame;
},
- update : function (model) {
+ shortcode : function (model) {
var self = this, content;
_.each( this.defaults, function( value, key ) {
@@ -1129,13 +1131,13 @@
wp.media.mixin.pauseAllPlayers();
- data = window.decodeURIComponent( $( node ).data('wpview-text') );
+ data = window.decodeURIComponent( $( node ).attr('data-wpview-text') );
frame = media.edit( data );
frame.on( 'close', function () {
frame.detach();
} );
- frame.state( self.shortcode + '-details' ).on( 'update', function( selection ) {
- var shortcode = wp.media[ self.shortcode ].update( selection ).string();
+ frame.state( self.state ).on( 'update', function( selection ) {
+ var shortcode = wp.media[ self.shortcode ].shortcode( selection ).string();
$( node ).attr( 'data-wpview-text', window.encodeURIComponent( shortcode ) );
wp.mce.views.refreshView( self, shortcode );
frame.detach();
@@ -1205,6 +1207,7 @@
wp.mce.video = _.extend( {}, wp.mce.media, {
shortcode: 'video',
+ state: 'video-details',
View: wp.mce.media.View.extend({
className: 'editor-video',
template: media.template('editor-video')
@@ -1215,6 +1218,7 @@
wp.mce.audio = _.extend( {}, wp.mce.media, {
shortcode: 'audio',
+ state: 'audio-details',
View: wp.mce.media.View.extend({
className: 'editor-audio',
template: media.template('editor-audio')
@@ -1223,6 +1227,138 @@
wp.mce.views.register( 'audio', wp.mce.audio );
+ wp.mce.media.PlaylistView = wp.mce.View.extend({
+ className: 'editor-playlist',
+ template: media.template('editor-playlist'),
+
+ initialize: function( options ) {
+ this.data = {};
+ this.attachments = [];
+ this.shortcode = options.shortcode;
+ _.bindAll( this, 'setPlayer' );
+ $(this).on('ready', this.setNode);
+ },
+
+ setNode: function (e, node) {
+ this.node = node;
+ this.fetch();
+ },
+
+ fetch: function() {
+ this.attachments = wp.media[ this.shortcode.tag ].attachments( this.shortcode );
+ this.attachments.more().done( this.setPlayer );
+ },
+
+ setPlayer: function () {
+ var p,
+ html = this.getHtml(),
+ t = this.encodedText,
+ self = this;
+
+ this.unsetPlayer();
+
+ _.each( tinymce.editors, function( editor ) {
+ var doc;
+ if ( editor.plugins.wpview ) {
+ doc = editor.getDoc();
+ $( doc ).find( '[data-wpview-text="' + t + '"]' ).each(function (i, elem) {
+ var node = $( elem );
+ node.html( html );
+ self.node = elem;
+ });
+ }
+ }, this );
+
+ p = new WPPlaylistView({
+ el: $( self.node ).find( '.wp-playlist' ).get(0),
+ metadata: this.data
+ });
+
+ this.player = p._player;
+ },
+
+ getHtml: function() {
+ var data = this.shortcode.attrs.named,
+ model = wp.media[ this.shortcode.tag ],
+ type = 'playlist' === this.shortcode.tag ? 'audio' : 'video',
+ options,
+ attachments,
+ tracks = [];
+
+ if ( ! this.attachments.length ) {
+ return;
+ }
+
+ _.each( model.defaults, function( value, key ) {
+ data[ key ] = model.coerce( data, key );
+ });
+
+ attachments = this.attachments.toJSON();
+
+ options = {
+ type: type,
+ style: data.style,
+ tracklist: data.tracklist,
+ tracknumbers: data.tracknumbers,
+ images: data.images,
+ artists: data.artists
+ };
+
+ _.each( attachments, function (attachment) {
+ var size = {}, track = {
+ src : attachment.url,
+ type : attachment.mime,
+ title : attachment.title,
+ caption : attachment.caption,
+ description : attachment.description,
+ meta : attachment.meta
+ };
+
+ if ( 'video' === type ) {
+ if ( ! options.width ) {
+ options.width = attachment.width;
+ options.height = attachment.height;
+ }
+ size.width = attachment.width;
+ size.height = attachment.height;
+ track.dimensions = {
+ original : size,
+ resized : size
+ };
+ } else {
+ options.width = 400;
+ }
+
+ track.image = attachment.image;
+ track.thumb = attachment.thumb;
+
+ tracks.push( track );
+ } );
+
+ options.tracks = tracks;
+ this.data = options;
+
+ return this.template( options );
+ }
+ });
+ _.extend( wp.mce.media.PlaylistView.prototype, wp.media.mixin );
+
+ wp.mce.playlist = _.extend( {}, wp.mce.media, {
+ shortcode: 'playlist',
+ state: 'playlist-edit',
+ View: wp.mce.media.PlaylistView
+ } );
+
+ wp.mce.views.register( 'playlist', wp.mce.playlist );
+
+ wp.mce['video-playlist'] = _.extend( {}, wp.mce.media, {
+ shortcode: 'video-playlist',
+ state: 'video-playlist-edit',
+ View: wp.mce.media.PlaylistView
+ } );
+
+ wp.mce.views.register( 'video-playlist', wp.mce['video-playlist'] );
+
function init() {
$(document.body)
.on( 'click', '.wp-switch-editor', wp.media.mixin.pauseAllPlayers )
diff --git a/src/wp-includes/js/media-editor.js b/src/wp-includes/js/media-editor.js
index d0b4308810..f7253b7969 100644
--- a/src/wp-includes/js/media-editor.js
+++ b/src/wp-includes/js/media-editor.js
@@ -198,6 +198,23 @@
}
}
+ if ( ! _.isEmpty( attachment.caption ) ) {
+ shortcode.caption = attachment.caption;
+ } else if ( attachment.meta && attachment.meta.title ) {
+ shortcode.caption = '&#8220;' + attachment.meta.title + '&#8221;';
+ if ( attachment.meta.album ) {
+ shortcode.caption += ' from ' + attachment.meta.album;
+ }
+
+ if ( attachment.meta.artist ) {
+ shortcode.caption += ' by ' + attachment.meta.artist;
+ }
+ } else if ( ! _.isEmpty( attachment.description ) ) {
+ shortcode.caption = attachment.description;
+ } else {
+ shortcode.caption = attachment.title;
+ }
+
extension = attachment.filename.split('.').pop();
if ( _.contains( wp.media.view.settings.embedExts, extension ) ) {
@@ -387,6 +404,7 @@
if ( attachments[this.tag] ) {
_.extend( attrs, attachments[this.tag].toJSON() );
}
+
// Convert all gallery shortcodes to use the `ids` property.
// Ignore `post__in` and `post__not_in`; the attachments in
// the collection will already reflect those properties.
diff --git a/src/wp-includes/js/mediaelement/wp-playlist.js b/src/wp-includes/js/mediaelement/wp-playlist.js
index 6c19e1da5f..bfe75c2bb0 100644
--- a/src/wp-includes/js/mediaelement/wp-playlist.js
+++ b/src/wp-includes/js/mediaelement/wp-playlist.js
@@ -8,10 +8,10 @@
itemTemplate : wp.template('wp-playlist-item'),
- initialize : function () {
+ initialize : function (options) {
var settings = {};
- this.data = $.parseJSON( this.$('script').html() );
+ this.data = options.metadata || $.parseJSON( this.$('script').html() );
this.playerNode = this.$( this.data.type );
this.tracks = new Backbone.Collection( this.data.tracks );
@@ -38,7 +38,7 @@
}
settings.success = this.bindPlayer;
- new MediaElementPlayer( this.playerNode.get(0), settings );
+ this._player = new MediaElementPlayer( this.playerNode.get(0), settings );
},
renderCurrent : function () {
@@ -132,9 +132,13 @@
});
$(document).ready(function () {
- $('.wp-playlist').each(function () {
- return new WPPlaylistView({ el: this });
- });
+ if ( ! $( 'body' ).hasClass('wp-admin') ) {
+ $('.wp-playlist').each(function () {
+ return new WPPlaylistView({ el: this });
+ });
+ }
});
+ window.WPPlaylistView = WPPlaylistView;
+
}(jQuery, _, Backbone)); \ No newline at end of file
diff --git a/src/wp-includes/js/tinymce/plugins/wpgallery/plugin.js b/src/wp-includes/js/tinymce/plugins/wpgallery/plugin.js
index 2f0912873b..7f82e3575f 100644
--- a/src/wp-includes/js/tinymce/plugins/wpgallery/plugin.js
+++ b/src/wp-includes/js/tinymce/plugins/wpgallery/plugin.js
@@ -13,28 +13,6 @@ tinymce.PluginManager.add('wpgallery', function( editor ) {
'data-wp-media="' + data + '" data-mce-resize="false" data-mce-placeholder="1" />';
}
- function replaceCallback( match, type, close ) {
- var index;
-
- if ( close && close.indexOf( '[' + type ) > -1 ) {
- index = match.length - close.length;
- return html( 'wp-' + type, match.substring( 0, index ) ) + match.substring( index );
- }
-
- return html( 'wp-' + type, match );
- }
-
- function replaceAVShortcodes( content ) {
- var testRegex = /\[(video-playlist|playlist)[^\]]*\]/,
- replaceRegex = /\[(video-playlist|playlist)[^\]]*\]([\s\S]*?\[\/\1\])?/;
-
- while ( testRegex.test( content ) ) {
- content = content.replace( replaceRegex, replaceCallback );
- }
-
- return content;
- }
-
function restoreMediaShortcodes( content ) {
function getAttr( str, name ) {
name = new RegExp( name + '=\"([^\"]+)\"' ).exec( str );
@@ -76,25 +54,6 @@ tinymce.PluginManager.add('wpgallery', function( editor ) {
editor.dom.setAttrib( node, 'data-wp-media', window.encodeURIComponent( shortcode ) );
frame.detach();
});
- } else if ( editor.dom.hasClass( node, 'wp-playlist' ) && wp.media.playlist ) {
- frame = wp.media.playlist.edit( data );
-
- frame.state('playlist-edit').on( 'update', function( selection ) {
- var shortcode = wp.media.playlist.shortcode( selection ).string();
- editor.dom.setAttrib( node, 'data-wp-media', window.encodeURIComponent( shortcode ) );
- frame.detach();
- });
- } else if ( editor.dom.hasClass( node, 'wp-video-playlist' ) && wp.media['video-playlist'] ) {
- frame = wp.media['video-playlist'].edit( data );
-
- frame.state('video-playlist-edit').on( 'update', function( selection ) {
- var shortcode = wp.media['video-playlist'].shortcode( selection ).string();
- editor.dom.setAttrib( node, 'data-wp-media', window.encodeURIComponent( shortcode ) );
- frame.detach();
- });
- } else {
- // temp
- window.console && window.console.log( 'Edit AV shortcode ' + data );
}
}
@@ -152,10 +111,6 @@ tinymce.PluginManager.add('wpgallery', function( editor ) {
if ( node.nodeName === 'IMG' && dom.getAttrib( node, 'data-wp-media' ) ) {
if ( dom.hasClass( node, 'wp-gallery' ) ) {
event.name = 'gallery';
- } else if ( dom.hasClass( node, 'wp-playlist' ) ) {
- event.name = 'playlist';
- } else if ( dom.hasClass( node, 'wp-video-playlist' ) ) {
- event.name = 'video-playlist';
}
}
});
@@ -165,8 +120,6 @@ tinymce.PluginManager.add('wpgallery', function( editor ) {
if ( ! editor.plugins.wpview ) {
event.content = replaceGalleryShortcodes( event.content );
}
-
- event.content = replaceAVShortcodes( event.content );
});
editor.on( 'PostProcess', function( event ) {
diff --git a/src/wp-includes/js/tinymce/skins/wordpress/wp-content.css b/src/wp-includes/js/tinymce/skins/wordpress/wp-content.css
index 6ee1e2f931..f758542193 100644
--- a/src/wp-includes/js/tinymce/skins/wordpress/wp-content.css
+++ b/src/wp-includes/js/tinymce/skins/wordpress/wp-content.css
@@ -141,14 +141,6 @@ img::selection {
background-image: url(images/gallery.png);
}
-.mce-content-body img.wp-media.wp-playlist {
- background-image: url("images/playlist-audio.png");
-}
-
-.mce-content-body img.wp-media.wp-video-playlist {
- background-image: url("images/playlist-video.png");
-}
-
/* Image resize handles */
.mce-content-body div.mce-resizehandle {
border-color: #777;
@@ -299,6 +291,16 @@ embed {
border-color: rgba(0,0,0,0.3);
}
+.wpview-type-audio .track-details {
+ position: absolute;
+ top: 0;
+ left: 5px;
+ width: 85%;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+}
+
.gallery img[data-mce-selected]:focus {
outline: none;
}
diff --git a/src/wp-includes/media-template.php b/src/wp-includes/media-template.php
index 9f72f176f6..add9940006 100644
--- a/src/wp-includes/media-template.php
+++ b/src/wp-includes/media-template.php
@@ -814,7 +814,7 @@ function wp_print_media_templates() {
<div class="setting preload">
<span><?php _e( 'Preload' ); ?></span>
<div class="button-group button-large" data-setting="preload">
- <button class="button" value="auto"><?php _ex( 'Auto', 'auto preload video' ); ?></button>
+ <button class="button" value="auto"><?php _ex( 'Auto', 'auto preload audio' ); ?></button>
<button class="button" value="metadata"><?php _e( 'Metadata' ); ?></button>
<button class="button active" value="none"><?php _e( 'None' ); ?></button>
</div>
@@ -829,6 +829,12 @@ function wp_print_media_templates() {
<span><?php _e( 'Loop' ); ?></span>
<input type="checkbox" data-setting="loop" />
</label>
+
+ <label class="setting">
+ <span><?php _e( 'Caption' ); ?></span>
+ <input type="text" data-setting="caption" value="{{ data.model.caption }}" />
+ </label>
+
<div class="clear"></div>
</div>
</div>
@@ -901,7 +907,7 @@ function wp_print_media_templates() {
<div class="setting preload">
<span><?php _e( 'Preload' ); ?></span>
<div class="button-group button-large" data-setting="preload">
- <button class="button" value="auto"><?php _e( 'Auto' ); ?></button>
+ <button class="button" value="auto"><?php _ex( 'Auto', 'auto preload video' ); ?></button>
<button class="button" value="metadata"><?php _e( 'Metadata' ); ?></button>
<button class="button active" value="none"><?php _e( 'None' ); ?></button>
</div>
@@ -936,6 +942,11 @@ function wp_print_media_templates() {
<# } #>
<textarea class="hidden content-setting">{{ content }}</textarea>
</label>
+
+ <label class="setting">
+ <span><?php _e( 'Caption' ); ?></span>
+ <input type="text" data-setting="caption" value="{{ data.model.caption }}" />
+ </label>
</div>
</div>
</script>
@@ -966,6 +977,9 @@ function wp_print_media_templates() {
<div class="dashicons dashicons-edit edit"></div>
<div class="dashicons dashicons-no-alt remove"></div>
</div>
+ <# if ( ! _.isEmpty( data.model.caption ) ) { #>
+ <div class="track-details">{{{ data.model.caption }}}</div>
+ <# } #>
<?php wp_underscore_audio_template() ?>
</script>
@@ -974,9 +988,31 @@ function wp_print_media_templates() {
<div class="dashicons dashicons-edit edit"></div>
<div class="dashicons dashicons-no-alt remove"></div>
</div>
+ <# if ( ! _.isEmpty( data.model.caption ) ) { #>
+ <div class="track-details">{{{ data.model.caption }}}</div>
+ <# } #>
<?php wp_underscore_video_template() ?>
</script>
+ <?php wp_underscore_playlist_templates() ?>
+
+ <script type="text/html" id="tmpl-editor-playlist">
+ <div class="toolbar">
+ <div class="dashicons dashicons-edit edit"></div>
+ <div class="dashicons dashicons-no-alt remove"></div>
+ </div>
+ <div class="wp-playlist wp-{{ data.type }}-playlist wp-playlist-{{ data.style }}">
+ <# if ( 'audio' === data.type ){ #>
+ <div class="wp-playlist-current-item"></div>
+ <# } #>
+ <{{ data.type }} controls="controls" preload="none" <#
+ if ( data.width ) { #> width="{{ data.width }}"<# }
+ #><# if ( data.height ) { #> height="{{ data.height }}"<# } #>></{{ data.type }}>
+ <div class="wp-playlist-next"></div>
+ <div class="wp-playlist-prev"></div>
+ </div>
+ </script>
+
<?php
/**
diff --git a/src/wp-includes/media.php b/src/wp-includes/media.php
index a1afae1698..a7eea4e996 100644
--- a/src/wp-includes/media.php
+++ b/src/wp-includes/media.php
@@ -999,17 +999,12 @@ function gallery_shortcode( $attr ) {
}
/**
- * Output and enqueue default scripts and styles for playlists.
+ * Output the templates used by playlists
*
* @since 3.9.0
- *
- * @param string $type Type of playlist: "audio" or "video."
*/
-function wp_playlist_scripts( $type ) {
- wp_enqueue_style( 'wp-mediaelement' );
- wp_enqueue_script( 'wp-playlist' );
+function wp_underscore_playlist_templates() {
?>
-<!--[if lt IE 9]><script>document.createElement('<?php echo esc_js( $type ) ?>');</script><![endif]-->
<script type="text/html" id="tmpl-wp-playlist-current-item">
<# if ( data.image ) { #>
<img src="{{{ data.thumb.src }}}"/>
@@ -1045,6 +1040,22 @@ function wp_playlist_scripts( $type ) {
</script>
<?php
}
+
+/**
+ * Output and enqueue default scripts and styles for playlists.
+ *
+ * @since 3.9.0
+ *
+ * @param string $type Type of playlist: "audio" or "video."
+ */
+function wp_playlist_scripts( $type ) {
+ wp_enqueue_style( 'wp-mediaelement' );
+ wp_enqueue_script( 'wp-playlist' );
+?>
+<!--[if lt IE 9]><script>document.createElement('<?php echo esc_js( $type ) ?>');</script><![endif]-->
+<?php
+ wp_underscore_playlist_templates();
+}
add_action( 'wp_playlist_scripts', 'wp_playlist_scripts' );
/**
@@ -1390,6 +1401,7 @@ function wp_audio_shortcode( $attr, $content = '' ) {
$default_types = wp_get_audio_extensions();
$defaults_atts = array(
+ 'caption' => '',
'src' => '',
'loop' => '',
'autoplay' => '',
@@ -1549,6 +1561,7 @@ function wp_video_shortcode( $attr, $content = '' ) {
$default_types = wp_get_video_extensions();
$defaults_atts = array(
+ 'caption' => '',
'src' => '',
'poster' => '',
'loop' => '',
@@ -2332,6 +2345,22 @@ function wp_prepare_attachment_for_js( $attachment ) {
if ( $meta && ( 'audio' === $type || 'video' === $type ) ) {
if ( isset( $meta['length_formatted'] ) )
$response['fileLength'] = $meta['length_formatted'];
+
+ $response['meta'] = array();
+ $keys = array( 'title', 'artist', 'band', 'album', 'genre', 'year', 'length', 'length_formatted' );
+ foreach ( $keys as $key ) {
+ if ( ! empty( $meta[ $key ] ) ) {
+ $response['meta'][ $key ] = $meta[ $key ];
+ }
+ }
+
+ $id = get_post_thumbnail_id( $attachment->ID );
+ if ( ! empty( $id ) ) {
+ list( $src, $width, $height ) = wp_get_attachment_image_src( $id, 'full' );
+ $response['image'] = compact( 'src', 'width', 'height' );
+ list( $src, $width, $height ) = wp_get_attachment_image_src( $id, 'thumbnail' );
+ $response['thumb'] = compact( 'src', 'width', 'height' );
+ }
}
if ( function_exists('get_compat_media_markup') )
diff --git a/src/wp-includes/script-loader.php b/src/wp-includes/script-loader.php
index ff2544ab59..77121f4f87 100644
--- a/src/wp-includes/script-loader.php
+++ b/src/wp-includes/script-loader.php
@@ -396,7 +396,7 @@ function wp_default_scripts( &$scripts ) {
// Both rely on numerous settings, styles, and templates to operate correctly.
$scripts->add( 'media-views', "/wp-includes/js/media-views$suffix.js", array( 'utils', 'media-models', 'wp-plupload', 'jquery-ui-sortable', 'wp-mediaelement' ), false, 1 );
$scripts->add( 'media-editor', "/wp-includes/js/media-editor$suffix.js", array( 'shortcode', 'media-views' ), false, 1 );
- $scripts->add( 'media-audiovideo', "/wp-includes/js/media-audiovideo$suffix.js", array( 'media-editor', 'mce-view' ), false, 1 );
+ $scripts->add( 'media-audiovideo', "/wp-includes/js/media-audiovideo$suffix.js", array( 'media-editor', 'mce-view', 'wp-playlist' ), false, 1 );
$scripts->add( 'mce-view', "/wp-includes/js/mce-view$suffix.js", array( 'shortcode', 'media-models' ), false, 1 );
if ( is_admin() ) {