wp/wp-includes/js/tinymce/plugins/wpview/editor_plugin_src.js
changeset 0 d970ebf37754
equal deleted inserted replaced
-1:000000000000 0:d970ebf37754
       
     1 /**
       
     2  * WordPress View plugin.
       
     3  */
       
     4 
       
     5 (function() {
       
     6 	var VK = tinymce.VK,
       
     7 		TreeWalker = tinymce.dom.TreeWalker,
       
     8 		selected;
       
     9 
       
    10 	tinymce.create('tinymce.plugins.wpView', {
       
    11 		init : function( editor, url ) {
       
    12 			var wpView = this;
       
    13 
       
    14 			// Check if the `wp.mce` API exists.
       
    15 			if ( typeof wp === 'undefined' || ! wp.mce )
       
    16 				return;
       
    17 
       
    18 			editor.onPreInit.add( function( editor ) {
       
    19 				// Add elements so we can set `contenteditable` to false.
       
    20 				editor.schema.addValidElements('div[*],span[*]');
       
    21 			});
       
    22 
       
    23 			// When the editor's content changes, scan the new content for
       
    24 			// matching view patterns, and transform the matches into
       
    25 			// view wrappers. Since the editor's DOM is outdated at this point,
       
    26 			// we'll wait to render the views.
       
    27 			editor.onBeforeSetContent.add( function( editor, o ) {
       
    28 				if ( ! o.content )
       
    29 					return;
       
    30 
       
    31 				o.content = wp.mce.view.toViews( o.content );
       
    32 			});
       
    33 
       
    34 			// When the editor's content has been updated and the DOM has been
       
    35 			// processed, render the views in the document.
       
    36 			editor.onSetContent.add( function( editor, o ) {
       
    37 				wp.mce.view.render( editor.getDoc() );
       
    38 			});
       
    39 
       
    40 			editor.onInit.add( function( editor ) {
       
    41 
       
    42 				// When a view is selected, ensure content that is being pasted
       
    43 				// or inserted is added to a text node (instead of the view).
       
    44 				editor.selection.onBeforeSetContent.add( function( selection, o ) {
       
    45 					var view = wpView.getParentView( selection.getNode() ),
       
    46 						walker, target;
       
    47 
       
    48 					// If the selection is not within a view, bail.
       
    49 					if ( ! view )
       
    50 						return;
       
    51 
       
    52 					// If there are no additional nodes or the next node is a
       
    53 					// view, create a text node after the current view.
       
    54 					if ( ! view.nextSibling || wpView.isView( view.nextSibling ) ) {
       
    55 						target = editor.getDoc().createTextNode('');
       
    56 						editor.dom.insertAfter( target, view );
       
    57 
       
    58 					// Otherwise, find the next text node.
       
    59 					} else {
       
    60 						walker = new TreeWalker( view.nextSibling, view.nextSibling );
       
    61 						target = walker.next();
       
    62 					}
       
    63 
       
    64 					// Select the `target` text node.
       
    65 					selection.select( target );
       
    66 					selection.collapse( true );
       
    67 				});
       
    68 
       
    69 				// When the selection's content changes, scan any new content
       
    70 				// for matching views and immediately render them.
       
    71 				//
       
    72 				// Runs on paste and on inserting nodes/html.
       
    73 				editor.selection.onSetContent.add( function( selection, o ) {
       
    74 					if ( ! o.context )
       
    75 						return;
       
    76 
       
    77 					var node = selection.getNode();
       
    78 
       
    79 					if ( ! node.innerHTML )
       
    80 						return;
       
    81 
       
    82 					node.innerHTML = wp.mce.view.toViews( node.innerHTML );
       
    83 					wp.mce.view.render( node );
       
    84 				});
       
    85 			});
       
    86 
       
    87 			// When the editor's contents are being accessed as a string,
       
    88 			// transform any views back to their text representations.
       
    89 			editor.onPostProcess.add( function( editor, o ) {
       
    90 				if ( ( ! o.get && ! o.save ) || ! o.content )
       
    91 					return;
       
    92 
       
    93 				o.content = wp.mce.view.toText( o.content );
       
    94 			});
       
    95 
       
    96 			// Triggers when the selection is changed.
       
    97 			// Add the event handler to the top of the stack.
       
    98 			editor.onNodeChange.addToTop( function( editor, controlManager, node, collapsed, o ) {
       
    99 				var view = wpView.getParentView( node );
       
   100 
       
   101 				// Update the selected view.
       
   102 				if ( view ) {
       
   103 					wpView.select( view );
       
   104 
       
   105 					// Prevent the selection from propagating to other plugins.
       
   106 					return false;
       
   107 
       
   108 				// If we've clicked off of the selected view, deselect it.
       
   109 				} else {
       
   110 					wpView.deselect();
       
   111 				}
       
   112 			});
       
   113 
       
   114 			editor.onKeyDown.addToTop( function( editor, event ) {
       
   115 				var keyCode = event.keyCode,
       
   116 					view, instance;
       
   117 
       
   118 				// If a view isn't selected, let the event go on its merry way.
       
   119 				if ( ! selected )
       
   120 					return;
       
   121 
       
   122 				// If the caret is not within the selected view, deselect the
       
   123 				// view and bail.
       
   124 				view = wpView.getParentView( editor.selection.getNode() );
       
   125 				if ( view !== selected ) {
       
   126 					wpView.deselect();
       
   127 					return;
       
   128 				}
       
   129 
       
   130 				// If delete or backspace is pressed, delete the view.
       
   131 				if ( keyCode === VK.DELETE || keyCode === VK.BACKSPACE ) {
       
   132 					if ( (instance = wp.mce.view.instance( selected )) ) {
       
   133 						instance.remove();
       
   134 						wpView.deselect();
       
   135 					}
       
   136 				}
       
   137 
       
   138 				// Let keypresses that involve the command or control keys through.
       
   139 				// Also, let any of the F# keys through.
       
   140 				if ( event.metaKey || event.ctrlKey || ( keyCode >= 112 && keyCode <= 123 ) )
       
   141 					return;
       
   142 
       
   143 				event.preventDefault();
       
   144 			});
       
   145 		},
       
   146 
       
   147 		getParentView : function( node ) {
       
   148 			while ( node ) {
       
   149 				if ( this.isView( node ) )
       
   150 					return node;
       
   151 
       
   152 				node = node.parentNode;
       
   153 			}
       
   154 		},
       
   155 
       
   156 		isView : function( node ) {
       
   157 			return (/(?:^|\s)wp-view-wrap(?:\s|$)/).test( node.className );
       
   158 		},
       
   159 
       
   160 		select : function( view ) {
       
   161 			if ( view === selected )
       
   162 				return;
       
   163 
       
   164 			this.deselect();
       
   165 			selected = view;
       
   166 			wp.mce.view.select( selected );
       
   167 		},
       
   168 
       
   169 		deselect : function() {
       
   170 			if ( selected )
       
   171 				wp.mce.view.deselect( selected );
       
   172 			selected = null;
       
   173 		},
       
   174 
       
   175 		getInfo : function() {
       
   176 			return {
       
   177 				longname  : 'WordPress Views',
       
   178 				author    : 'WordPress',
       
   179 				authorurl : 'http://wordpress.org',
       
   180 				infourl   : 'http://wordpress.org',
       
   181 				version   : '1.0'
       
   182 			};
       
   183 		}
       
   184 	});
       
   185 
       
   186 	// Register plugin
       
   187 	tinymce.PluginManager.add( 'wpview', tinymce.plugins.wpView );
       
   188 })();