- /**
- * wp.mce.View
- *
- * A Backbone-like View constructor intended for use when rendering a TinyMCE View. The main difference is
- * that the TinyMCE View is not tied to a particular DOM node.
- *
- * @param {Object} [options={}]
- */
- wp.mce.View = function( options ) {
- options = options || {};
- this.type = options.type;
- _.extend( this, _.pick( options, viewOptions ) );
- this.initialize.apply( this, arguments );
- };
-
- _.extend( wp.mce.View.prototype, {
- initialize: function() {},
- getHtml: function() {
- return '';
- },
- loadingPlaceholder: function() {
- return '' +
- '<div class="loading-placeholder">' +
- '<div class="dashicons dashicons-admin-media"></div>' +
- '<div class="wpview-loading"><ins></ins></div>' +
- '</div>';
- },
- render: function( force ) {
- if ( force || ! this.rendered() ) {
- this.unbind();
-
- this.setContent(
- '<p class="wpview-selection-before">\u00a0</p>' +
- '<div class="wpview-body" contenteditable="false">' +
- '<div class="toolbar">' +
- ( _.isFunction( views[ this.type ].edit ) ? '<div class="dashicons dashicons-edit edit"></div>' : '' ) +
- '<div class="dashicons dashicons-no-alt remove"></div>' +
- '</div>' +
- '<div class="wpview-content wpview-type-' + this.type + '">' +
- ( this.getHtml() || this.loadingPlaceholder() ) +
- '</div>' +
- ( this.overlay ? '<div class="wpview-overlay"></div>' : '' ) +
- '</div>' +
- '<p class="wpview-selection-after">\u00a0</p>',
- 'wrap'
- );
-
- $( this ).trigger( 'ready' );
-
- this.rendered( true );
- }
- },
- unbind: function() {},
- getEditors: function( callback ) {
- var editors = [];
-
- _.each( tinymce.editors, function( editor ) {
- if ( editor.plugins.wpview ) {
- if ( callback ) {
- callback( editor );
- }
-
- editors.push( editor );
- }
- }, this );
-
- return editors;
- },
- getNodes: function( callback ) {
- var nodes = [],
- self = this;
-
- this.getEditors( function( editor ) {
- $( editor.getBody() )
- .find( '[data-wpview-text="' + self.encodedText + '"]' )
- .each( function ( i, node ) {
- if ( callback ) {
- callback( editor, node, $( node ).find( '.wpview-content' ).get( 0 ) );
- }
-
- nodes.push( node );
- } );
- } );
-
- return nodes;
- },
- setContent: function( html, option ) {
- this.getNodes( function ( editor, node, content ) {
- var el = ( option === 'wrap' || option === 'replace' ) ? node : content,
- insert = html;
-
- if ( _.isString( insert ) ) {
- insert = editor.dom.createFragment( insert );
- }
-
- if ( option === 'replace' ) {
- editor.dom.replace( insert, el );
- } else {
- el.innerHTML = '';
- el.appendChild( insert );
- }
- } );
- },
- /* jshint scripturl: true */
- setIframes: function ( head, body ) {
- var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver,
- importStyles = this.type === 'video' || this.type === 'audio' || this.type === 'playlist';
-
- if ( head || body.indexOf( '<script' ) !== -1 ) {
- this.getNodes( function ( editor, node, content ) {
- var dom = editor.dom,
- styles = '',
- bodyClasses = editor.getBody().className || '',
- iframe, iframeDoc, i, resize;
-
- content.innerHTML = '';
- head = head || '';
-
- if ( importStyles ) {
- if ( ! wp.mce.views.sandboxStyles ) {
- tinymce.each( dom.$( 'link[rel="stylesheet"]', editor.getDoc().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 ) + '\n';
- }
- });
-
- wp.mce.views.sandboxStyles = styles;
- } else {
- styles = wp.mce.views.sandboxStyles;
- }
- }
-
- // 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() {
- iframe = dom.add( content, 'iframe', {
- src: tinymce.Env.ie ? 'javascript:""' : '',
- frameBorder: '0',
- allowTransparency: 'true',
- scrolling: 'no',
- 'class': 'wpview-sandbox',
- style: {
- width: '100%',
- display: 'block'
- }
- } );
-
- iframeDoc = iframe.contentWindow.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.close();
-
- resize = function() {
- // Make sure the iframe still exists.
- iframe.contentWindow && $( iframe ).height( $( iframeDoc.body ).height() );
- };
-
- if ( MutationObserver ) {
- new MutationObserver( _.debounce( function() {
- resize();
- }, 100 ) )
- .observe( iframeDoc.body, {
- attributes: true,
- childList: true,
- subtree: true
- } );
- } else {
- for ( i = 1; i < 6; i++ ) {
- setTimeout( resize, i * 700 );
- }
- }
-
- if ( importStyles ) {
- editor.on( 'wp-body-class-change', function() {
- iframeDoc.body.className = editor.getBody().className;
- });
- }
- }, 50 );
- });
- } else {
- this.setContent( body );
- }
- },
- setError: function( message, dashicon ) {
- this.setContent(
- '<div class="wpview-error">' +
- '<div class="dashicons dashicons-' + ( dashicon ? dashicon : 'no' ) + '"></div>' +
- '<p>' + message + '</p>' +
- '</div>'
- );
- },
- rendered: function( value ) {
- var notRendered;
-
- this.getNodes( function( editor, node ) {
- if ( value != null ) {
- $( node ).data( 'rendered', value === true );
- } else {
- notRendered = notRendered || ! $( node ).data( 'rendered' );
- }
- } );
-
- return ! notRendered;
- }
- } );
-
- // take advantage of the Backbone extend method
- wp.mce.View.extend = Backbone.View.extend;
-