Index: src/wp-includes/js/mce-view.js =================================================================== --- src/wp-includes/js/mce-view.js (revision 28687) +++ src/wp-includes/js/mce-view.js (working copy) @@ -8,7 +8,9 @@ // Ensure the global `wp` object exists. window.wp = window.wp || {}; -(function($){ +( function( $ ) { + 'use strict'; + var views = {}, instances = {}, media = wp.media, @@ -637,60 +639,155 @@ /** * TinyMCE handler for the embed shortcode */ - wp.mce.views.register( 'embed', { - shortcode: 'embed', - View: _.extend( {}, wp.media.mixin, { - template: media.template( 'editor-embed' ), - initialize: function( options ) { - this.players = []; - this.content = options.content; - this.parsed = false; - this.shortcode = options.shortcode; - _.bindAll( this, 'setHtml', 'setNode', 'fetch' ); - $( this ).on( 'ready', this.setNode ); - }, - unbind: function() { - var self = this; - _.each( this.players, function ( player ) { - player.pause(); - self.removePlayer( player ); - } ); - this.players = []; - }, - setNode: function ( e, node ) { - this.node = node; - if ( this.parsed ) { - this.parseMediaShortcodes(); - } else { - this.fetch(); + wp.mce.embedView = _.extend( {}, wp.media.mixin, { + template: media.template( 'editor-embed' ), + initialize: function( options ) { + this.players = []; + this.content = options.content; + this.parsed = false; + this.original = options.url || options.shortcode.string(); + if ( options.url ) { + this.shortcode = '[embed]' + options.url + '[/embed]'; + } else { + this.shortcode = options.shortcode.string(); + } + _.bindAll( this, 'setHtml', 'setNode', 'fetch' ); + $( this ).on( 'ready', this.setNode ); + }, + unbind: function() { + var self = this; + _.each( this.players, function ( player ) { + player.pause(); + self.removePlayer( player ); + } ); + this.players = []; + }, + setNode: function ( e, node ) { + this.node = node; + if ( this.parsed ) { + this.setHtml( this.parsed ); + this.parseMediaShortcodes(); + } else { + this.fetch(); + } + }, + fetch: function () { + var self = this; + wp.ajax.send( 'parse-embed', { + data: { + post_ID: $( '#post_ID' ).val(), + content: this.shortcode } - }, - fetch: function () { - wp.ajax.send( 'parse-embed', { - data: { - post_ID: $( '#post_ID' ).val(), - content: this.shortcode.string() + } ).done( function( content ) { + self.parsed = content; + self.setHtml( content ); + } ); + }, + /* jshint scripturl: true */ + setHtml: function ( content ) { + var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver, + html, $html, scripts, observer, iframe, iframeWin, iframeDoc, + test = '' + + '
' + + '' + + '
' + ), this.node.lastChild ); + this.node.insertBefore( iframe, this.node.lastChild ); + + iframeWin = iframe.contentWindow; + iframeDoc = iframeWin.document; + + iframeWin.resize = function() { + window.parent.postMessage( { + height: $( iframeDoc ).height() + }, '*' ); + }; + + window.addEventListener( 'message', function ( event ) { + if ( event.data.height ) { + $( iframe ).height( event.data.height ); + } + }, false ); + + iframeDoc.open(); + iframeDoc.write( '' + html + '' ); + iframeDoc.close(); + + if ( MutationObserver ) { + observer = new MutationObserver( _.debounce( function() { + iframeWin.resize(); + }, 500 ) ).observe( iframeDoc.body, { + attributes: true, + childList: true, + subtree: true + } ); } - } ).done( this.setHtml ); - }, - setHtml: function ( content ) { - this.parsed = content; - $( this.node ).html( this.getHtml() ); - this.parseMediaShortcodes(); - }, - parseMediaShortcodes: function () { - var self = this; - $( '.wp-audio-shortcode, .wp-video-shortcode', this.node ).each( function ( i, element ) { - self.players.push( new MediaElementPlayer( element, self.mejsSettings ) ); - } ); - }, - getHtml: function() { - if ( ! this.parsed ) { - return ''; + } else { + this.node.insertBefore( dom.createFragment( html ), this.node.lastChild ); } - return this.template({ content: this.parsed }); } - } ), + + this.parseMediaShortcodes(); + }, + parseMediaShortcodes: function () { + var self = this; + $( '.wp-audio-shortcode, .wp-video-shortcode', this.node ).each( function ( i, element ) { + self.players.push( new MediaElementPlayer( element, self.mejsSettings ) ); + } ); + }, + getHtml: function() { + return ''; + } + } ); + + wp.mce.views.register( 'embed', { + shortcode: 'embed', + View: wp.mce.embedView, + edit: function() {} + } ); + + wp.mce.views.register( 'embedURL', { + shortcode: 'embed', + toView: function( content ) { + var re = /^

\s*(https?:\/\/[^\s"]+)\s*<\/p>$/gim, + match = re.exec( content ); + + if ( ! match ) { + return; + } + + return { + index: match.index, + content: match[0], + options: { + url: match[1] + } + }; + }, + View: wp.mce.embedView, edit: function() {} } ); Index: src/wp-includes/js/tinymce/plugins/wpview/plugin.js =================================================================== --- src/wp-includes/js/tinymce/plugins/wpview/plugin.js (revision 28687) +++ src/wp-includes/js/tinymce/plugins/wpview/plugin.js (working copy) @@ -158,6 +158,8 @@ // matching view patterns, and transform the matches into // view wrappers. editor.on( 'BeforeSetContent', function( event ) { + var node; + if ( ! event.content ) { return; } @@ -166,14 +168,15 @@ wp.mce.views.unbind( editor ); } - event.content = wp.mce.views.toViews( event.content ); - }); + node = editor.selection.getNode(); - editor.on( 'PastePreProcess', function( event ) { - if ( event.content.match( /^\s*(https?:\/\/[^\s"]+)\s*$/im ) ) { - event.content = '[embed]' + event.content + '[/embed]'; + // If a url is inserted in an empty paragraph, wrap the url in p tags so it's detected by wp.mce.views. + if ( node.nodeName === 'P' && editor.dom.isEmpty( node ) && event.content.match( /^\s*(https?:\/\/[^\s"]+)\s*$/im ) ) { + event.content = '

' + event.content + '

'; } - } ); + + event.content = wp.mce.views.toViews( event.content ); + }); // When the editor's content has been updated and the DOM has been // processed, render the views in the document.