WordPress.org

Make WordPress Core

Changeset 22210


Ignore:
Timestamp:
10/12/2012 03:28:22 AM (7 years ago)
Author:
koopersmith
Message:

MCE Views: First pass at keystroke and insertion handling.

  • When a MCE view is selected, normal keystrokes (those without command/control) are blocked.
  • Backspace/delete will successfully remove the view.
  • Arrow handling will be added at a later point.
  • When a MCE view is selected and content is pasted or injected (e.g. when an attachment is added), the content is added to the first text node after the view. If the view is at the end of the document or the next element is another view, a text node is injected into the DOM immediately after the selected view.

see #21390, #21812, #21813, #21815.

Location:
trunk/wp-includes/js
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/wp-includes/js/mce-view.js

    r22208 r22210  
    312312            $( '.wp-view-wrap', scope ).each( function() {
    313313                var wrapper = $(this),
    314                     id = wrapper.data('wp-view'),
    315                     view = instances[ id ];
     314                    view = wp.mce.view.instance( this );
    316315
    317316                if ( ! view )
     
    358357        attrs: function( content ) {
    359358            return wp.mce.view.removeInternalAttrs( wp.html.attrs( content ) );
     359        },
     360
     361        // ### instance( scope )
     362        //
     363        // Accepts a MCE view wrapper `node` (i.e. a node with the
     364        // `wp-view-wrap` class).
     365        instance: function( node ) {
     366            var id = $( node ).data('wp-view');
     367
     368            if ( id )
     369                return instances[ id ];
    360370        },
    361371
  • trunk/wp-includes/js/tinymce/plugins/wpview/editor_plugin_src.js

    r22208 r22210  
    44
    55(function() {
    6 
     6    var VK = tinymce.VK,
     7        TreeWalker = tinymce.dom.TreeWalker,
     8        selected;
    79
    810    tinymce.create('tinymce.plugins.wpView', {
    911        init : function( editor, url ) {
    10             var wpView = this,
    11                 selected;
     12            var wpView = this;
    1213
    1314            // Check if the `wp.mce` API exists.
     
    3940            editor.onInit.add( function( editor ) {
    4041
     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
    4169                // When the selection's content changes, scan any new content
    4270                // for matching views and immediately render them.
     
    6795
    6896            // Triggers when the selection is changed.
    69             editor.onNodeChange.add( function( editor, controlManager, node, collapsed, o ) {
     97            // Add the event handler to the top of the stack.
     98            editor.onNodeChange.addToTop( function( editor, controlManager, node, collapsed, o ) {
    7099                var view = wpView.getParentView( node );
    71100
     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
    72108                // If we've clicked off of the selected view, deselect it.
    73                 if ( selected && selected !== view )
    74                     wp.mce.view.deselect( selected );
     109                } else {
     110                    wpView.deselect();
     111                }
     112            });
    75113
    76                 // Bail if we're not selecting another view.
    77                 if ( ! view )
     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 )
    78120                    return;
    79121
    80                 // Update the selected view.
    81                 selected = view;
    82                 wp.mce.view.select( selected );
     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                }
    83129
    84                 // Prevent the selection from propagating to other plugins.
    85                 return false;
     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();
    86144            });
    87145        },
     
    89147        getParentView : function( node ) {
    90148            while ( node ) {
    91                 if ( /(?:^|\s)wp-view-wrap(?:\s|$)/.test( node.className ) )
     149                if ( this.isView( node ) )
    92150                    return node;
    93151
    94152                node = node.parentNode;
    95153            }
     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;
    96173        },
    97174
Note: See TracChangeset for help on using the changeset viewer.