TinyMCE wpView:

- When a view is selected, pressing the up or down arrow key should move the caret to the block above or below the view.
- Selecting some text that touches the view and deleting it should not remove part of the view.
- Show/hide the "fake" carets on editor focus/blur.
- Don't create new paragraphs before or after a view on pressing the arrow keys or delete key. Paragraphs are created on pressing Enter.
Props avryl, see #28595.

git-svn-id: https://develop.svn.wordpress.org/trunk@29010 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Andrew Ozz 2014-07-07 01:20:53 +00:00
parent c9f0cb6295
commit f30a20c9a4
3 changed files with 78 additions and 18 deletions

View File

@ -8,7 +8,8 @@ tinymce.PluginManager.add( 'wpview', function( editor ) {
VK = tinymce.util.VK, VK = tinymce.util.VK,
TreeWalker = tinymce.dom.TreeWalker, TreeWalker = tinymce.dom.TreeWalker,
toRemove = false, toRemove = false,
cursorInterval, lastKeyDownNode, setViewCursorTries; firstFocus = true,
cursorInterval, lastKeyDownNode, setViewCursorTries, focus;
function getView( node ) { function getView( node ) {
return editor.dom.getParent( node, function( node ) { return editor.dom.getParent( node, function( node ) {
@ -349,10 +350,30 @@ tinymce.PluginManager.add( 'wpview', function( editor ) {
selection = editor.selection, selection = editor.selection,
node = selection.getNode(), node = selection.getNode(),
view = getView( node ), view = getView( node ),
cursorBefore, cursorAfter; cursorBefore, cursorAfter,
range, clonedRange, tempRange;
lastKeyDownNode = node; lastKeyDownNode = 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 );
}
}
if ( ! view ) { if ( ! view ) {
return; return;
} }
@ -375,30 +396,26 @@ tinymce.PluginManager.add( 'wpview', function( editor ) {
} }
} }
} else { } else {
handleEnter( view, true ); setViewCursor( true, view );
} }
event.preventDefault(); event.preventDefault();
} else if ( cursorAfter && ( keyCode === VK.DOWN || keyCode === VK.RIGHT ) ) { } else if ( cursorAfter && ( keyCode === VK.DOWN || keyCode === VK.RIGHT ) ) {
if ( view.nextSibling ) { if ( view.nextSibling ) {
if ( getView( view.nextSibling ) ) { if ( getView( view.nextSibling ) ) {
setViewCursor( false, view.nextSibling ); setViewCursor( keyCode === VK.RIGHT, view.nextSibling );
} else { } else {
selection.setCursorLocation( view.nextSibling, 0 ); selection.setCursorLocation( view.nextSibling, 0 );
} }
} else {
handleEnter( view );
} }
event.preventDefault(); event.preventDefault();
} else if ( cursorBefore && ( keyCode === VK.UP || keyCode === VK.LEFT ) ) { } else if ( cursorBefore && ( keyCode === VK.UP || keyCode === VK.LEFT ) ) {
if ( view.previousSibling ) { if ( view.previousSibling ) {
if ( getView( view.previousSibling ) ) { if ( getView( view.previousSibling ) ) {
setViewCursor( true, view.previousSibling ); setViewCursor( keyCode === VK.UP, view.previousSibling );
} else { } else {
selection.select( view.previousSibling, true ); selection.select( view.previousSibling, true );
selection.collapse(); selection.collapse();
} }
} else {
handleEnter( view, true );
} }
event.preventDefault(); event.preventDefault();
} else if ( cursorBefore && keyCode === VK.DOWN ) { } else if ( cursorBefore && keyCode === VK.DOWN ) {
@ -409,7 +426,7 @@ tinymce.PluginManager.add( 'wpview', function( editor ) {
selection.setCursorLocation( view.nextSibling, 0 ); selection.setCursorLocation( view.nextSibling, 0 );
} }
} else { } else {
handleEnter( view ); setViewCursor( false, view );
} }
event.preventDefault(); event.preventDefault();
} else if ( ( cursorAfter && keyCode === VK.LEFT ) || ( cursorBefore && keyCode === VK.RIGHT ) ) { } else if ( ( cursorAfter && keyCode === VK.LEFT ) || ( cursorBefore && keyCode === VK.RIGHT ) ) {
@ -465,12 +482,35 @@ tinymce.PluginManager.add( 'wpview', function( editor ) {
return; return;
} }
if ( keyCode === VK.LEFT || keyCode === VK.UP ) { if ( keyCode === VK.LEFT ) {
setViewCursor( true, view ); setViewCursor( true, view );
deselect(); deselect();
} else if ( keyCode === VK.RIGHT || keyCode === VK.DOWN ) { } else if ( keyCode === VK.UP ) {
if ( view.previousSibling ) {
if ( getView( view.previousSibling ) ) {
setViewCursor( true, view.previousSibling );
} else {
selection.select( view.previousSibling, true );
selection.collapse();
}
} else {
setViewCursor( true, view );
}
deselect();
} else if ( keyCode === VK.RIGHT ) {
setViewCursor( false, view ); setViewCursor( false, view );
deselect(); deselect();
} else if ( keyCode === VK.DOWN ) {
if ( view.nextSibling ) {
if ( getView( view.nextSibling ) ) {
setViewCursor( false, view.nextSibling );
} else {
selection.setCursorLocation( view.nextSibling, 0 );
}
} else {
setViewCursor( false, view );
}
deselect();
} else if ( keyCode === VK.ENTER ) { } else if ( keyCode === VK.ENTER ) {
handleEnter( view ); handleEnter( view );
} else if ( keyCode === VK.DELETE || keyCode === VK.BACKSPACE ) { } else if ( keyCode === VK.DELETE || keyCode === VK.BACKSPACE ) {
@ -511,6 +551,26 @@ tinymce.PluginManager.add( 'wpview', function( editor ) {
} }
}); });
editor.on( 'focus', function() {
var view;
focus = true;
editor.dom.addClass( editor.getBody(), 'has-focus' );
// Edge case: show the fake caret when the editor is focused for the first time
// and the first element is a view.
if ( firstFocus && ( view = getView( editor.getBody().firstChild ) ) ) {
setViewCursor( true, view );
}
firstFocus = false;
} );
editor.on( 'blur', function() {
focus = false;
editor.dom.removeClass( editor.getBody(), 'has-focus' );
} );
editor.on( 'nodechange', function( event ) { editor.on( 'nodechange', function( event ) {
var dom = editor.dom, var dom = editor.dom,
views = editor.dom.select( '.wpview-wrap' ), views = editor.dom.select( '.wpview-wrap' ),
@ -526,7 +586,7 @@ tinymce.PluginManager.add( 'wpview', function( editor ) {
dom.removeClass( views, 'wpview-selection-after' ); dom.removeClass( views, 'wpview-selection-after' );
dom.removeClass( views, 'wpview-cursor-hide' ); dom.removeClass( views, 'wpview-cursor-hide' );
if ( view ) { if ( view && editor.selection.isCollapsed() && focus ) {
if ( className === 'wpview-selection-before' || className === 'wpview-selection-after' ) { if ( className === 'wpview-selection-before' || className === 'wpview-selection-after' ) {
setViewCursorTries = 0; setViewCursorTries = 0;

View File

@ -241,8 +241,8 @@ audio {
user-select: text; user-select: text;
} }
.wpview-wrap.wpview-selection-before:before, .has-focus .wpview-wrap.wpview-selection-before:before,
.wpview-wrap.wpview-selection-after:before { .has-focus .wpview-wrap.wpview-selection-after:before {
content: ''; content: '';
margin: 0; margin: 0;
padding: 0; padding: 0;
@ -258,12 +258,12 @@ audio {
opacity: 1; opacity: 1;
} }
.wpview-wrap.wpview-selection-after:before { .has-focus .wpview-wrap.wpview-selection-after:before {
left: auto; left: auto;
right: -3px; right: -3px;
} }
.wpview-wrap.wpview-cursor-hide:before { .has-focus .wpview-wrap.wpview-cursor-hide:before {
opacity: 0; opacity: 0;
} }

View File

@ -18,7 +18,7 @@ $wp_db_version = 27916;
* *
* @global string $tinymce_version * @global string $tinymce_version
*/ */
$tinymce_version = '4028-20140630'; $tinymce_version = '4028-20140706';
/** /**
* Holds the required PHP version * Holds the required PHP version