CKEDITOR.dtd[ node.getName() ][ '#' ];\r
}\r
\r
- // Merge the visual line content at the cursor range into the block.\r
+ // Join visually two block lines.\r
function joinNextLineToCursor( editor, cursor, nextCursor )\r
{\r
editor.fire( 'saveSnapshot' );\r
var bm = cursor.createBookmark();\r
\r
// Kill original bogus;\r
- var currentPath = new CKEDITOR.dom.elementPath( cursor.startContainer );\r
- var currentLi = currentPath.lastElement.getAscendant( 'li', 1 );\r
-\r
- var bogus = currentPath.block.getBogus();\r
- bogus && bogus.remove();\r
+ var currentPath = new CKEDITOR.dom.elementPath( cursor.startContainer ),\r
+ pathBlock = currentPath.block,\r
+ currentBlock = currentPath.lastElement.getAscendant( 'li', 1 ) || pathBlock,\r
+ nextPath = new CKEDITOR.dom.elementPath( nextCursor.startContainer ),\r
+ nextLi = nextPath.contains( CKEDITOR.dtd.$listItem ),\r
+ nextList = nextPath.contains( CKEDITOR.dtd.$list ),\r
+ last;\r
+\r
+ // Remove bogus node the current block/pseudo block.\r
+ if ( pathBlock )\r
+ {\r
+ var bogus = pathBlock.getBogus();\r
+ bogus && bogus.remove();\r
+ }\r
+ else if ( nextList )\r
+ {\r
+ last = nextList.getPrevious( nonEmpty );\r
+ if ( last && blockBogus( last ) )\r
+ last.remove();\r
+ }\r
\r
// Kill the tail br in extracted.\r
- var last = frag.getLast();\r
+ last = frag.getLast();\r
if ( last && last.type == CKEDITOR.NODE_ELEMENT && last.is( 'br' ) )\r
last.remove();\r
\r
else\r
cursor.startContainer.append( frag );\r
\r
- var nextPath = new CKEDITOR.dom.elementPath( nextCursor.startContainer );\r
- var nextLi = nextCursor.startContainer.getAscendant( 'li', 1 );\r
-\r
// Move the sub list nested in the next list item.\r
if ( nextLi )\r
{\r
if ( sublist )\r
{\r
// If next line is in the sub list of the current list item.\r
- if ( currentLi.contains( nextLi ) )\r
+ if ( currentBlock.contains( nextLi ) )\r
{\r
mergeChildren( sublist, nextLi.getParent(), nextLi );\r
sublist.remove();\r
}\r
// Migrate the sub list to current list item.\r
else\r
- currentLi.append( sublist );\r
+ currentBlock.append( sublist );\r
}\r
}\r
\r
if ( !range.collapsed )\r
return;\r
\r
+ var path = new CKEDITOR.dom.elementPath( range.startContainer );\r
var isBackspace = key == 8;\r
var body = editor.document.getBody();\r
var walker = new CKEDITOR.dom.walker( range.clone() );\r
walker.evaluator = function( node ) { return nonEmpty( node ) && !blockBogus( node ); };\r
\r
+ // Backspace/Del behavior at the start/end of table is handled in core.\r
+ walker.guard = function( node, isOut ) { return !( isOut && node.type == CKEDITOR.NODE_ELEMENT && node.is( 'table' ) ); };\r
+\r
var cursor = range.clone();\r
\r
if ( isBackspace )\r
{\r
var previous, joinWith;\r
\r
- var path = new CKEDITOR.dom.elementPath( range.startContainer );\r
-\r
// Join a sub list's first line, with the previous visual line in parent.\r
if ( ( previous = path.contains( listNodeNames ) ) &&\r
range.checkBoundaryOfElement( previous, CKEDITOR.START ) &&\r
joinNextLineToCursor( editor, cursor, range );\r
evt.cancel();\r
}\r
+ else\r
+ {\r
+ var list = path.contains( listNodeNames ), li;\r
+ // Backspace pressed at the start of list outdents the first list item. (#9129)\r
+ if ( list && range.checkBoundaryOfElement( list, CKEDITOR.START ) )\r
+ {\r
+ li = list.getFirst( nonEmpty );\r
+\r
+ if ( range.checkBoundaryOfElement( li, CKEDITOR.START ) )\r
+ {\r
+ previous = list.getPrevious( nonEmpty );\r
+\r
+ // Only if the list item contains a sub list, do nothing but\r
+ // simply move cursor backward one character.\r
+ if ( getSubList( li ) )\r
+ {\r
+ if ( previous ) {\r
+ range.moveToElementEditEnd( previous );\r
+ range.select();\r
+ }\r
+\r
+ evt.cancel();\r
+ }\r
+ else\r
+ {\r
+ editor.execCommand( 'outdent' );\r
+ evt.cancel();\r
+ }\r
+ }\r
+ }\r
+ }\r
}\r
else\r
{\r
- var li = range.startContainer.getAscendant( 'li', 1 );\r
+ var next, nextLine;\r
+ li = range.startContainer.getAscendant( 'li', 1 );\r
+\r
if ( li )\r
{\r
walker.range.setEndAt( body, CKEDITOR.POSITION_BEFORE_END );\r
// Indicate cursor at the visual end of an list item.\r
var isAtEnd = 0;\r
\r
- var next = walker.next();\r
+ next = walker.next();\r
\r
// When list item contains a sub list.\r
if ( next && next.type == CKEDITOR.NODE_ELEMENT &&\r
if ( isAtEnd && next )\r
{\r
// Put cursor range there.\r
- var nextLine = range.clone();\r
+ nextLine = range.clone();\r
nextLine.moveToElementEditStart( next );\r
\r
joinNextLineToCursor( editor, cursor, nextLine );\r
evt.cancel();\r
}\r
}\r
+ else\r
+ {\r
+ // Handle Del key pressed before the list.\r
+ walker.range.setEndAt( body, CKEDITOR.POSITION_BEFORE_END );\r
+ next = walker.next();\r
+\r
+ if ( next && next.type == CKEDITOR.NODE_ELEMENT &&\r
+ next.getName() in listNodeNames )\r
+ {\r
+ // The start <li>\r
+ next = next.getFirst( nonEmpty );\r
+\r
+ // Simply remove the current empty block, move cursor to the\r
+ // subsequent list.\r
+ if ( path.block &&\r
+ range.checkStartOfBlock() &&\r
+ range.checkEndOfBlock() )\r
+ {\r
+ path.block.remove();\r
+ range.moveToElementEditStart( next );\r
+ range.select();\r
+ evt.cancel();\r
+ }\r
+\r
+ // Preventing the default (merge behavior), but simply move\r
+ // the cursor one character forward if subsequent list item\r
+ // contains sub list.\r
+ else if ( getSubList( next ) )\r
+ {\r
+ range.moveToElementEditStart( next );\r
+ range.select();\r
+ evt.cancel();\r
+ }\r
+ // Merge the first list item with the current line.\r
+ else\r
+ {\r
+ nextLine = range.clone();\r
+ nextLine.moveToElementEditStart( next );\r
+ joinNextLineToCursor( editor, cursor, nextLine );\r
+ evt.cancel();\r
+ }\r
+ }\r
+ }\r
}\r
\r
// The backspace/del could potentially put cursor at a bad position,\r