TinyMCE wpViews:

- Prevent undo steps from being added when the body of a wpview changes.
- Add unbind() to handle cleanup on DOM rebuilding in TinyMCE.
- Ensure that MediaElement's cleanup routine is run on every player in all instances of the editor.
- Initialize the players after some delay to ensure CSS is loaded.
Props gcorne and wonderboymusic, fixes #27389
Built from https://develop.svn.wordpress.org/trunk@28084


git-svn-id: http://core.svn.wordpress.org/trunk@27915 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
Andrew Ozz 2014-04-12 00:46:14 +00:00
parent 5e51ea9940
commit 191dd168c1
7 changed files with 60 additions and 24 deletions

View File

@ -41,12 +41,15 @@ window.wp = window.wp || {};
doc = editor.getDoc();
$( doc ).find( '[data-wpview-text="' + this.encodedText + '"]' ).each(function (i, elem) {
var node = $( elem );
node.html( html );
// The <ins> is used to mark the end of the wrapper div. Needed when comparing
// the content as string for preventing extra undo levels.
node.html( html ).append( '<ins data-wpview-end="1"></ins>' );
$( self ).trigger( 'ready', elem );
});
}
}, this );
}
},
unbind: function() {}
} );
// take advantage of the Backbone extend method
@ -92,6 +95,17 @@ window.wp = window.wp || {};
delete views[ type ];
},
/**
* wp.mce.views.unbind( editor )
*
* The editor DOM is being rebuilt, run cleanup.
*/
unbind: function() {
_.each( instances, function( instance ) {
instance.unbind();
} );
},
/**
* toViews( content )
* Scans a `content` string for each view's pattern, replacing any
@ -339,6 +353,7 @@ window.wp = window.wp || {};
* @mixin
*/
wp.mce.media = {
loaded: false,
/**
* @global wp.shortcode
*
@ -410,6 +425,7 @@ window.wp = window.wp || {};
*/
wp.mce.media.View = wp.mce.View.extend({
initialize: function( options ) {
this.players = [];
this.shortcode = options.shortcode;
_.bindAll( this, 'setPlayer' );
$(this).on( 'ready', this.setPlayer );
@ -460,8 +476,9 @@ window.wp = window.wp || {};
media = wp.media.view.MediaDetails.prepareSrc( media.get(0) );
setTimeout( function() {
self.player = new MediaElementPlayer( media, this.mejsSettings );
}, 75 );
wp.mce.media.loaded = true;
self.players.push( new MediaElementPlayer( media, self.mejsSettings ) );
}, wp.mce.media.loaded ? 10 : 500 );
},
/**
@ -475,6 +492,15 @@ window.wp = window.wp || {};
wp.media[ this.shortcode.tag ].defaults
);
return this.template({ model: attrs });
},
unbind: function() {
var self = this;
this.pauseAllPlayers();
_.each( this.players, function (player) {
self.removePlayer( player );
} );
this.players = [];
}
});
_.extend( wp.mce.media.View.prototype, wp.media.mixin );

File diff suppressed because one or more lines are too long

View File

@ -128,8 +128,8 @@
* MediaElement tries to pull the audio/video tag out of
* its container and re-add it to the DOM.
*/
removePlayer: function() {
var t = this.player, featureIndex, feature;
removePlayer: function(t) {
var featureIndex, feature;
// invoke features cleanup
for ( featureIndex in t.options.features ) {
@ -165,7 +165,7 @@
unsetPlayer : function() {
if ( this.player ) {
wp.media.mixin.pauseAllPlayers();
wp.media.mixin.removePlayer.apply( this );
wp.media.mixin.removePlayer( this.player );
this.player = false;
}
}
@ -914,4 +914,4 @@
$( init );
}(jQuery, _, Backbone));
}(jQuery, _, Backbone));

File diff suppressed because one or more lines are too long

View File

@ -80,11 +80,12 @@ tinymce.PluginManager.add( 'wpview', function( editor ) {
'contenteditable': 'true'
}, getViewText( viewNode ) );
viewNode.appendChild( clipboard );
// Prepend inside the wrapper
viewNode.insertBefore( clipboard, viewNode.firstChild );
// Both of the following are necessary to prevent manipulating the selection/focus
editor.dom.bind( clipboard, 'beforedeactivate focusin focusout', _stop );
editor.dom.bind( selected, 'beforedeactivate focusin focusout', _stop );
dom.bind( clipboard, 'beforedeactivate focusin focusout', _stop );
dom.bind( selected, 'beforedeactivate focusin focusout', _stop );
// Make sure that the editor is focused.
// It is possible that the editor is not focused when the mouse event fires
@ -140,8 +141,14 @@ tinymce.PluginManager.add( 'wpview', function( editor ) {
return;
}
// Remove the content of view wrappers from HTML string
function emptyViews( content ) {
return content.replace(/(<div[^>]+wpview-wrap[^>]+>)[\s\S]+?data-wpview-end[^>]*><\/ins><\/div>/g, '$1</div>' );
}
// Prevent adding undo levels on changes inside a view wrapper
editor.on( 'BeforeAddUndo', function( event ) {
if ( selected && ! toRemove ) {
if ( event.lastLevel && emptyViews( event.level.content ) === emptyViews( event.lastLevel.content ) ) {
event.preventDefault();
}
});
@ -149,12 +156,16 @@ tinymce.PluginManager.add( 'wpview', function( editor ) {
// When the editor's content changes, scan the new content for
// matching view patterns, and transform the matches into
// view wrappers.
editor.on( 'BeforeSetContent', function( e ) {
if ( ! e.content ) {
editor.on( 'BeforeSetContent', function( event ) {
if ( ! event.content ) {
return;
}
e.content = wp.mce.views.toViews( e.content );
if ( ! event.initial ) {
wp.mce.views.unbind( editor );
}
event.content = wp.mce.views.toViews( event.content );
});
// When the editor's content has been updated and the DOM has been
@ -162,11 +173,7 @@ tinymce.PluginManager.add( 'wpview', function( editor ) {
editor.on( 'SetContent', function( event ) {
var body, padNode;
// don't (re-)render views if the format of the content is raw
// to avoid adding additional undo levels on undo/redo
if ( event.format !== 'raw' ) {
wp.mce.views.render();
}
wp.mce.views.render();
// Add padding <p> if the noneditable node is last
if ( event.load || ! event.set ) {
@ -175,7 +182,10 @@ tinymce.PluginManager.add( 'wpview', function( editor ) {
if ( isView( body.lastChild ) ) {
padNode = createPadNode();
body.appendChild( padNode );
editor.selection.setCursorLocation( padNode, 0 );
if ( ! event.initial ) {
editor.selection.setCursorLocation( padNode, 0 );
}
}
}
});

File diff suppressed because one or more lines are too long