// check(Start|End)OfBlock.\r
function getCheckStartEndBlockEvalFunction( isStart )\r
{\r
- var hadBr = false, bookmarkEvaluator = CKEDITOR.dom.walker.bookmark( true );\r
+ var skipBogus = false,\r
+ bookmarkEvaluator = CKEDITOR.dom.walker.bookmark( true ),\r
+ nbspRegExp = /^[\t\r\n ]*(?: |\xa0)$/;\r
+\r
return function( node )\r
{\r
// First ignore bookmark nodes.\r
\r
if ( node.type == CKEDITOR.NODE_TEXT )\r
{\r
+ // Skip the block filler NBSP.\r
+ if ( CKEDITOR.env.ie &&\r
+ nbspRegExp.test( node.getText() ) &&\r
+ !skipBogus &&\r
+ !( isStart && node.getNext() ) )\r
+ {\r
+ skipBogus = true;\r
+ }\r
// If there's any visible text, then we're not at the start.\r
- if ( node.hasAscendant( 'pre' ) || CKEDITOR.tools.trim( node.getText() ).length )\r
+ else if ( node.hasAscendant( 'pre' ) || CKEDITOR.tools.trim( node.getText() ).length )\r
return false;\r
}\r
else if ( node.type == CKEDITOR.NODE_ELEMENT )\r
// at the start.\r
if ( !inlineChildReqElements[ node.getName() ] )\r
{\r
- // If we're working at the end-of-block, forgive the first <br /> in non-IE\r
- // browsers.\r
- if ( !isStart && !CKEDITOR.env.ie && node.getName() == 'br' && !hadBr )\r
- hadBr = true;\r
+ // Skip the padding block br.\r
+ if ( !CKEDITOR.env.ie &&\r
+ node.is( 'br' ) &&\r
+ !skipBogus &&\r
+ !( isStart && node.getNext() ) )\r
+ {\r
+ skipBogus = true;\r
+ }\r
else\r
return false;\r
}\r
if ( serializable )\r
{\r
baseId = 'cke_bm_' + CKEDITOR.tools.getNextNumber();\r
- startNode.setAttribute( 'id', baseId + 'S' );\r
+ startNode.setAttribute( 'id', baseId + ( collapsed ? 'C' : 'S' ) );\r
}\r
\r
// If collapsed, the endNode will not be created.\r
this.moveToPosition( startNode, CKEDITOR.POSITION_AFTER_END );\r
\r
return {\r
- startNode : serializable ? baseId + 'S' : startNode,\r
+ startNode : serializable ? baseId + ( collapsed ? 'C' : 'S' ) : startNode,\r
endNode : serializable ? baseId + 'E' : endNode,\r
serializable : serializable,\r
collapsed : collapsed\r
return false;\r
}\r
\r
- // Antecipate the trim() call here, so the walker will not make\r
- // changes to the DOM, which would not get reflected into this\r
- // range otherwise.\r
- this.trim();\r
-\r
// We need to grab the block element holding the start boundary, so\r
// let's use an element path for it.\r
var path = new CKEDITOR.dom.elementPath( this.startContainer );\r
return false;\r
}\r
\r
- // Antecipate the trim() call here, so the walker will not make\r
- // changes to the DOM, which would not get reflected into this\r
- // range otherwise.\r
- this.trim();\r
-\r
// We need to grab the block element holding the start boundary, so\r
// let's use an element path for it.\r
var path = new CKEDITOR.dom.elementPath( this.endContainer );\r
*/\r
moveToElementEditablePosition : function( el, isMoveToEnd )\r
{\r
+ var nbspRegExp = /^[\t\r\n ]*(?: |\xa0)$/;\r
+\r
function nextDFS( node, childOnly )\r
{\r
var next;\r
\r
- if ( node.type == CKEDITOR.NODE_ELEMENT\r
- && node.isEditable( false )\r
- && !CKEDITOR.dtd.$nonEditable[ node.getName() ] )\r
- {\r
+ if ( node.type == CKEDITOR.NODE_ELEMENT && node.isEditable( false ) )\r
next = node[ isMoveToEnd ? 'getLast' : 'getFirst' ]( nonWhitespaceOrBookmarkEval );\r
- }\r
\r
if ( !childOnly && !next )\r
next = node[ isMoveToEnd ? 'getPrevious' : 'getNext' ]( nonWhitespaceOrBookmarkEval );\r
return next;\r
}\r
\r
+ // Handle non-editable element e.g. HR.\r
+ if ( el.type == CKEDITOR.NODE_ELEMENT && !el.isEditable( false ) )\r
+ {\r
+ this.moveToPosition( el, isMoveToEnd ?\r
+ CKEDITOR.POSITION_AFTER_END :\r
+ CKEDITOR.POSITION_BEFORE_START );\r
+ return true;\r
+ }\r
+\r
var found = 0;\r
\r
while ( el )\r
// Stop immediately if we've found a text node.\r
if ( el.type == CKEDITOR.NODE_TEXT )\r
{\r
- this.moveToPosition( el, isMoveToEnd ?\r
+ // Put cursor before block filler.\r
+ if ( isMoveToEnd && this.checkEndOfBlock() && nbspRegExp.test( el.getText() ) )\r
+ this.moveToPosition( el, CKEDITOR.POSITION_BEFORE_START );\r
+ else\r
+ this.moveToPosition( el, isMoveToEnd ?\r
CKEDITOR.POSITION_AFTER_END :\r
CKEDITOR.POSITION_BEFORE_START );\r
found = 1;\r
CKEDITOR.POSITION_AFTER_START );\r
found = 1;\r
}\r
+ // Put cursor before padding block br.\r
+ else if ( isMoveToEnd && el.is( 'br' ) && this.checkEndOfBlock() )\r
+ this.moveToPosition( el, CKEDITOR.POSITION_BEFORE_START );\r
}\r
\r
el = nextDFS( el, found );\r