Add MCE views for audio and video shortcodes. When the shortcode does not contain a source that supports native playback, just show the filename.

* Remove the audio/video shortcode parsing from the `wpgallery` plugin.
* Make `mce-view` a dependency of `media-audiovideo`
* Introduce `wp.mce.video`, `wp.mce.audio`, `wp.mce.media`, and `wp.mce.media.View`
* Rename `wp.media.audio|video.shortcode()` to `wp.media.audio|video.update()` since it is called on Update and returns a `wp.shortcode` object now.
* In `wp.mce.View.render()`, fire a `ready` event when the placeholder is being parsed and pass the current node to the event handler.

See #27389, #27437.



git-svn-id: https://develop.svn.wordpress.org/trunk@27615 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Scott Taylor 2014-03-19 07:01:56 +00:00
parent bd71f66240
commit ce1c3140ab
6 changed files with 221 additions and 76 deletions

View File

@ -31,10 +31,14 @@ window.wp = window.wp || {};
var html = this.getHtml(); var html = this.getHtml();
// Search all tinymce editor instances and update the placeholders // Search all tinymce editor instances and update the placeholders
_.each( tinymce.editors, function( editor ) { _.each( tinymce.editors, function( editor ) {
var doc; var doc, self = this;
if ( editor.plugins.wpview ) { if ( editor.plugins.wpview ) {
doc = editor.getDoc(); doc = editor.getDoc();
$( doc ).find( '[data-wpview-text="' + this.encodedText + '"]' ).html( html ); $( doc ).find( '[data-wpview-text="' + this.encodedText + '"]' ).each(function (i, elem) {
var node = $( elem );
node.html( html );
$( self ).trigger( 'ready', elem );
});
} }
}, this ); }, this );
} }
@ -178,7 +182,7 @@ window.wp = window.wp || {};
/** /**
* Refresh views after an update is made * Refresh views after an update is made
* *
* @param view {object} being refreshed * @param view {object} being refreshed
* @param text {string} textual representation of the view * @param text {string} textual representation of the view
*/ */
@ -204,9 +208,9 @@ window.wp = window.wp || {};
return instances[ encodedText ]; return instances[ encodedText ];
}, },
/** /**
* render( scope ) * render( scope )
* *
* Renders any view instances inside a DOM node `scope`. * Renders any view instances inside a DOM node `scope`.
* *
* View instances are detected by the presence of wrapper elements. * View instances are detected by the presence of wrapper elements.

View File

@ -1,4 +1,4 @@
/* global _wpMediaViewsL10n */ /* global _wpMediaViewsL10n, _wpmejsSettings, MediaElementPlayer */
(function ($, _, Backbone) { (function ($, _, Backbone) {
var media = wp.media, l10n = typeof _wpMediaViewsL10n === 'undefined' ? {} : _wpMediaViewsL10n; var media = wp.media, l10n = typeof _wpMediaViewsL10n === 'undefined' ? {} : _wpMediaViewsL10n;
@ -61,7 +61,7 @@
video: ['ogg', 'webm'] video: ['ogg', 'webm']
}, },
'chrome' : { 'chrome' : {
audio: ['ogg', 'mpeg', 'x-ms-wma'], audio: ['ogg', 'mpeg'],
video: ['ogg', 'webm', 'mp4', 'm4v', 'mpeg'] video: ['ogg', 'webm', 'mp4', 'm4v', 'mpeg']
}, },
'ff' : { 'ff' : {
@ -227,20 +227,24 @@
return frame; return frame;
}, },
shortcode : function (shortcode) { update : function (model) {
var self = this; var self = this, content;
_.each( wp.media.audio.defaults, function( value, key ) { _.each( this.defaults, function( value, key ) {
shortcode[ key ] = self.coerce( shortcode, key ); model[ key ] = self.coerce( model, key );
if ( value === shortcode[ key ] ) { if ( value === model[ key ] ) {
delete shortcode[ key ]; delete model[ key ];
} }
}); });
return wp.shortcode.string({ content = model.content;
tag: 'audio', delete model.content;
attrs: shortcode
return new wp.shortcode({
tag: 'audio',
attrs: model,
content: content
}); });
} }
}; };
@ -283,21 +287,23 @@
return frame; return frame;
}, },
shortcode : function (shortcode) { update : function (model) {
var self = this, content = shortcode.content; var self = this, content;
delete shortcode.content;
_.each( this.defaults, function( value, key ) { _.each( this.defaults, function( value, key ) {
shortcode[ key ] = self.coerce( shortcode, key ); model[ key ] = self.coerce( model, key );
if ( value === shortcode[ key ] ) { if ( value === model[ key ] ) {
delete shortcode[ key ]; delete model[ key ];
} }
}); });
return wp.shortcode.string({ content = model.content;
tag: 'video', delete model.content;
attrs: shortcode,
return new wp.shortcode({
tag: 'video',
attrs: model,
content: content content: content
}); });
} }
@ -972,6 +978,125 @@
} }
} ); } );
wp.mce.media = {
toView: function( content ) {
var match = wp.shortcode.next( this.shortcode, content );
if ( ! match ) {
return;
}
return {
index: match.index,
content: match.content,
options: {
shortcode: match.shortcode
}
};
},
edit: function( node ) {
var p,
media = wp.media[ this.shortcode ],
self = this,
frame, data;
wp.media.mixin.pauseAllPlayers();
data = window.decodeURIComponent( $( node ).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();
$( node ).attr( 'data-wpview-text', window.encodeURIComponent( shortcode ) );
wp.mce.views.refreshView( self, shortcode );
frame.detach();
} );
frame.open();
}
};
wp.mce.media.View = wp.mce.View.extend({
initialize: function( options ) {
this.shortcode = options.shortcode;
_.bindAll( this, 'setPlayer' );
$(this).on( 'ready', this.setPlayer );
},
setPlayer: function (e, node) {
// if the ready event fires on an empty node
if ( ! node ) {
return;
}
var self = this,
media,
settings = {},
className = '.wp-' + this.shortcode.tag + '-shortcode';
if ( this.player ) {
this.unsetPlayer();
}
media = $( node ).find( className );
if ( ! _.isUndefined( window._wpmejsSettings ) ) {
settings.pluginPath = _wpmejsSettings.pluginPath;
}
if ( ! this.isCompatible( media ) ) {
media.closest( '.wpview-wrap' ).addClass( 'wont-play' );
if ( ! media.parent().hasClass( 'wpview-wrap' ) ) {
media.parent().replaceWith( media );
}
media.replaceWith( '<p>' + media.find( 'source' ).eq(0).prop( 'src' ) + '</p>' );
return;
} else {
media.closest( '.wpview-wrap' ).removeClass( 'wont-play' );
if ( this.ua.is( 'ff' ) ) {
media.prop( 'preload', 'metadata' );
} else {
media.prop( 'preload', 'none' );
}
}
media = wp.media.view.MediaDetails.prepareSrc( media.get(0) );
// Thanks, Firefox!
setTimeout(function () {
self.player = new MediaElementPlayer( media, settings );
}, 50);
},
getHtml: function() {
var attrs = this.shortcode.attrs.named;
return this.template({ model: attrs });
}
});
_.extend( wp.mce.media.View.prototype, wp.media.mixin );
wp.mce.video = _.extend( {}, wp.mce.media, {
shortcode: 'video',
View: wp.mce.media.View.extend({
className: 'editor-video',
template: media.template('editor-video')
})
} );
wp.mce.views.register( 'video', wp.mce.video );
wp.mce.audio = _.extend( {}, wp.mce.media, {
shortcode: 'audio',
View: wp.mce.media.View.extend({
className: 'editor-audio',
template: media.template('editor-audio')
})
} );
wp.mce.views.register( 'audio', wp.mce.audio );
function init() { function init() {
$(document.body) $(document.body)
.on( 'click', '.wp-switch-editor', wp.media.mixin.pauseAllPlayers ) .on( 'click', '.wp-switch-editor', wp.media.mixin.pauseAllPlayers )

View File

@ -25,8 +25,8 @@ tinymce.PluginManager.add('wpgallery', function( editor ) {
} }
function replaceAVShortcodes( content ) { function replaceAVShortcodes( content ) {
var testRegex = /\[(video-playlist|audio|video|playlist)[^\]]*\]/, var testRegex = /\[(video-playlist|playlist)[^\]]*\]/,
replaceRegex = /\[(video-playlist|audio|video|playlist)[^\]]*\]([\s\S]*?\[\/\1\])?/; replaceRegex = /\[(video-playlist|playlist)[^\]]*\]([\s\S]*?\[\/\1\])?/;
while ( testRegex.test( content ) ) { while ( testRegex.test( content ) ) {
content = content.replace( replaceRegex, replaceCallback ); content = content.replace( replaceRegex, replaceCallback );
@ -92,31 +92,6 @@ tinymce.PluginManager.add('wpgallery', function( editor ) {
editor.dom.setAttrib( node, 'data-wp-media', window.encodeURIComponent( shortcode ) ); editor.dom.setAttrib( node, 'data-wp-media', window.encodeURIComponent( shortcode ) );
frame.detach(); frame.detach();
}); });
} else if ( editor.dom.hasClass( node, 'wp-video' ) ) {
frame = wp.media.video.edit( data );
frame.on( 'close', function () {
frame.detach();
} );
frame.state( 'video-details' ).on(
'update replace add-source select-poster-image add-track',
function ( selection ) {
var shortcode = wp.media.video.shortcode( selection );
editor.dom.setAttrib( node, 'data-wp-media', window.encodeURIComponent( shortcode ) );
frame.detach();
}
);
frame.open();
} else if ( editor.dom.hasClass( node, 'wp-audio' ) ) {
frame = wp.media.audio.edit( data );
frame.on( 'close', function () {
frame.detach();
} );
frame.state( 'audio-details' ).on( 'update replace add-source', function ( selection ) {
var shortcode = wp.media.audio.shortcode( selection );
editor.dom.setAttrib( node, 'data-wp-media', window.encodeURIComponent( shortcode ) );
frame.detach();
} );
frame.open();
} else { } else {
// temp // temp
window.console && window.console.log( 'Edit AV shortcode ' + data ); window.console && window.console.log( 'Edit AV shortcode ' + data );
@ -177,10 +152,6 @@ tinymce.PluginManager.add('wpgallery', function( editor ) {
if ( node.nodeName === 'IMG' && dom.getAttrib( node, 'data-wp-media' ) ) { if ( node.nodeName === 'IMG' && dom.getAttrib( node, 'data-wp-media' ) ) {
if ( dom.hasClass( node, 'wp-gallery' ) ) { if ( dom.hasClass( node, 'wp-gallery' ) ) {
event.name = 'gallery'; event.name = 'gallery';
} else if ( dom.hasClass( node, 'wp-video' ) ) {
event.name = 'video';
} else if ( dom.hasClass( node, 'wp-audio' ) ) {
event.name = 'audio';
} else if ( dom.hasClass( node, 'wp-playlist' ) ) { } else if ( dom.hasClass( node, 'wp-playlist' ) ) {
event.name = 'playlist'; event.name = 'playlist';
} else if ( dom.hasClass( node, 'wp-video-playlist' ) ) { } else if ( dom.hasClass( node, 'wp-video-playlist' ) ) {

View File

@ -141,15 +141,6 @@ img::selection {
background-image: url(images/gallery.png); background-image: url(images/gallery.png);
} }
.mce-content-body img.wp-media.wp-video {
background-image: url(images/video.png);
}
.mce-content-body img.wp-media.wp-audio {
height: 70px;
background-image: url(images/audio.png);
}
.mce-content-body img.wp-media.wp-playlist { .mce-content-body img.wp-media.wp-playlist {
background-image: url("images/playlist-audio.png"); background-image: url("images/playlist-audio.png");
} }
@ -223,44 +214,81 @@ embed {
} }
/** /**
* Gallery preview * Media previews
*/ */
.wpview-type-gallery { .wpview-type-gallery,
.wpview-type-audio,
.wpview-type-video {
position: relative; position: relative;
margin-bottom: 16px; margin-bottom: 16px;
cursor: pointer; cursor: pointer;
border: 1px solid transparent; border: 1px solid transparent;
} }
.wpview-type-gallery:after { .wpview-type-audio {
padding: 24px 0 0;
}
.wpview-type-video {
padding: 0;
}
.wont-play {
padding: 4px 0;
}
.wont-play p {
font-size: 13px;
line-height: 1.3;
display: block;
width: 70%;
margin: 0 15%;
text-align: center;
}
.wpview-type-gallery:after {
content: ''; content: '';
display: table; display: table;
clear: both; clear: both;
} }
.wpview-type-gallery.selected { .wpview-type-gallery.selected,
.wpview-type-audio,
.wpview-type-video {
background-color: #f2f8ff; background-color: #f2f8ff;
border-color: #777; border-color: #777;
} }
.wpview-type-gallery .toolbar { .wpview-type-gallery .toolbar,
position: absolute; .wpview-type-audio .toolbar,
top: 0; .wpview-type-video .toolbar {
right: 0; position: absolute;
background-color: #333; top: 0;
color: white; right: 0;
background-color: #333;
color: white;
display: none; display: none;
z-index: 100;
} }
.wpview-type-video .toolbar div,
.wpview-type-gallery .toolbar div, .wpview-type-gallery .toolbar div,
#wp-image-toolbar div { #wp-image-toolbar div {
margin: 5px; margin: 5px;
} }
.wpview-type-audio .toolbar div {
margin: 2px 5px;
}
.wpview-type-audio .toolbar,
.wpview-type-video .toolbar,
.wpview-type-gallery.selected .toolbar { .wpview-type-gallery.selected .toolbar {
display: block; display: block;
} }
.wpview-type-audio .toolbar span,
.wpview-type-video .toolbar span,
.wpview-type-gallery .toolbar span { .wpview-type-gallery .toolbar span {
cursor: pointer; cursor: pointer;
} }

View File

@ -961,6 +961,23 @@ function wp_print_media_templates() {
<# } ); #> <# } ); #>
</div> </div>
</script> </script>
<script type="text/html" id="tmpl-editor-audio">
<div class="toolbar">
<div class="dashicons dashicons-format-audio edit"></div>
<div class="dashicons dashicons-no-alt remove"></div>
</div>
<?php wp_underscore_audio_template() ?>
</script>
<script type="text/html" id="tmpl-editor-video">
<div class="toolbar">
<div class="dashicons dashicons-format-video edit"></div>
<div class="dashicons dashicons-no-alt remove"></div>
</div>
<?php wp_underscore_video_template() ?>
</script>
<?php <?php
/** /**

View File

@ -396,7 +396,7 @@ function wp_default_scripts( &$scripts ) {
// Both rely on numerous settings, styles, and templates to operate correctly. // 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', 'image-edit' ), false, 1 ); $scripts->add( 'media-views', "/wp-includes/js/media-views$suffix.js", array( 'utils', 'media-models', 'wp-plupload', 'jquery-ui-sortable', 'wp-mediaelement', 'image-edit' ), false, 1 );
$scripts->add( 'media-editor', "/wp-includes/js/media-editor$suffix.js", array( 'shortcode', 'media-views' ), 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' ), false, 1 ); $scripts->add( 'media-audiovideo', "/wp-includes/js/media-audiovideo$suffix.js", array( 'media-editor', 'mce-view' ), false, 1 );
$scripts->add( 'mce-view', "/wp-includes/js/mce-view$suffix.js", array( 'shortcode', 'media-models' ), false, 1 ); $scripts->add( 'mce-view', "/wp-includes/js/mce-view$suffix.js", array( 'shortcode', 'media-models' ), false, 1 );
if ( is_admin() ) { if ( is_admin() ) {