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. Built from https://develop.svn.wordpress.org/trunk@29236 git-svn-id: http://core.svn.wordpress.org/trunk@29020 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
parent
13d0a0a367
commit
1d637d85e0
|
@ -76,7 +76,7 @@ tinymce.PluginManager.add( 'wpview', function( editor ) {
|
||||||
editor.nodeChanged();
|
editor.nodeChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleEnter( view, before, keyCode ) {
|
function handleEnter( view, before, key ) {
|
||||||
var dom = editor.dom,
|
var dom = editor.dom,
|
||||||
padNode = dom.create( 'p' );
|
padNode = dom.create( 'p' );
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ tinymce.PluginManager.add( 'wpview', function( editor ) {
|
||||||
|
|
||||||
deselect();
|
deselect();
|
||||||
|
|
||||||
if ( before && keyCode === VK.ENTER ) {
|
if ( before && key === VK.ENTER ) {
|
||||||
setViewCursor( before, view );
|
setViewCursor( before, view );
|
||||||
} else {
|
} else {
|
||||||
editor.selection.setCursorLocation( padNode, 0 );
|
editor.selection.setCursorLocation( padNode, 0 );
|
||||||
|
@ -336,207 +336,197 @@ tinymce.PluginManager.add( 'wpview', function( editor ) {
|
||||||
|
|
||||||
// (De)select views when arrow keys are used to navigate the content of the editor.
|
// (De)select views when arrow keys are used to navigate the content of the editor.
|
||||||
editor.on( 'keydown', function( event ) {
|
editor.on( 'keydown', function( event ) {
|
||||||
if ( event.metaKey || event.ctrlKey || ( keyCode >= 112 && keyCode <= 123 ) ) {
|
var key = event.keyCode,
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( selected ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var keyCode = event.keyCode,
|
|
||||||
dom = editor.dom,
|
dom = editor.dom,
|
||||||
selection = editor.selection,
|
selection = editor.selection,
|
||||||
node = selection.getNode(),
|
node, view, cursorBefore, cursorAfter,
|
||||||
view = getView( node ),
|
range, clonedRange, tempRange, remove;
|
||||||
cursorBefore, cursorAfter,
|
|
||||||
range, clonedRange, tempRange;
|
|
||||||
|
|
||||||
lastKeyDownNode = node;
|
if ( selected ) {
|
||||||
|
// Let key presses that involve the command or control keys through.
|
||||||
// Make sure we don't delete part of a view.
|
// Also, let any of the F# keys through.
|
||||||
// If the range ends or starts with the view, we'll need to trim it.
|
if ( event.metaKey || event.ctrlKey || ( key >= 112 && key <= 123 ) ) {
|
||||||
if ( ! selection.isCollapsed() ) {
|
// But remove the view when cmd/ctrl + x/backspace are pressed.
|
||||||
range = selection.getRng();
|
if ( ( event.metaKey || event.ctrlKey ) && ( key === 88 || key === VK.BACKSPACE ) ) {
|
||||||
|
// We'll remove a cut view on keyup, otherwise the browser can't copy the content.
|
||||||
if ( view = getView( range.endContainer ) ) {
|
if ( key === 88 ) {
|
||||||
clonedRange = range.cloneRange();
|
toRemove = selected;
|
||||||
selection.select( view.previousSibling, true );
|
} else {
|
||||||
selection.collapse();
|
editor.dom.remove( selected );
|
||||||
tempRange = selection.getRng();
|
}
|
||||||
clonedRange.setEnd( tempRange.endContainer, tempRange.endOffset );
|
}
|
||||||
selection.setRng( clonedRange );
|
return;
|
||||||
} else if ( view = getView( range.startContainer ) ) {
|
|
||||||
clonedRange = range.cloneRange();
|
|
||||||
clonedRange.setStart( view.nextSibling, 0 );
|
|
||||||
selection.setRng( clonedRange );
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ( ! view ) {
|
view = getView( selection.getNode() );
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ! ( ( cursorBefore = dom.hasClass( view, 'wpview-selection-before' ) ) ||
|
// If the caret is not within the selected view, deselect the view and bail.
|
||||||
( cursorAfter = dom.hasClass( view, 'wpview-selection-after' ) ) ) ) {
|
if ( view !== selected ) {
|
||||||
return;
|
deselect();
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ( ( cursorAfter && keyCode === VK.UP ) || ( cursorBefore && keyCode === VK.BACKSPACE ) ) {
|
if ( key === VK.LEFT ) {
|
||||||
if ( view.previousSibling ) {
|
setViewCursor( true, view );
|
||||||
if ( getView( view.previousSibling ) ) {
|
event.preventDefault();
|
||||||
setViewCursor( false, view.previousSibling );
|
} else if ( key === VK.UP ) {
|
||||||
|
if ( view.previousSibling ) {
|
||||||
|
if ( getView( view.previousSibling ) ) {
|
||||||
|
setViewCursor( true, view.previousSibling );
|
||||||
|
} else {
|
||||||
|
deselect();
|
||||||
|
selection.select( view.previousSibling, true );
|
||||||
|
selection.collapse();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if ( dom.isEmpty( view.previousSibling ) && keyCode === VK.BACKSPACE ) {
|
setViewCursor( true, view );
|
||||||
dom.remove( view.previousSibling );
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
} else if ( key === VK.RIGHT ) {
|
||||||
|
setViewCursor( false, view );
|
||||||
|
event.preventDefault();
|
||||||
|
} else if ( key === VK.DOWN ) {
|
||||||
|
if ( view.nextSibling ) {
|
||||||
|
if ( getView( view.nextSibling ) ) {
|
||||||
|
setViewCursor( false, view.nextSibling );
|
||||||
|
} else {
|
||||||
|
deselect();
|
||||||
|
selection.setCursorLocation( view.nextSibling, 0 );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setViewCursor( false, view );
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
// Ignore keys that don't insert anything.
|
||||||
|
} else if ( ( key > 47 || VK.SPACEBAR || key === VK.ENTER || key === VK.DELETE || key === VK.BACKSPACE ) && key !== 144 && key !== 145 ) {
|
||||||
|
editor.undoManager.transact( function() {
|
||||||
|
remove = selected;
|
||||||
|
handleEnter( selected );
|
||||||
|
dom.remove( remove );
|
||||||
|
});
|
||||||
|
|
||||||
|
if ( key === VK.ENTER || key === VK.DELETE || key === VK.BACKSPACE ) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ( event.metaKey || event.ctrlKey || ( key >= 112 && key <= 123 ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
node = selection.getNode();
|
||||||
|
lastKeyDownNode = node;
|
||||||
|
view = getView( node );
|
||||||
|
|
||||||
|
// Make sure we don't delete part of a view.
|
||||||
|
// If the range ends or starts with the view, we'll need to trim it.
|
||||||
|
if ( ! selection.isCollapsed() ) {
|
||||||
|
range = selection.getRng();
|
||||||
|
|
||||||
|
if ( view = getView( range.endContainer ) ) {
|
||||||
|
clonedRange = range.cloneRange();
|
||||||
|
selection.select( view.previousSibling, true );
|
||||||
|
selection.collapse();
|
||||||
|
tempRange = selection.getRng();
|
||||||
|
clonedRange.setEnd( tempRange.endContainer, tempRange.endOffset );
|
||||||
|
selection.setRng( clonedRange );
|
||||||
|
} else if ( view = getView( range.startContainer ) ) {
|
||||||
|
clonedRange = range.cloneRange();
|
||||||
|
clonedRange.setStart( view.nextSibling, 0 );
|
||||||
|
selection.setRng( clonedRange );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure we don't eat any content.
|
||||||
|
if ( event.keyCode === VK.BACKSPACE ) {
|
||||||
|
if ( editor.dom.isEmpty( node ) ) {
|
||||||
|
if ( view = getView( node.previousSibling ) ) {
|
||||||
|
setViewCursor( false, view );
|
||||||
|
editor.dom.remove( node );
|
||||||
|
event.preventDefault();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if ( ( range = selection.getRng() ) &&
|
||||||
|
range.startOffset === 0 &&
|
||||||
|
range.endOffset === 0 &&
|
||||||
|
( view = getView( node.previousSibling ) ) ) {
|
||||||
|
setViewCursor( false, view );
|
||||||
|
event.preventDefault();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! view ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! ( ( cursorBefore = dom.hasClass( view, 'wpview-selection-before' ) ) ||
|
||||||
|
( cursorAfter = dom.hasClass( view, 'wpview-selection-after' ) ) ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ( cursorAfter && key === VK.UP ) || ( cursorBefore && key === VK.BACKSPACE ) ) {
|
||||||
|
if ( view.previousSibling ) {
|
||||||
|
if ( getView( view.previousSibling ) ) {
|
||||||
|
setViewCursor( false, view.previousSibling );
|
||||||
|
} else {
|
||||||
|
if ( dom.isEmpty( view.previousSibling ) && key === VK.BACKSPACE ) {
|
||||||
|
dom.remove( view.previousSibling );
|
||||||
|
} else {
|
||||||
|
selection.select( view.previousSibling, true );
|
||||||
|
selection.collapse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setViewCursor( true, view );
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
} else if ( cursorAfter && ( key === VK.DOWN || key === VK.RIGHT ) ) {
|
||||||
|
if ( view.nextSibling ) {
|
||||||
|
if ( getView( view.nextSibling ) ) {
|
||||||
|
setViewCursor( key === VK.RIGHT, view.nextSibling );
|
||||||
|
} else {
|
||||||
|
selection.setCursorLocation( view.nextSibling, 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
} else if ( cursorBefore && ( key === VK.UP || key === VK.LEFT ) ) {
|
||||||
|
if ( view.previousSibling ) {
|
||||||
|
if ( getView( view.previousSibling ) ) {
|
||||||
|
setViewCursor( key === VK.UP, view.previousSibling );
|
||||||
} else {
|
} else {
|
||||||
selection.select( view.previousSibling, true );
|
selection.select( view.previousSibling, true );
|
||||||
selection.collapse();
|
selection.collapse();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
event.preventDefault();
|
||||||
setViewCursor( true, view );
|
} else if ( cursorBefore && key === VK.DOWN ) {
|
||||||
}
|
if ( view.nextSibling ) {
|
||||||
event.preventDefault();
|
if ( getView( view.nextSibling ) ) {
|
||||||
} else if ( cursorAfter && ( keyCode === VK.DOWN || keyCode === VK.RIGHT ) ) {
|
setViewCursor( true, view.nextSibling );
|
||||||
if ( view.nextSibling ) {
|
} else {
|
||||||
if ( getView( view.nextSibling ) ) {
|
selection.setCursorLocation( view.nextSibling, 0 );
|
||||||
setViewCursor( keyCode === VK.RIGHT, view.nextSibling );
|
}
|
||||||
} else {
|
} else {
|
||||||
selection.setCursorLocation( view.nextSibling, 0 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
event.preventDefault();
|
|
||||||
} else if ( cursorBefore && ( keyCode === VK.UP || keyCode === VK.LEFT ) ) {
|
|
||||||
if ( view.previousSibling ) {
|
|
||||||
if ( getView( view.previousSibling ) ) {
|
|
||||||
setViewCursor( keyCode === VK.UP, view.previousSibling );
|
|
||||||
} else {
|
|
||||||
selection.select( view.previousSibling, true );
|
|
||||||
selection.collapse();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
event.preventDefault();
|
|
||||||
} else if ( cursorBefore && keyCode === VK.DOWN ) {
|
|
||||||
if ( view.nextSibling ) {
|
|
||||||
if ( getView( view.nextSibling ) ) {
|
|
||||||
setViewCursor( true, view.nextSibling );
|
|
||||||
} else {
|
|
||||||
selection.setCursorLocation( view.nextSibling, 0 );
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
setViewCursor( false, view );
|
|
||||||
}
|
|
||||||
event.preventDefault();
|
|
||||||
} else if ( ( cursorAfter && keyCode === VK.LEFT ) || ( cursorBefore && keyCode === VK.RIGHT ) ) {
|
|
||||||
select( view );
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopImmediatePropagation();
|
|
||||||
} else if ( cursorAfter && keyCode === VK.BACKSPACE ) {
|
|
||||||
dom.remove( view );
|
|
||||||
event.preventDefault();
|
|
||||||
} else if ( cursorAfter ) {
|
|
||||||
handleEnter( view );
|
|
||||||
} else if ( cursorBefore ) {
|
|
||||||
handleEnter( view , true, keyCode );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( keyCode === VK.ENTER ) {
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Handle key presses for selected views.
|
|
||||||
editor.on( 'keydown', function( event ) {
|
|
||||||
var dom = editor.dom,
|
|
||||||
keyCode = event.keyCode,
|
|
||||||
selection = editor.selection,
|
|
||||||
view;
|
|
||||||
|
|
||||||
// If a view isn't selected, let the event go on its merry way.
|
|
||||||
if ( ! selected ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Let key presses that involve the command or control keys through.
|
|
||||||
// Also, let any of the F# keys through.
|
|
||||||
if ( event.metaKey || event.ctrlKey || ( keyCode >= 112 && keyCode <= 123 ) ) {
|
|
||||||
// But remove the view when cmd/ctrl + x/backspace are pressed.
|
|
||||||
if ( ( event.metaKey || event.ctrlKey ) && ( keyCode === 88 || keyCode === VK.BACKSPACE ) ) {
|
|
||||||
// We'll remove a cut view on keyup, otherwise the browser can't copy the content.
|
|
||||||
if ( keyCode === 88 ) {
|
|
||||||
toRemove = selected;
|
|
||||||
} else {
|
|
||||||
editor.dom.remove( selected );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
view = getView( selection.getNode() );
|
|
||||||
|
|
||||||
// If the caret is not within the selected view, deselect the view and bail.
|
|
||||||
if ( view !== selected ) {
|
|
||||||
deselect();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( keyCode === VK.LEFT ) {
|
|
||||||
setViewCursor( true, view );
|
|
||||||
} else if ( keyCode === VK.UP ) {
|
|
||||||
if ( view.previousSibling ) {
|
|
||||||
if ( getView( view.previousSibling ) ) {
|
|
||||||
setViewCursor( true, view.previousSibling );
|
|
||||||
} else {
|
|
||||||
deselect();
|
|
||||||
selection.select( view.previousSibling, true );
|
|
||||||
selection.collapse();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
setViewCursor( true, view );
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if ( keyCode === VK.RIGHT ) {
|
|
||||||
setViewCursor( false, view );
|
|
||||||
} else if ( keyCode === VK.DOWN ) {
|
|
||||||
if ( view.nextSibling ) {
|
|
||||||
if ( getView( view.nextSibling ) ) {
|
|
||||||
setViewCursor( false, view.nextSibling );
|
|
||||||
} else {
|
|
||||||
deselect();
|
|
||||||
selection.setCursorLocation( view.nextSibling, 0 );
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
setViewCursor( false, view );
|
|
||||||
}
|
|
||||||
} else if ( keyCode === VK.ENTER ) {
|
|
||||||
handleEnter( view );
|
|
||||||
} else if ( keyCode === VK.DELETE || keyCode === VK.BACKSPACE ) {
|
|
||||||
dom.remove( selected );
|
|
||||||
}
|
|
||||||
|
|
||||||
event.preventDefault();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Make sure we don't eat any content.
|
|
||||||
editor.on( 'keydown', function( event ) {
|
|
||||||
var selection = editor.selection,
|
|
||||||
node, range, view;
|
|
||||||
|
|
||||||
if ( event.keyCode === VK.BACKSPACE ) {
|
|
||||||
node = selection.getNode();
|
|
||||||
|
|
||||||
if ( editor.dom.isEmpty( node ) ) {
|
|
||||||
if ( view = getView( node.previousSibling ) ) {
|
|
||||||
setViewCursor( false, view );
|
setViewCursor( false, view );
|
||||||
editor.dom.remove( node );
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
}
|
||||||
} else if ( ( range = selection.getRng() ) &&
|
event.preventDefault();
|
||||||
range.startOffset === 0 &&
|
} else if ( ( cursorAfter && key === VK.LEFT ) || ( cursorBefore && key === VK.RIGHT ) ) {
|
||||||
range.endOffset === 0 &&
|
select( view );
|
||||||
( view = getView( node.previousSibling ) ) ) {
|
event.preventDefault();
|
||||||
setViewCursor( false, view );
|
} else if ( cursorAfter && key === VK.BACKSPACE ) {
|
||||||
|
editor.undoManager.transact( function() {
|
||||||
|
handleEnter( view );
|
||||||
|
dom.remove( view );
|
||||||
|
});
|
||||||
|
event.preventDefault();
|
||||||
|
} else if ( cursorAfter ) {
|
||||||
|
handleEnter( view );
|
||||||
|
} else if ( cursorBefore ) {
|
||||||
|
handleEnter( view , true, key );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( key === VK.ENTER ) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -580,9 +570,12 @@ tinymce.PluginManager.add( 'wpview', function( editor ) {
|
||||||
|
|
||||||
clearInterval( cursorInterval );
|
clearInterval( cursorInterval );
|
||||||
|
|
||||||
dom.removeClass( views, 'wpview-selection-before' );
|
// This runs a lot and is faster than replacing each class separately
|
||||||
dom.removeClass( views, 'wpview-selection-after' );
|
tinymce.each( views, function ( view ) {
|
||||||
dom.removeClass( views, 'wpview-cursor-hide' );
|
if ( view.className ) {
|
||||||
|
view.className = view.className.replace( / ?\bwpview-(?:selection-before|selection-after|cursor-hide)\b/g, '' );
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if ( focus ) {
|
if ( focus ) {
|
||||||
if ( view ) {
|
if ( view ) {
|
||||||
|
|
File diff suppressed because one or more lines are too long
Binary file not shown.
Loading…
Reference in New Issue