diff --git a/src/wp-includes/js/mce-view.js b/src/wp-includes/js/mce-view.js
index 9817454..4e4d0e8 100644
--- a/src/wp-includes/js/mce-view.js
+++ b/src/wp-includes/js/mce-view.js
@@ -87,6 +87,8 @@ window.wp = window.wp || {};
 		 * and creates a new instance for every match.
 		 *
 		 * @param {String} content The string to scan.
+		 *
+		 * @return {String} The string with markers.
 		 */
 		setMarkers: function( content ) {
 			var pieces = [ { content: content } ],
@@ -298,11 +300,18 @@ window.wp = window.wp || {};
 		/**
 		 * 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.
 		 */
-		render: function( force ) {
+		render: function( content, force ) {
+			if ( content != null ) {
+				this.content = content;
+			}
+
+			content = this.getContent();
+
 			// If there's nothing to render an no loader needs to be shown, stop.
-			if ( ! this.loader && ! this.getContent() ) {
+			if ( ! this.loader && ! content ) {
 				return;
 			}
 
@@ -312,9 +321,10 @@ window.wp = window.wp || {};
 			// Replace any left over markers.
 			this.replaceMarkers();
 
-			if ( this.getContent() ) {
-				this.setContent( this.getContent(), function( editor, node ) {
-					$( node ).data( 'rendered', true ).trigger( 'wp-mce-view-bind' );
+			if ( content ) {
+				this.setContent( content, function( editor, node ) {
+					$( node ).data( 'rendered', true );
+					this.bindNode.apply( this, arguments );
 				}, force ? null : false );
 			} else {
 				this.setLoader();
@@ -322,11 +332,22 @@ window.wp = window.wp || {};
 		},
 
 		/**
+		 * Binds a given node after its content is added to the DOM.
+		 */
+		bindNode: function() {},
+
+		/**
+		 * Unbinds a given node before its content is removed from the DOM.
+		 */
+		unbindNode: function() {},
+
+		/**
 		 * Unbinds all view nodes tied to this view instance.
 		 * Runs before their content is removed from the DOM.
 		 */
 		unbind: function() {
 			this.getNodes( function( editor, node ) {
+				this.unbindNode.apply( this, arguments );
 				$( node ).trigger( 'wp-mce-view-unbind' );
 			}, true );
 		},
@@ -461,32 +482,32 @@ window.wp = window.wp || {};
 		 * @param {Boolean}  rendered Only set for (un)rendered nodes. Optional.
 		 */
 		setIframes: function( head, body, callback, rendered ) {
-			var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
+			var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver,
+				self = this;
 
 			this.getNodes( function( editor, node, content ) {
-				// Seems Firefox needs a bit of time to insert/set the view nodes,
-				// or the iframe will fail especially when switching Text => Visual.
-				setTimeout( function() {
-					var dom = editor.dom,
-						styles = '',
-						bodyClasses = editor.getBody().className || '',
-						iframe, iframeDoc, observer, i;
-
-					tinymce.each( dom.$(
-						'link[rel="stylesheet"]',
-						editor.getDoc().getElementsByTagName( 'head' )[0]
-					), function( link ) {
-						if (
-							link.href &&
-							link.href.indexOf( 'skins/lightgray/content.min.css' ) === -1 &&
-							link.href.indexOf( 'skins/wordpress/wp-content.css' ) === -1
-						) {
-							styles += dom.getOuterHTML( link );
-						}
-					} );
+				var dom = editor.dom,
+					styles = '',
+					bodyClasses = editor.getBody().className || '',
+					iframe, iframeDoc, observer, i;
+
+				if ( ! head ) {
+					head = editor.getDoc().getElementsByTagName( 'head' )[0].innerHTML;
+				}
+
+				tinymce.each( dom.$( 'link[rel="stylesheet"]', head ), function( link ) {
+					if ( link.href && link.href.indexOf( 'skins/lightgray/content.min.css' ) === -1 &&
+						link.href.indexOf( 'skins/wordpress/wp-content.css' ) === -1 ) {
+
+						styles += dom.getOuterHTML( link );
+					}
+				} );
 
-					content.innerHTML = '';
+				content.innerHTML = '';
 
+				// 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() {
 					iframe = dom.add( content, 'iframe', {
 						/* jshint scripturl: true */
 						src: tinymce.Env.ie ? 'javascript:""' : '',
@@ -582,7 +603,7 @@ window.wp = window.wp || {};
 						editor.off( 'wp-body-class-change', classChange );
 					} );
 
-					callback && callback.apply( this, arguments );
+					callback && callback.apply( self, arguments );
 				}, 50 );
 			}, rendered );
 		},
@@ -663,6 +684,7 @@ window.wp = window.wp || {};
 		 * @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' );
 			editor.dom.remove( node );
 		}
@@ -726,12 +748,10 @@ window.wp = window.wp || {};
 					}
 				} );
 
-				self.content = self.template( {
+				self.render( self.template( {
 					attachments: attachments,
 					columns: attrs.columns ? parseInt( attrs.columns, 10 ) : wp.media.galleryDefaults.columns
-				} );
-
-				self.render();
+				} ) );
 			} )
 			.fail( function( jqXHR, textStatus ) {
 				self.setError( textStatus );
@@ -752,16 +772,13 @@ window.wp = window.wp || {};
 				} );
 			}
 
