Index: /CKEditor/trunk/CHANGES.html
===================================================================
--- /CKEditor/trunk/CHANGES.html (revision 4545)
+++ /CKEditor/trunk/CHANGES.html (revision 4546)
@@ -81,4 +81,5 @@
#4455 : Fixed unable to start editing when image inside document not loaded.
#4517 : Fixed 'dialog_backgroundCoverColor' doesn't work on IE6.
+ #3165 : Fixed enter key in empty list item before nested one result in collapsed line.
CKEditor 3.0.1
Index: /CKEditor/trunk/_source/core/dom/element.js
===================================================================
--- /CKEditor/trunk/_source/core/dom/element.js (revision 4545)
+++ /CKEditor/trunk/_source/core/dom/element.js (revision 4546)
@@ -628,4 +628,5 @@
/**
* Gets the first child node of this element.
+ * @param {Function} evaluator Filtering the result node.
* @returns {CKEDITOR.dom.node} The first child node or null if not
* available.
@@ -635,8 +636,12 @@
* alert( first.getName() ); // "b"
*/
- getFirst : function()
- {
- var $ = this.$.firstChild;
- return $ ? new CKEDITOR.dom.node( $ ) : null;
+ getFirst : function( evaluator )
+ {
+ var first = this.$.firstChild,
+ retval = first && new CKEDITOR.dom.node( first );
+ if ( retval && evaluator && !evaluator( retval ) )
+ retval = retval.getNext( evaluator );
+
+ return retval;
},
Index: /CKEditor/trunk/_source/core/dom/walker.js
===================================================================
--- /CKEditor/trunk/_source/core/dom/walker.js (revision 4545)
+++ /CKEditor/trunk/_source/core/dom/walker.js (revision 4546)
@@ -409,3 +409,23 @@
};
};
+
+ /**
+ * Whether the node is invisible in wysiwyg mode.
+ * @param isReject
+ */
+ CKEDITOR.dom.walker.invisible = function( isReject )
+ {
+ var whitespace = CKEDITOR.dom.walker.whitespaces();
+ return function( node )
+ {
+ // Nodes that take no spaces in wysiwyg:
+ // 1. White-spaces but not including NBSP;
+ // 2. Empty inline elements, e.g. we're checking here
+ // 'offsetHeight' instead of 'offsetWidth' for properly excluding
+ // all sorts of empty paragraph, e.g.
.
+ var isInvisible = whitespace( node ) || node.is && !node.$.offsetHeight;
+ return isReject ^ isInvisible;
+ };
+ };
+
})();
Index: /CKEditor/trunk/_source/plugins/enterkey/plugin.js
===================================================================
--- /CKEditor/trunk/_source/plugins/enterkey/plugin.js (revision 4545)
+++ /CKEditor/trunk/_source/plugins/enterkey/plugin.js (revision 4546)
@@ -102,9 +102,10 @@
{
// If the next block is an with another list tree as the first
- // child, we'll need to append a placeholder or the list item
+ // child, we'll need to append a filler (
/NBSP) or the list item
// wouldn't be editable. (#1420)
- if ( nextBlock.is( 'li' ) && ( node = nextBlock.getFirst() )
- && node.is && node.is( 'ul', 'ol') )
- nextBlock.insertBefore( doc.createText( '\xa0' ), node );
+ if ( nextBlock.is( 'li' )
+ && ( node = nextBlock.getFirst( CKEDITOR.dom.walker.invisible( true ) ) )
+ && node.is && node.is( 'ul', 'ol' ) )
+ ( CKEDITOR.env.ie ? doc.createText( '\xa0' ) : doc.createElement( 'br' ) ).insertBefore( node );
// Move the selection to the end block.
Index: /CKEditor/trunk/_source/plugins/list/plugin.js
===================================================================
--- /CKEditor/trunk/_source/plugins/list/plugin.js (revision 4545)
+++ /CKEditor/trunk/_source/plugins/list/plugin.js (revision 4546)
@@ -540,4 +540,63 @@
};
+ var dtd = CKEDITOR.dtd;
+ var tailNbspRegex = /[\t\r\n ]*(?: |\xa0)$/;
+
+ function indexOfFirstChildElement( element, tagNameList )
+ {
+ var children = element.children,
+ child,
+ length = children.length;
+ for ( var i = 0; i < length; i++ )
+ {
+ child = children[ i ];
+ if( child.name && ( child.name in tagNameList ) )
+ return i;
+ }
+ }
+
+ function getExtendNestedListFilter( isHtmlFilter )
+ {
+ // An element filter function that corrects nested list start in an empty
+ // list item for better displaying/outputting. (#3165)
+ return function( listItem )
+ {
+ var children = listItem.children,
+ firstNestedListIndex = indexOfFirstChildElement( listItem, dtd.$list ),
+ firstNestedList = children[ firstNestedListIndex ],
+ nodeBefore = firstNestedList && firstNestedList.previous,
+ tailNbspmatch;
+
+ if( nodeBefore
+ && ( nodeBefore.name && nodeBefore.name == 'br'
+ || nodeBefore.value && ( tailNbspmatch = nodeBefore.value.match( tailNbspRegex ) ) ) )
+ {
+ var fillerNode = nodeBefore;
+
+ // Always use 'nbsp' as filler node if we found a nested list appear
+ // in front of a list item.
+ if ( !( tailNbspmatch && tailNbspmatch.index ) && fillerNode == children[ 0 ] )
+ children[ 0 ] = ( isHtmlFilter || CKEDITOR.env.ie ) ?
+ new CKEDITOR.htmlParser.text( '\xa0' ) :
+ new CKEDITOR.htmlParser.element( 'br', {} );
+
+ // Otherwise the filler is not needed anymore.
+ else if ( fillerNode.name == 'br' )
+ children.splice( firstNestedListIndex - 1, 1 );
+ else
+ fillerNode.value = fillerNode.value.replace( tailNbspRegex, '' );
+ }
+
+ };
+ }
+
+ var defaultListDataFilterRules = { elements : {} };
+ for( var i in dtd.$listItem )
+ defaultListDataFilterRules.elements[ i ] = getExtendNestedListFilter();
+
+ var defaultListHtmlFilterRules = { elements : {} };
+ for( i in dtd.$listItem )
+ defaultListHtmlFilterRules.elements[ i ] = getExtendNestedListFilter( true );
+
CKEDITOR.plugins.add( 'list',
{
@@ -567,4 +626,14 @@
},
+ afterInit : function ( editor )
+ {
+ var dataProcessor = editor.dataProcessor;
+ if( dataProcessor )
+ {
+ dataProcessor.dataFilter.addRules( defaultListDataFilterRules );
+ dataProcessor.htmlFilter.addRules( defaultListHtmlFilterRules );
+ }
+ },
+
requires : [ 'domiterator' ]
} );
Index: /CKEditor/trunk/_source/plugins/selection/plugin.js
===================================================================
--- /CKEditor/trunk/_source/plugins/selection/plugin.js (revision 4545)
+++ /CKEditor/trunk/_source/plugins/selection/plugin.js (revision 4546)
@@ -953,4 +953,8 @@
};
})();
+( function()
+{
+var notWhitespaces = CKEDITOR.dom.walker.whitespaces( true );
+var fillerTextRegex = /\ufeff|\u00a0/;
CKEDITOR.dom.range.prototype.select =
@@ -997,5 +1001,7 @@
// Actually, we are using this flag just to avoid using this hack in all
// situations, but just on those needed.
- isStartMarkerAlone = forceExpand || !startNode.hasPrevious() || ( startNode.getPrevious().is && startNode.getPrevious().is( 'br' ) );
+ var next = startNode.getNext( notWhitespaces );
+ isStartMarkerAlone = ( !( next && next.getText && next.getText().match( fillerTextRegex ) ) // already a filler there?
+ && ( forceExpand || !startNode.hasPrevious() || ( startNode.getPrevious().is && startNode.getPrevious().is( 'br' ) ) ) );
// Append a temporary before the selection.
@@ -1081,2 +1087,3 @@
selection.addRange( nativeRange );
};
+} )();