Make WordPress Core

Changeset 29236


Ignore:
Timestamp:
07/19/2014 12:33:46 AM (11 years ago)
Author:
azaozz
Message:

TinyMCE wpView:

  • Typing something replaces a selected view.
  • Pressing backspace deletes the selection.
  • Pressing enter also deletes the selection.
  • Pasting something replaces the selection.
  • Also merge the different 'keydown' handlers.

Props avryl, fixes #28913.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/js/tinymce/plugins/wpview/plugin.js

    r29190 r29236  
    7777    }
    7878
    79     function handleEnter( view, before, keyCode ) {
     79    function handleEnter( view, before, key ) {
    8080        var dom = editor.dom,
    8181            padNode = dom.create( 'p' );
     
    9393        deselect();
    9494
    95         if ( before && keyCode === VK.ENTER ) {
     95        if ( before && key === VK.ENTER ) {
    9696            setViewCursor( before, view );
    9797        } else {
     
    337337    // (De)select views when arrow keys are used to navigate the content of the editor.
    338338    editor.on( 'keydown', function( event ) {
    339         if ( event.metaKey || event.ctrlKey || ( keyCode >= 112 && keyCode <= 123 ) ) {
    340             return;
    341         }
    342 
    343         if ( selected ) {
    344             return;
    345         }
    346 
    347         var keyCode = event.keyCode,
     339        var key = event.keyCode,
    348340            dom = editor.dom,
    349341            selection = editor.selection,
    350             node = selection.getNode(),
    351             view = getView( node ),
    352             cursorBefore, cursorAfter,
    353             range, clonedRange, tempRange;
    354 
    355         lastKeyDownNode = node;
    356 
    357         // Make sure we don't delete part of a view.
    358         // If the range ends or starts with the view, we'll need to trim it.
    359         if ( ! selection.isCollapsed() ) {
    360             range = selection.getRng();
    361 
    362             if ( view = getView( range.endContainer ) ) {
    363                 clonedRange = range.cloneRange();
    364                 selection.select( view.previousSibling, true );
    365                 selection.collapse();
    366                 tempRange = selection.getRng();
    367                 clonedRange.setEnd( tempRange.endContainer, tempRange.endOffset );
    368                 selection.setRng( clonedRange );
    369             } else if ( view = getView( range.startContainer ) ) {
    370                 clonedRange = range.cloneRange();
    371                 clonedRange.setStart( view.nextSibling, 0 );
    372                 selection.setRng( clonedRange );
    373             }
    374         }
    375 
    376         if ( ! view ) {
    377             return;
    378         }
    379 
    380         if ( ! ( ( cursorBefore = dom.hasClass( view, 'wpview-selection-before' ) ) ||
    381                 ( cursorAfter = dom.hasClass( view, 'wpview-selection-after' ) ) ) ) {
    382             return;
    383         }
    384 
    385         if ( ( cursorAfter && keyCode === VK.UP ) || ( cursorBefore && keyCode === VK.BACKSPACE ) ) {
    386             if ( view.previousSibling ) {
    387                 if ( getView( view.previousSibling ) ) {
    388                     setViewCursor( false, view.previousSibling );
     342            node, view, cursorBefore, cursorAfter,
     343            range, clonedRange, tempRange, remove;
     344
     345        if ( selected ) {
     346            // Let key presses that involve the command or control keys through.
     347            // Also, let any of the F# keys through.
     348            if ( event.metaKey || event.ctrlKey || ( key >= 112 && key <= 123 ) ) {
     349                // But remove the view when cmd/ctrl + x/backspace are pressed.
     350                if ( ( event.metaKey || event.ctrlKey ) && ( key === 88 || key === VK.BACKSPACE ) ) {
     351                    // We'll remove a cut view on keyup, otherwise the browser can't copy the content.
     352                    if ( key === 88 ) {
     353                        toRemove = selected;
     354                    } else {
     355                        editor.dom.remove( selected );
     356                    }
     357                }
     358                return;
     359            }
     360
     361            view = getView( selection.getNode() );
     362
     363            // If the caret is not within the selected view, deselect the view and bail.
     364            if ( view !== selected ) {
     365                deselect();
     366                return;
     367            }
     368
     369            if ( key === VK.LEFT ) {
     370                setViewCursor( true, view );
     371                event.preventDefault();
     372            } else if ( key === VK.UP ) {
     373                if ( view.previousSibling ) {
     374                    if ( getView( view.previousSibling ) ) {
     375                        setViewCursor( true, view.previousSibling );
     376                    } else {
     377                        deselect();
     378                        selection.select( view.previousSibling, true );
     379                        selection.collapse();
     380                    }
    389381                } else {
    390                     if ( dom.isEmpty( view.previousSibling ) && keyCode === VK.BACKSPACE ) {
    391                         dom.remove( view.previousSibling );
     382                    setViewCursor( true, view );
     383                }
     384                event.preventDefault();
     385            } else if ( key === VK.RIGHT ) {
     386                setViewCursor( false, view );
     387                event.preventDefault();
     388            } else if ( key === VK.DOWN ) {
     389                if ( view.nextSibling ) {
     390                    if ( getView( view.nextSibling ) ) {
     391                        setViewCursor( false, view.nextSibling );
     392                    } else {
     393                        deselect();
     394                        selection.setCursorLocation( view.nextSibling, 0 );
     395                    }
     396                } else {
     397                    setViewCursor( false, view );
     398                }
     399                event.preventDefault();
     400            // Ignore keys that don't insert anything.
     401            } else if ( ( key > 47 || VK.SPACEBAR || key === VK.ENTER || key === VK.DELETE || key === VK.BACKSPACE ) && key !== 144 && key !== 145 ) {
     402                editor.undoManager.transact( function() {
     403                    remove = selected;
     404                    handleEnter( selected );
     405                    dom.remove( remove );
     406                });
     407
     408                if ( key === VK.ENTER || key === VK.DELETE || key === VK.BACKSPACE ) {
     409                    event.preventDefault();
     410                }
     411            }
     412        } else {
     413            if ( event.metaKey || event.ctrlKey || ( key >= 112 && key <= 123 ) ) {
     414                return;
     415            }
     416
     417            node = selection.getNode();
     418            lastKeyDownNode = node;
     419            view = getView( node );
     420
     421            // Make sure we don't delete part of a view.
     422            // If the range ends or starts with the view, we'll need to trim it.
     423            if ( ! selection.isCollapsed() ) {
     424                range = selection.getRng();
     425
     426                if ( view = getView( range.endContainer ) ) {
     427                    clonedRange = range.cloneRange();
     428                    selection.select( view.previousSibling, true );
     429                    selection.collapse();
     430                    tempRange = selection.getRng();
     431                    clonedRange.setEnd( tempRange.endContainer, tempRange.endOffset );
     432                    selection.setRng( clonedRange );
     433                } else if ( view = getView( range.startContainer ) ) {
     434                    clonedRange = range.cloneRange();
     435                    clonedRange.setStart( view.nextSibling, 0 );
     436                    selection.setRng( clonedRange );
     437                }
     438            }
     439
     440            // Make sure we don't eat any content.
     441            if ( event.keyCode === VK.BACKSPACE ) {
     442                if ( editor.dom.isEmpty( node ) ) {
     443                    if ( view = getView( node.previousSibling ) ) {
     444                        setViewCursor( false, view );
     445                        editor.dom.remove( node );
     446                        event.preventDefault();
     447                        return;
     448                    }
     449                } else if ( ( range = selection.getRng() ) &&
     450                        range.startOffset === 0 &&
     451                        range.endOffset === 0 &&
     452                        ( view = getView( node.previousSibling ) ) ) {
     453                    setViewCursor( false, view );
     454                    event.preventDefault();
     455                    return;
     456                }
     457            }
     458
     459            if ( ! view ) {
     460                return;
     461            }
     462
     463            if ( ! ( ( cursorBefore = dom.hasClass( view, 'wpview-selection-before' ) ) ||
     464                    ( cursorAfter = dom.hasClass( view, 'wpview-selection-after' ) ) ) ) {
     465                return;
     466            }
     467
     468            if ( ( cursorAfter && key === VK.UP ) || ( cursorBefore && key === VK.BACKSPACE ) ) {
     469                if ( view.previousSibling ) {
     470                    if ( getView( view.previousSibling ) ) {
     471                        setViewCursor( false, view.previousSibling );
     472                    } else {
     473                        if ( dom.isEmpty( view.previousSibling ) && key === VK.BACKSPACE ) {
     474                            dom.remove( view.previousSibling );
     475                        } else {
     476                            selection.select( view.previousSibling, true );
     477                            selection.collapse();
     478                        }
     479                    }
     480                } else {
     481                    setViewCursor( true, view );
     482                }
     483                event.preventDefault();
     484            } else if ( cursorAfter && ( key === VK.DOWN || key === VK.RIGHT ) ) {
     485                if ( view.nextSibling ) {
     486                    if ( getView( view.nextSibling ) ) {
     487                        setViewCursor( key === VK.RIGHT, view.nextSibling );
     488                    } else {
     489                        selection.setCursorLocation( view.nextSibling, 0 );
     490                    }
     491                }
     492                event.preventDefault();
     493            } else if ( cursorBefore && ( key === VK.UP || key ===  VK.LEFT ) ) {
     494                if ( view.previousSibling ) {
     495                    if ( getView( view.previousSibling ) ) {
     496                        setViewCursor( key === VK.UP, view.previousSibling );
    392497                    } else {
    393498                        selection.select( view.previousSibling, true );
     
    395500                    }
    396501                }
    397             } else {
    398                 setViewCursor( true, view );
    399             }
    400             event.preventDefault();
    401         } else if ( cursorAfter && ( keyCode === VK.DOWN || keyCode === VK.RIGHT ) ) {
    402             if ( view.nextSibling ) {
    403                 if ( getView( view.nextSibling ) ) {
    404                     setViewCursor( keyCode === VK.RIGHT, view.nextSibling );
     502                event.preventDefault();
     503            } else if ( cursorBefore && key === VK.DOWN ) {
     504                if ( view.nextSibling ) {
     505                    if ( getView( view.nextSibling ) ) {
     506                        setViewCursor( true, view.nextSibling );
     507                    } else {
     508                        selection.setCursorLocation( view.nextSibling, 0 );
     509                    }
    405510                } else {
    406                     selection.setCursorLocation( view.nextSibling, 0 );
    407                 }
    408             }
    409             event.preventDefault();
    410         } else if ( cursorBefore && ( keyCode === VK.UP || keyCode ===  VK.LEFT ) ) {
    411             if ( view.previousSibling ) {
    412                 if ( getView( view.previousSibling ) ) {
    413                     setViewCursor( keyCode === VK.UP, view.previousSibling );
    414                 } else {
    415                     selection.select( view.previousSibling, true );
    416                     selection.collapse();
    417                 }
    418             }
    419             event.preventDefault();
    420         } else if ( cursorBefore && keyCode === VK.DOWN ) {
    421             if ( view.nextSibling ) {
    422                 if ( getView( view.nextSibling ) ) {
    423                     setViewCursor( true, view.nextSibling );
    424                 } else {
    425                     selection.setCursorLocation( view.nextSibling, 0 );
    426                 }
    427             } else {
    428                 setViewCursor( false, view );
    429             }
    430             event.preventDefault();
    431         } else if ( ( cursorAfter && keyCode === VK.LEFT ) || ( cursorBefore && keyCode === VK.RIGHT ) ) {
    432             select( view );
    433             event.preventDefault();
    434             event.stopImmediatePropagation();
    435         } else if ( cursorAfter && keyCode === VK.BACKSPACE ) {
    436             dom.remove( view );
    437             event.preventDefault();
    438         } else if ( cursorAfter ) {
    439             handleEnter( view );
    440         } else if ( cursorBefore ) {
    441             handleEnter( view , true, keyCode );
    442         }
    443 
    444         if ( keyCode === VK.ENTER ) {
    445             event.preventDefault();
    446         }
    447     });
    448 
    449     // Handle key presses for selected views.
    450     editor.on( 'keydown', function( event ) {
    451         var dom = editor.dom,
    452             keyCode = event.keyCode,
    453             selection = editor.selection,
    454             view;
    455 
    456         // If a view isn't selected, let the event go on its merry way.
    457         if ( ! selected ) {
    458             return;
    459         }
    460 
    461         // Let key presses that involve the command or control keys through.
    462         // Also, let any of the F# keys through.
    463         if ( event.metaKey || event.ctrlKey || ( keyCode >= 112 && keyCode <= 123 ) ) {
    464             // But remove the view when cmd/ctrl + x/backspace are pressed.
    465             if ( ( event.metaKey || event.ctrlKey ) && ( keyCode === 88 || keyCode === VK.BACKSPACE ) ) {
    466                 // We'll remove a cut view on keyup, otherwise the browser can't copy the content.
    467                 if ( keyCode === 88 ) {
    468                     toRemove = selected;
    469                 } else {
    470                     editor.dom.remove( selected );
    471                 }
    472             }
    473             return;
    474         }
    475 
    476         view = getView( selection.getNode() );
    477 
    478         // If the caret is not within the selected view, deselect the view and bail.
    479         if ( view !== selected ) {
    480             deselect();
    481             return;
    482         }
    483 
    484         if ( keyCode === VK.LEFT ) {
    485             setViewCursor( true, view );
    486         } else if ( keyCode === VK.UP ) {
    487             if ( view.previousSibling ) {
    488                 if ( getView( view.previousSibling ) ) {
    489                     setViewCursor( true, view.previousSibling );
    490                 } else {
    491                     deselect();
    492                     selection.select( view.previousSibling, true );
    493                     selection.collapse();
    494                 }
    495             } else {
    496                 setViewCursor( true, view );
    497             }
    498 
    499         } else if ( keyCode === VK.RIGHT ) {
    500             setViewCursor( false, view );
    501         } else if ( keyCode === VK.DOWN ) {
    502             if ( view.nextSibling ) {
    503                 if ( getView( view.nextSibling ) ) {
    504                     setViewCursor( false, view.nextSibling );
    505                 } else {
    506                     deselect();
    507                     selection.setCursorLocation( view.nextSibling, 0 );
    508                 }
    509             } else {
    510                 setViewCursor( false, view );
    511             }
    512         } else if ( keyCode === VK.ENTER ) {
    513             handleEnter( view );
    514         } else if ( keyCode === VK.DELETE || keyCode === VK.BACKSPACE ) {
    515             dom.remove( selected );
    516         }
    517 
    518         event.preventDefault();
    519     });
    520 
    521     // Make sure we don't eat any content.
    522     editor.on( 'keydown', function( event ) {
    523         var selection = editor.selection,
    524             node, range, view;
    525 
    526         if ( event.keyCode === VK.BACKSPACE ) {
    527             node = selection.getNode();
    528 
    529             if ( editor.dom.isEmpty( node ) ) {
    530                 if ( view = getView( node.previousSibling ) ) {
    531511                    setViewCursor( false, view );
    532                     editor.dom.remove( node );
    533                     event.preventDefault();
    534                 }
    535             } else if ( ( range = selection.getRng() ) &&
    536                     range.startOffset === 0 &&
    537                     range.endOffset === 0 &&
    538                     ( view = getView( node.previousSibling ) ) ) {
    539                 setViewCursor( false, view );
     512                }
     513                event.preventDefault();
     514            } else if ( ( cursorAfter && key === VK.LEFT ) || ( cursorBefore && key === VK.RIGHT ) ) {
     515                select( view );
     516                event.preventDefault();
     517            } else if ( cursorAfter && key === VK.BACKSPACE ) {
     518                editor.undoManager.transact( function() {
     519                    handleEnter( view );
     520                    dom.remove( view );
     521                });
     522                event.preventDefault();
     523            } else if ( cursorAfter ) {
     524                handleEnter( view );
     525            } else if ( cursorBefore ) {
     526                handleEnter( view , true, key );
     527            }
     528
     529            if ( key === VK.ENTER ) {
    540530                event.preventDefault();
    541531            }
     
    581571        clearInterval( cursorInterval );
    582572
    583         dom.removeClass( views, 'wpview-selection-before' );
    584         dom.removeClass( views, 'wpview-selection-after' );
    585         dom.removeClass( views, 'wpview-cursor-hide' );
     573        // This runs a lot and is faster than replacing each class separately
     574        tinymce.each( views, function ( view ) {
     575            if ( view.className ) {
     576                view.className = view.className.replace( / ?\bwpview-(?:selection-before|selection-after|cursor-hide)\b/g, '' );
     577            }
     578        });
    586579
    587580        if ( focus ) {
Note: See TracChangeset for help on using the changeset viewer.