wp/wp-includes/js/mce-view.js
changeset 7 cf61fcea0001
parent 5 5e2f62d02dcd
child 9 177826044cd9
--- a/wp/wp-includes/js/mce-view.js	Tue Jun 09 11:14:17 2015 +0000
+++ b/wp/wp-includes/js/mce-view.js	Mon Oct 14 17:39:30 2019 +0200
@@ -1,7 +1,5 @@
 /* global tinymce */
 
-window.wp = window.wp || {};
-
 /*
  * The TinyMCE view API.
  *
@@ -24,7 +22,7 @@
  * |- registered view
  * |  |- ...
  */
-( function( window, wp, $ ) {
+( function( window, wp, shortcode, $ ) {
 	'use strict';
 
 	var views = {},
@@ -87,14 +85,14 @@
 		 * and creates a new instance for every match.
 		 *
 		 * @param {String} content The string to scan.
+		 * @param {tinymce.Editor} editor The editor.
 		 *
 		 * @return {String} The string with markers.
 		 */
-		setMarkers: function( content ) {
+		setMarkers: function( content, editor ) {
 			var pieces = [ { content: content } ],
 				self = this,
-				instance,
-				current;
+				instance, current;
 
 			_.each( views, function( view, type ) {
 				current = pieces.slice();
@@ -102,7 +100,7 @@
 
 				_.each( current, function( piece ) {
 					var remaining = piece.content,
-						result;
+						result, text;
 
 					// Ignore processed pieces, but retain their location.
 					if ( piece.processed ) {
@@ -118,11 +116,13 @@
 							pieces.push( { content: remaining.substring( 0, result.index ) } );
 						}
 
+						result.options.editor = editor;
 						instance = self.createInstance( type, result.content, result.options );
+						text = instance.loader ? '.' : instance.text;
 
 						// Add the processed piece for the match.
 						pieces.push( {
-							content: '<p data-wpview-marker="' + instance.encodedText + '">' + instance.text + '</p>',
+							content: instance.ignore ? text : '<p data-wpview-marker="' + instance.encodedText + '">' + text + '</p>',
 							processed: true
 						} );
 
@@ -138,31 +138,43 @@
 				} );
 			} );
 
-			return _.pluck( pieces, 'content' ).join( '' );
+			content = _.pluck( pieces, 'content' ).join( '' );
+			return content.replace( /<p>\s*<p data-wpview-marker=/g, '<p data-wpview-marker=' ).replace( /<\/p>\s*<\/p>/g, '</p>' );
 		},
 
 		/**
 		 * Create a view instance.
 		 *
-		 * @param {String} type    The view type.
-		 * @param {String} text    The textual representation of the view.
-		 * @param {Object} options Options.
+		 * @param {String}  type    The view type.
+		 * @param {String}  text    The textual representation of the view.
+		 * @param {Object}  options Options.
+		 * @param {Boolean} force   Recreate the instance. Optional.
 		 *
 		 * @return {wp.mce.View} The view instance.
 		 */
-		createInstance: function( type, text, options ) {
+		createInstance: function( type, text, options, force ) {
 			var View = this.get( type ),
 				encodedText,
 				instance;
 
-			text = tinymce.DOM.decode( text ),
-			encodedText = encodeURIComponent( text ),
-			instance = this.getInstance( encodedText );
+			if ( text.indexOf( '[' ) !== -1 && text.indexOf( ']' ) !== -1 ) {
+				// Looks like a shortcode? Remove any line breaks from inside of shortcodes
+				// or autop will replace them with <p> and <br> later and the string won't match.
+				text = text.replace( /\[[^\]]+\]/g, function( match ) {
+					return match.replace( /[\r\n]/g, '' );
+				});
+			}
 
-			if ( instance ) {
-				return instance;
+			if ( ! force ) {
+				instance = this.getInstance( text );
+
+				if ( instance ) {
+					return instance;
+				}
 			}
 
+			encodedText = encodeURIComponent( text );
+
 			options = _.extend( options || {}, {
 				text: text,
 				encodedText: encodedText
@@ -204,7 +216,7 @@
 		 */
 		render: function( force ) {
 			_.each( instances, function( instance ) {
-				instance.render( force );
+				instance.render( null, force );
 			} );
 		},
 
@@ -214,12 +226,13 @@
 		 * @param {String}         text   The new text.
 		 * @param {tinymce.Editor} editor The TinyMCE editor instance the view node is in.
 		 * @param {HTMLElement}    node   The view node to update.
+		 * @param {Boolean}        force  Recreate the instance. Optional.
 		 */
-		update: function( text, editor, node ) {
+		update: function( text, editor, node, force ) {
 			var instance = this.getInstance( node );
 
 			if ( instance ) {
-				instance.update( text, editor, node );
+				instance.update( text, editor, node, force );
 			}
 		},
 
@@ -233,8 +246,8 @@
 			var instance = this.getInstance( node );
 
 			if ( instance && instance.edit ) {
-				instance.edit( instance.text, function( text ) {
-					instance.update( text, editor, node );
+				instance.edit( instance.text, function( text, force ) {
+					instance.update( text, editor, node, force );
 				} );
 			}
 		},
@@ -267,7 +280,7 @@
 
 	wp.mce.View.extend = Backbone.View.extend;
 
-	_.extend( wp.mce.View.prototype, {
+	_.extend( wp.mce.View.prototype, /** @lends wp.mce.View.prototype */{
 
 		/**
 		 * The content.
@@ -289,7 +302,7 @@
 		initialize: function() {},
 
 		/**
-		 * Retuns the content to render in the view node.
+		 * Returns the content to render in the view node.
 		 *
 		 * @return {*}
 		 */
@@ -300,8 +313,8 @@
 		/**
 		 * Renders all view nodes tied to this view instance that are not yet rendered.
 		 *
-		 * @param {String} content The content to render. Optional.
-		 * @param {Boolean} force Rerender all view nodes tied to this view instance.
+		 * @param {String}  content The content to render. Optional.
+		 * @param {Boolean} force   Rerender all view nodes tied to this view instance. Optional.
 		 */
 		render: function( content, force ) {
 			if ( content != null ) {
@@ -322,9 +335,9 @@
 			this.replaceMarkers();
 
 			if ( content ) {
-				this.setContent( content, function( editor, node, contentNode ) {
+				this.setContent( content, function( editor, node ) {
 					$( node ).data( 'rendered', true );
-					this.bindNode.call( this, editor, node, contentNode );
+					this.bindNode.call( this, editor, node );
 				}, force ? null : false );
 			} else {
 				this.setLoader();
@@ -346,9 +359,8 @@
 		 * Runs before their content is removed from the DOM.
 		 */
 		unbind: function() {
-			this.getNodes( function( editor, node, contentNode ) {
-				this.unbindNode.call( this, editor, node, contentNode );
-				$( node ).trigger( 'wp-mce-view-unbind' );
+			this.getNodes( function( editor, node ) {
+				this.unbindNode.call( this, editor, node );
 			}, true );
 		},
 
@@ -389,7 +401,7 @@
 						return rendered ? data : ! data;
 					} )
 					.each( function() {
-						callback.call( self, editor, this, $( this ).find( '.wpview-content' ).get( 0 ) );
+						callback.call( self, editor, this, this /* back compat */ );
 					} );
 			} );
 		},
@@ -416,23 +428,26 @@
 		 */
 		replaceMarkers: function() {
 			this.getMarkers( function( editor, node ) {
-				if ( $( node ).text() !== this.text ) {
+				var selected = node === editor.selection.getNode();
+				var $viewNode;
+
+				if ( ! this.loader && $( node ).text() !== tinymce.DOM.decode( this.text ) ) {
 					editor.dom.setAttrib( node, 'data-wpview-marker', null );
 					return;
 				}
 
-				editor.dom.replace(
-					editor.dom.createFragment(
-						'<div class="wpview-wrap" data-wpview-text="' + this.encodedText + '" data-wpview-type="' + this.type + '">' +
-							'<p class="wpview-selection-before">\u00a0</p>' +
-							'<div class="wpview-body" contenteditable="false">' +
-								'<div class="wpview-content wpview-type-' + this.type + '"></div>' +
-							'</div>' +
-							'<p class="wpview-selection-after">\u00a0</p>' +
-						'</div>'
-					),
-					node
+				$viewNode = editor.$(
+					'<div class="wpview wpview-wrap" data-wpview-text="' + this.encodedText + '" data-wpview-type="' + this.type + '" contenteditable="false"></div>'
 				);
+
+				editor.$( node ).replaceWith( $viewNode );
+
+				if ( selected ) {
+					setTimeout( function() {
+						editor.selection.select( $viewNode[0] );
+						editor.selection.collapse();
+					} );
+				}
 			} );
 		},
 
@@ -453,22 +468,25 @@
 		 * @param {Boolean}  rendered Only set for (un)rendered nodes. Optional.
 		 */
 		setContent: function( content, callback, rendered ) {
-			if ( _.isObject( content ) && content.body.indexOf( '<script' ) !== -1 ) {
+			if ( _.isObject( content ) && ( content.sandbox || content.head || content.body.indexOf( '<script' ) !== -1 ) ) {
 				this.setIframes( content.head || '', content.body, callback, rendered );
 			} else if ( _.isString( content ) && content.indexOf( '<script' ) !== -1 ) {
 				this.setIframes( '', content, callback, rendered );
 			} else {
-				this.getNodes( function( editor, node, contentNode ) {
+				this.getNodes( function( editor, node ) {
 					content = content.body || content;
 
 					if ( content.indexOf( '<iframe' ) !== -1 ) {
-						content += '<div class="wpview-overlay"></div>';
+						content += '<span class="mce-shim"></span>';
 					}
 
-					contentNode.innerHTML = '';
-					contentNode.appendChild( _.isString( content ) ? editor.dom.createFragment( content ) : content );
+					editor.undoManager.transact( function() {
+						node.innerHTML = '';
+						node.appendChild( _.isString( content ) ? editor.dom.createFragment( content ) : content );
+						editor.dom.add( node, 'span', { 'class': 'wpview-end' } );
+					} );
 
-					callback && callback.call( this, editor, node, contentNode );
+					callback && callback.call( this, editor, node );
 				}, rendered );
 			}
 		},
@@ -482,14 +500,22 @@
 		 * @param {Boolean}  rendered Only set for (un)rendered nodes. Optional.
 		 */
 		setIframes: function( head, body, callback, rendered ) {
-			var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver,
-				self = this;
+			var self = this;
 
-			this.getNodes( function( editor, node, contentNode ) {
+			if ( body.indexOf( '[' ) !== -1 && body.indexOf( ']' ) !== -1 ) {
+				var shortcodesRegExp = new RegExp( '\\[\\/?(?:' + window.mceViewL10n.shortcodes.join( '|' ) + ')[^\\]]*?\\]', 'g' );
+				// Escape tags inside shortcode previews.
+				body = body.replace( shortcodesRegExp, function( match ) {
+					return match.replace( /</g, '&lt;' ).replace( />/g, '&gt;' );
+				} );
+			}
+
+			this.getNodes( function( editor, node ) {
 				var dom = editor.dom,
 					styles = '',
 					bodyClasses = editor.getBody().className || '',
-					editorHead = editor.getDoc().getElementsByTagName( 'head' )[0];
+					editorHead = editor.getDoc().getElementsByTagName( 'head' )[0],
+					iframe, iframeWin, iframeDoc, MutationObserver, observer, i, block;
 
 				tinymce.each( dom.$( 'link[rel="stylesheet"]', editorHead ), function( link ) {
 					if ( link.href && link.href.indexOf( 'skins/lightgray/content.min.css' ) === -1 &&
@@ -499,14 +525,21 @@
 					}
 				} );
 
-				// Seems the browsers need a bit of time to insert/set the view nodes,
-				// or the iframe will fail especially when switching Text => Visual.
-				setTimeout( function() {
-					var iframe, iframeDoc, observer, i;
+				if ( self.iframeHeight ) {
+					dom.add( node, 'span', {
+						'data-mce-bogus': 1,
+						style: {
+							display: 'block',
+							width: '100%',
+							height: self.iframeHeight
+						}
+					}, '\u200B' );
+				}
 
-					contentNode.innerHTML = '';
+				editor.undoManager.transact( function() {
+					node.innerHTML = '';
 
-					iframe = dom.add( contentNode, 'iframe', {
+					iframe = dom.add( node, 'iframe', {
 						/* jshint scripturl: true */
 						src: tinymce.Env.ie ? 'javascript:""' : '',
 						frameBorder: '0',
@@ -516,105 +549,137 @@
 						style: {
 							width: '100%',
 							display: 'block'
-						}
+						},
+						height: self.iframeHeight
 					} );
 
-					dom.add( contentNode, 'div', { 'class': 'wpview-overlay' } );
+					dom.add( node, 'span', { 'class': 'mce-shim' } );
+					dom.add( node, 'span', { 'class': 'wpview-end' } );
+				} );
 
-					iframeDoc = iframe.contentWindow.document;
+				// Bail if the iframe node is not attached to the DOM.
+				// Happens when the view is dragged in the editor.
+				// There is a browser restriction when iframes are moved in the DOM. They get emptied.
+				// The iframe will be rerendered after dropping the view node at the new location.
+				if ( ! iframe.contentWindow ) {
+					return;
+				}
 
-					iframeDoc.open();
+				iframeWin = iframe.contentWindow;
+				iframeDoc = iframeWin.document;
+				iframeDoc.open();
 
-					iframeDoc.write(
-						'<!DOCTYPE html>' +
-						'<html>' +
-							'<head>' +
-								'<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />' +
-								head +
-								styles +
-								'<style>' +
-									'html {' +
-										'background: transparent;' +
-										'padding: 0;' +
-										'margin: 0;' +
-									'}' +
-									'body#wpview-iframe-sandbox {' +
-										'background: transparent;' +
-										'padding: 1px 0 !important;' +
-										'margin: -1px 0 0 !important;' +
-									'}' +
-									'body#wpview-iframe-sandbox:before,' +
-									'body#wpview-iframe-sandbox:after {' +
-										'display: none;' +
-										'content: "";' +
-									'}' +
-								'</style>' +
-							'</head>' +
-							'<body id="wpview-iframe-sandbox" class="' + bodyClasses + '">' +
-								body +
-							'</body>' +
-						'</html>'
-					);
+				iframeDoc.write(
+					'<!DOCTYPE html>' +
+					'<html>' +
+						'<head>' +
+							'<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />' +
+							head +
+							styles +
+							'<style>' +
+								'html {' +
+									'background: transparent;' +
+									'padding: 0;' +
+									'margin: 0;' +
+								'}' +
+								'body#wpview-iframe-sandbox {' +
+									'background: transparent;' +
+									'padding: 1px 0 !important;' +
+									'margin: -1px 0 0 !important;' +
+								'}' +
+								'body#wpview-iframe-sandbox:before,' +
+								'body#wpview-iframe-sandbox:after {' +
+									'display: none;' +
+									'content: "";' +
+								'}' +
+								'iframe {' +
+									'max-width: 100%;' +
+								'}' +
+							'</style>' +
+						'</head>' +
+						'<body id="wpview-iframe-sandbox" class="' + bodyClasses + '">' +
+							body +
+						'</body>' +
+					'</html>'
+				);
 
-					iframeDoc.close();
+				iframeDoc.close();
 
-					function resize() {
-						var $iframe, iframeDocHeight;
+				function resize() {
+					var $iframe;
+
+					if ( block ) {
+						return;
+					}
 
-						// Make sure the iframe still exists.
-						if ( iframe.contentWindow ) {
-							$iframe = $( iframe );
-							iframeDocHeight = $( iframeDoc.body ).height();
+					// Make sure the iframe still exists.
+					if ( iframe.contentWindow ) {
+						$iframe = $( iframe );
+						self.iframeHeight = $( iframeDoc.body ).height();
 
-							if ( $iframe.height() !== iframeDocHeight ) {
-								$iframe.height( iframeDocHeight );
-								editor.nodeChanged();
-							}
+						if ( $iframe.height() !== self.iframeHeight ) {
+							$iframe.height( self.iframeHeight );
+							editor.nodeChanged();
 						}
 					}
+				}
 
-					$( iframe.contentWindow ).on( 'load', resize );
+				if ( self.iframeHeight ) {
+					block = true;
 
-					if ( MutationObserver ) {
-						observer = new MutationObserver( _.debounce( resize, 100 ) );
+					setTimeout( function() {
+						block = false;
+						resize();
+					}, 3000 );
+				}
+
+				function reload() {
+					if ( ! editor.isHidden() ) {
+						$( node ).data( 'rendered', null );
 
-						observer.observe( iframeDoc.body, {
-							attributes: true,
-							childList: true,
-							subtree: true
+						setTimeout( function() {
+							wp.mce.views.render();
 						} );
+					}
+				}
 
-						$( node ).one( 'wp-mce-view-unbind', function() {
-							observer.disconnect();
-						} );
+				function addObserver() {
+					observer = new MutationObserver( _.debounce( resize, 100 ) );
+
+					observer.observe( iframeDoc.body, {
+						attributes: true,
+						childList: true,
+						subtree: true
+					} );
+				}
+
+				$( iframeWin ).on( 'load', resize ).on( 'unload', reload );
+
+				MutationObserver = iframeWin.MutationObserver || iframeWin.WebKitMutationObserver || iframeWin.MozMutationObserver;
+
+				if ( MutationObserver ) {
+					if ( ! iframeDoc.body ) {
+						iframeDoc.addEventListener( 'DOMContentLoaded', addObserver, false );
 					} else {
-						for ( i = 1; i < 6; i++ ) {
-							setTimeout( resize, i * 700 );
-						}
+						addObserver();
 					}
-
-					function classChange() {
-						iframeDoc.body.className = editor.getBody().className;
+				} else {
+					for ( i = 1; i < 6; i++ ) {
+						setTimeout( resize, i * 700 );
 					}
+				}
 
-					editor.on( 'wp-body-class-change', classChange );
-
-					$( node ).one( 'wp-mce-view-unbind', function() {
-						editor.off( 'wp-body-class-change', classChange );
-					} );
-
-					callback && callback.call( self, editor, node, contentNode );
-				}, 50 );
+				callback && callback.call( self, editor, node );
 			}, rendered );
 		},
 
 		/**
 		 * Sets a loader for all view nodes tied to this view instance.
 		 */
-		setLoader: function() {
+		setLoader: function( dashicon ) {
 			this.setContent(
 				'<div class="loading-placeholder">' +
-					'<div class="dashicons dashicons-admin-media"></div>' +
+					'<div class="dashicons dashicons-' + ( dashicon || 'admin-media' ) + '"></div>' +
 					'<div class="wpview-loading"><ins></ins></div>' +
 				'</div>'
 			);
@@ -624,7 +689,7 @@
 		 * Sets an error for all view nodes tied to this view instance.
 		 *
 		 * @param {String} message  The error message to set.
-		 * @param {String} dashicon A dashicon ID (optional). {@link https://developer.wordpress.org/resource/dashicons/}
+		 * @param {String} dashicon A dashicon ID. Optional. {@link https://developer.wordpress.org/resource/dashicons/}
 		 */
 		setError: function( message, dashicon ) {
 			this.setContent(
@@ -643,7 +708,7 @@
 		 * @return {Object}
 		 */
 		match: function( content ) {
-			var match = wp.shortcode.next( this.type, content );
+			var match = shortcode.next( this.type, content );
 
 			if ( match ) {
 				return {
@@ -662,15 +727,19 @@
 		 * @param {String}         text   The new text.
 		 * @param {tinymce.Editor} editor The TinyMCE editor instance the view node is in.
 		 * @param {HTMLElement}    node   The view node to update.
+		 * @param {Boolean}        force  Recreate the instance. Optional.
 		 */
-		update: function( text, editor, node ) {
+		update: function( text, editor, node, force ) {
 			_.find( views, function( view, type ) {
 				var match = view.prototype.match( text );
 
 				if ( match ) {
 					$( node ).data( 'rendered', false );
 					editor.dom.setAttrib( node, 'data-wpview-text', encodeURIComponent( text ) );
-					wp.mce.views.createInstance( type, text, match.options ).render();
+					wp.mce.views.createInstance( type, text, match.options, force ).render();
+
+					editor.selection.select( node );
+					editor.nodeChanged();
 					editor.focus();
 
 					return true;
@@ -685,35 +754,52 @@
 		 * @param {HTMLElement}    node   The view node to remove.
 		 */
 		remove: function( editor, node ) {
-			this.unbindNode.call( this, editor, node, $( node ).find( '.wpview-content' ).get( 0 ) );
-			$( node ).trigger( 'wp-mce-view-unbind' );
+			this.unbindNode.call( this, editor, node );
 			editor.dom.remove( node );
 			editor.focus();
 		}
 	} );
-} )( window, window.wp, window.jQuery );
+} )( window, window.wp, window.wp.shortcode, window.jQuery );
 
 /*
  * The WordPress core TinyMCE views.
  * Views for the gallery, audio, video, playlist and embed shortcodes,
  * and a view for embeddable URLs.
  */
-( function( window, views, $ ) {
-	var postID = $( '#post_ID' ).val() || 0,
-		media, gallery, av, embed;
+( function( window, views, media, $ ) {
+	var base, gallery, av, embed,
+		schema, parser, serializer;
+
+	function verifyHTML( string ) {
+		var settings = {};
+
+		if ( ! window.tinymce ) {
+			return string.replace( /<[^>]+>/g, '' );
+		}
 
-	media = {
+		if ( ! string || ( string.indexOf( '<' ) === -1 && string.indexOf( '>' ) === -1 ) ) {
+			return string;
+		}
+
+		schema = schema || new window.tinymce.html.Schema( settings );
+		parser = parser || new window.tinymce.html.DomParser( settings, schema );
+		serializer = serializer || new window.tinymce.html.Serializer( settings, schema );
+
+		return serializer.serialize( parser.parse( string, { forced_root_block: false } ) );
+	}
+
+	base = {
 		state: [],
 
 		edit: function( text, update ) {
-			var media = wp.media[ this.type ],
-				frame = media.edit( text );
+			var type = this.type,
+				frame = media[ type ].edit( text );
 
 			this.pausePlayers && this.pausePlayers();
 
 			_.each( this.state, function( state ) {
 				frame.state( state ).on( 'update', function( selection ) {
-					update( media.shortcode( selection ).string() );
+					update( media[ type ].shortcode( selection ).string(), type === 'gallery' );
 				} );
 			} );
 
@@ -725,12 +811,12 @@
 		}
 	};
 
-	gallery = _.extend( {}, media, {
+	gallery = _.extend( {}, base, {
 		state: [ 'gallery-edit' ],
-		template: wp.media.template( 'editor-gallery' ),
+		template: media.template( 'editor-gallery' ),
 
 		initialize: function() {
-			var attachments = wp.media.gallery.attachments( this.shortcode, postID ),
+			var attachments = media.gallery.attachments( this.shortcode, media.view.settings.post.id ),
 				attrs = this.shortcode.attrs.named,
 				self = this;
 
@@ -751,8 +837,9 @@
 				} );
 
 				self.render( self.template( {
+					verifyHTML: verifyHTML,
 					attachments: attachments,
-					columns: attrs.columns ? parseInt( attrs.columns, 10 ) : wp.media.galleryDefaults.columns
+					columns: attrs.columns ? parseInt( attrs.columns, 10 ) : media.galleryDefaults.columns
 				} ) );
 			} )
 			.fail( function( jqXHR, textStatus ) {
@@ -761,29 +848,36 @@
 		}
 	} );
 
-	av = _.extend( {}, media, {
+	av = _.extend( {}, base, {
 		action: 'parse-media-shortcode',
 
 		initialize: function() {
-			var self = this;
+			var self = this, maxwidth = null;
 
 			if ( this.url ) {
 				this.loader = false;
-				this.shortcode = wp.media.embed.shortcode( {
+				this.shortcode = media.embed.shortcode( {
 					url: this.text
 				} );
 			}
 
+			// Obtain the target width for the embed.
+			if ( self.editor ) {
+				maxwidth = self.editor.getBody().clientWidth;
+			}
+
 			wp.ajax.post( this.action, {
-				post_ID: postID,
+				post_ID: media.view.settings.post.id,
 				type: this.shortcode.tag,
-				shortcode: this.shortcode.string()
+				shortcode: this.shortcode.string(),
+				maxwidth: maxwidth
 			} )
 			.done( function( response ) {
 				self.render( response );
 			} )
 			.fail( function( response ) {
 				if ( self.url ) {
+					self.ignore = true;
 					self.removeMarkers();
 				} else {
 					self.setError( response.message || response.statusText, 'admin-media' );
@@ -816,8 +910,7 @@
 		action: 'parse-embed',
 
 		edit: function( text, update ) {
-			var media = wp.media.embed,
-				frame = media.edit( text, this.url ),
+			var frame = media.embed.edit( text, this.url ),
 				self = this;
 
 			this.pausePlayers();
@@ -834,7 +927,7 @@
 				if ( self.url ) {
 					update( data.url );
 				} else {
-					update( media.shortcode( data ).string() );
+					update( media.embed.shortcode( data ).string() );
 				}
 			} );
 
@@ -878,4 +971,4 @@
 			}
 		}
 	} ) );
-} )( window, window.wp.mce.views, window.jQuery );
+} )( window, window.wp.mce.views, window.wp.media, window.jQuery );