angelovcom.net

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

plugin.js (6083B)


      1 /**
      2  * WordPress View plugin.
      3  */
      4 ( function( tinymce ) {
      5 	tinymce.PluginManager.add( 'wpview', function( editor ) {
      6 		function noop () {}
      7 
      8 		// Set this here as wp-tinymce.js may be loaded too early.
      9 		var wp = window.wp;
     10 
     11 		if ( ! wp || ! wp.mce || ! wp.mce.views ) {
     12 			return {
     13 				getView: noop
     14 			};
     15 		}
     16 
     17 		// Check if a node is a view or not.
     18 		function isView( node ) {
     19 			return editor.dom.hasClass( node, 'wpview' );
     20 		}
     21 
     22 		// Replace view tags with their text.
     23 		function resetViews( content ) {
     24 			function callback( match, $1 ) {
     25 				return '<p>' + window.decodeURIComponent( $1 ) + '</p>';
     26 			}
     27 
     28 			if ( ! content || content.indexOf( ' data-wpview-' ) === -1 ) {
     29 				return content;
     30 			}
     31 
     32 			return content
     33 				.replace( /<div[^>]+data-wpview-text="([^"]+)"[^>]*>(?:\.|[\s\S]+?wpview-end[^>]+>\s*<\/span>\s*)?<\/div>/g, callback )
     34 				.replace( /<p[^>]+data-wpview-marker="([^"]+)"[^>]*>[\s\S]*?<\/p>/g, callback );
     35 		}
     36 
     37 		editor.on( 'init', function() {
     38 			var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
     39 
     40 			if ( MutationObserver ) {
     41 				new MutationObserver( function() {
     42 					editor.fire( 'wp-body-class-change' );
     43 				} )
     44 				.observe( editor.getBody(), {
     45 					attributes: true,
     46 					attributeFilter: ['class']
     47 				} );
     48 			}
     49 
     50 			// Pass on body class name changes from the editor to the wpView iframes.
     51 			editor.on( 'wp-body-class-change', function() {
     52 				var className = editor.getBody().className;
     53 
     54 				editor.$( 'iframe[class="wpview-sandbox"]' ).each( function( i, iframe ) {
     55 					// Make sure it is a local iframe.
     56 					// jshint scripturl: true
     57 					if ( ! iframe.src || iframe.src === 'javascript:""' ) {
     58 						try {
     59 							iframe.contentWindow.document.body.className = className;
     60 						} catch( er ) {}
     61 					}
     62 				});
     63 			} );
     64 		});
     65 
     66 		// Scan new content for matching view patterns and replace them with markers.
     67 		editor.on( 'beforesetcontent', function( event ) {
     68 			var node;
     69 
     70 			if ( ! event.selection ) {
     71 				wp.mce.views.unbind();
     72 			}
     73 
     74 			if ( ! event.content ) {
     75 				return;
     76 			}
     77 
     78 			if ( ! event.load ) {
     79 				node = editor.selection.getNode();
     80 
     81 				if ( node && node !== editor.getBody() && /^\s*https?:\/\/\S+\s*$/i.test( event.content ) ) {
     82 					// When a url is pasted or inserted, only try to embed it when it is in an empty paragraph.
     83 					node = editor.dom.getParent( node, 'p' );
     84 
     85 					if ( node && /^[\s\uFEFF\u00A0]*$/.test( editor.$( node ).text() || '' ) ) {
     86 						// Make sure there are no empty inline elements in the <p>.
     87 						node.innerHTML = '';
     88 					} else {
     89 						return;
     90 					}
     91 				}
     92 			}
     93 
     94 			event.content = wp.mce.views.setMarkers( event.content, editor );
     95 		} );
     96 
     97 		// Replace any new markers nodes with views.
     98 		editor.on( 'setcontent', function() {
     99 			wp.mce.views.render();
    100 		} );
    101 
    102 		// Empty view nodes for easier processing.
    103 		editor.on( 'preprocess hide', function( event ) {
    104 			editor.$( 'div[data-wpview-text], p[data-wpview-marker]', event.node ).each( function( i, node ) {
    105 				node.innerHTML = '.';
    106 			} );
    107 		}, true );
    108 
    109 		// Replace views with their text.
    110 		editor.on( 'postprocess', function( event ) {
    111 			event.content = resetViews( event.content );
    112 		} );
    113 
    114 		// Prevent adding of undo levels when replacing wpview markers
    115 		// or when there are changes only in the (non-editable) previews.
    116 		editor.on( 'beforeaddundo', function( event ) {
    117 			var lastContent;
    118 			var newContent = event.level.content || ( event.level.fragments && event.level.fragments.join( '' ) );
    119 
    120 			if ( ! event.lastLevel ) {
    121 				lastContent = editor.startContent;
    122 			} else {
    123 				lastContent = event.lastLevel.content || ( event.lastLevel.fragments && event.lastLevel.fragments.join( '' ) );
    124 			}
    125 
    126 			if (
    127 				! newContent ||
    128 				! lastContent ||
    129 				newContent.indexOf( ' data-wpview-' ) === -1 ||
    130 				lastContent.indexOf( ' data-wpview-' ) === -1
    131 			) {
    132 				return;
    133 			}
    134 
    135 			if ( resetViews( lastContent ) === resetViews( newContent ) ) {
    136 				event.preventDefault();
    137 			}
    138 		} );
    139 
    140 		// Make sure views are copied as their text.
    141 		editor.on( 'drop objectselected', function( event ) {
    142 			if ( isView( event.targetClone ) ) {
    143 				event.targetClone = editor.getDoc().createTextNode(
    144 					window.decodeURIComponent( editor.dom.getAttrib( event.targetClone, 'data-wpview-text' ) )
    145 				);
    146 			}
    147 		} );
    148 
    149 		// Clean up URLs for easier processing.
    150 		editor.on( 'pastepreprocess', function( event ) {
    151 			var content = event.content;
    152 
    153 			if ( content ) {
    154 				content = tinymce.trim( content.replace( /<[^>]+>/g, '' ) );
    155 
    156 				if ( /^https?:\/\/\S+$/i.test( content ) ) {
    157 					event.content = content;
    158 				}
    159 			}
    160 		} );
    161 
    162 		// Show the view type in the element path.
    163 		editor.on( 'resolvename', function( event ) {
    164 			if ( isView( event.target ) ) {
    165 				event.name = editor.dom.getAttrib( event.target, 'data-wpview-type' ) || 'object';
    166 			}
    167 		} );
    168 
    169 		// See `media` plugin.
    170 		editor.on( 'click keyup', function() {
    171 			var node = editor.selection.getNode();
    172 
    173 			if ( isView( node ) ) {
    174 				if ( editor.dom.getAttrib( node, 'data-mce-selected' ) ) {
    175 					node.setAttribute( 'data-mce-selected', '2' );
    176 				}
    177 			}
    178 		} );
    179 
    180 		editor.addButton( 'wp_view_edit', {
    181 			tooltip: 'Edit|button', // '|button' is not displayed, only used for context.
    182 			icon: 'dashicon dashicons-edit',
    183 			onclick: function() {
    184 				var node = editor.selection.getNode();
    185 
    186 				if ( isView( node ) ) {
    187 					wp.mce.views.edit( editor, node );
    188 				}
    189 			}
    190 		} );
    191 
    192 		editor.addButton( 'wp_view_remove', {
    193 			tooltip: 'Remove',
    194 			icon: 'dashicon dashicons-no',
    195 			onclick: function() {
    196 				editor.fire( 'cut' );
    197 			}
    198 		} );
    199 
    200 		editor.once( 'preinit', function() {
    201 			var toolbar;
    202 
    203 			if ( editor.wp && editor.wp._createToolbar ) {
    204 				toolbar = editor.wp._createToolbar( [
    205 					'wp_view_edit',
    206 					'wp_view_remove'
    207 				] );
    208 
    209 				editor.on( 'wptoolbar', function( event ) {
    210 					if ( ! event.collapsed && isView( event.element ) ) {
    211 						event.toolbar = toolbar;
    212 					}
    213 				} );
    214 			}
    215 		} );
    216 
    217 		editor.wp = editor.wp || {};
    218 		editor.wp.getView = noop;
    219 		editor.wp.setViewCursor = noop;
    220 
    221 		return {
    222 			getView: noop
    223 		};
    224 	} );
    225 } )( window.tinymce );