-			wp.ajax.send( this.action, {
-				data: {
-					post_ID: postID,
-					type: this.shortcode.tag,
-					shortcode: this.shortcode.string()
-				}
+			wp.ajax.post( this.action, {
+				post_ID: postID,
+				type: this.shortcode.tag,
+				shortcode: this.shortcode.string()
 			} )
 			.done( function( response ) {
-				self.content = response;
-				self.render();
+				self.render( response );
 			} )
 			.fail( function( response ) {
 				if ( self.url ) {
diff --git a/src/wp-includes/js/tinymce/plugins/wpview/plugin.js b/src/wp-includes/js/tinymce/plugins/wpview/plugin.js
index 9a8b650..657317e 100644
--- a/src/wp-includes/js/tinymce/plugins/wpview/plugin.js
+++ b/src/wp-includes/js/tinymce/plugins/wpview/plugin.js
@@ -4,7 +4,8 @@
  * WordPress View plugin.
  */
 tinymce.PluginManager.add( 'wpview', function( editor ) {
-	var selected,
+	var $ = editor.$,
+		selected,
 		Env = tinymce.Env,
 		VK = tinymce.util.VK,
 		TreeWalker = tinymce.dom.TreeWalker,
@@ -153,13 +154,17 @@ tinymce.PluginManager.add( 'wpview', function( editor ) {
 
 	// Remove the content of view wrappers from HTML string
 	function emptyViews( content ) {
-		return content.replace(/<div[^>]+data-wpview-text=\"([^"]+)"[^>]*>[\s\S]+?wpview-selection-after[^>]+>(?:&nbsp;|\u00a0)*<\/p><\/div>/g, '$1' );
+		content = content.replace( /<div[^>]+data-wpview-text="([^"]+)"[^>]*>[\s\S]+?wpview-selection-after[^>]+>[^<>]*<\/p>\s*<\/div>/g, function( all, match ) {
+			return '<p>' + window.decodeURIComponent( match ) + '</p>';
+		});
+
+		return content.replace( / data-wpview-marker="[^"]+"/g, '' );
 	}
 
 	// Prevent adding undo levels on changes inside a view wrapper
 	editor.on( 'BeforeAddUndo', function( event ) {
-		if ( event.lastLevel && emptyViews( event.level.content ) === emptyViews( event.lastLevel.content ) ) {
-			event.preventDefault();
+		if ( event.level.content ) {
+			event.level.content = emptyViews( event.level.content );
 		}
 	});
 
@@ -169,6 +174,10 @@ tinymce.PluginManager.add( 'wpview', function( editor ) {
 	editor.on( 'BeforeSetContent', function( event ) {
 		var node;
 
+		if ( ! event.selection ) {
+			wp.mce.views.unbind();
+		}
+
 		if ( ! event.content ) {
 			return;
 		}
@@ -339,22 +348,30 @@ tinymce.PluginManager.add( 'wpview', function( editor ) {
 		}
 	});
 
-	editor.on( 'PreProcess', function( event ) {
-		// Empty the wpview wrap nodes
-		tinymce.each( editor.dom.select( 'div[data-wpview-text]', event.node ), function( node ) {
-			node.textContent = node.innerText = '\u00a0';
+	function resetViews( rootNode ) {
+		// Replace view nodes
+		$( 'div[data-wpview-text]', rootNode ).each( function( i, node ) {
+			var $node = $( node ),
+				text = window.decodeURIComponent( $node.attr( 'data-wpview-text' ) || '' );
+
+			if ( text && node.parentNode ) {
+				$node.replaceWith( $( editor.dom.create('p') ).text( text ) );
+			}
 		});
-    });
 
-    editor.on( 'PostProcess', function( event ) {
-		if ( event.content ) {
-			event.content = event.content.replace( /<div [^>]*?data-wpview-text="([^"]*)"[^>]*>[\s\S]*?<\/div>/g, function( match, shortcode ) {
-				if ( shortcode ) {
-					return '<p>' + window.decodeURIComponent( shortcode ) + '</p>';
-				}
-				return ''; // If error, remove the view wrapper
-			});
-		}
+		// Remove marker attributes
+		$( 'p[data-wpview-marker]', rootNode ).attr( 'data-wpview-marker', null );
+	}
+
+	editor.on( 'PreProcess', function( event ) {
+		// Replace the view nodes with their text in the DOM clone.
+		resetViews( event.node );
+    }, true );
+
+	editor.on( 'hide', function() {
+		// Replace the view nodes with their text directly in the editor body.
+		wp.mce.views.unbind();
+		resetViews( editor.getBody() );
 	});
 
 	// Excludes arrow keys, delete, backspace, enter, space bar.
