From 30c933b7dccb968845e6e1b6546a5337fafbefa0 Mon Sep 17 00:00:00 2001 From: Piotr Jasiun Date: Mon, 2 Dec 2013 16:38:34 +0100 Subject: [PATCH 1/8] Makes code more readable and ready to future changes. --- core/dom/range.js | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/core/dom/range.js b/core/dom/range.js index 69af9790f3f..497fc293270 100644 --- a/core/dom/range.js +++ b/core/dom/range.js @@ -1116,17 +1116,16 @@ CKEDITOR.dom.range = function( root ) { commonReached = needsWhiteSpace = false; if ( container.type == CKEDITOR.NODE_TEXT ) { - // Check if there is any non-space text after the - // offset. Otherwise, container is null. - container = !CKEDITOR.tools.trim( container.substring( offset ) ).length && container; - - // If we found only whitespace in the node, it - // means that we'll need more whitespace to be able - // to expand. For example, can be expanded in - // "A [B]", but not in "A [B]". - needsWhiteSpace = !( container && container.getLength() ); + // Check if there is only white space after the offset. + if ( CKEDITOR.tools.trim( container.substring( offset ) ).length ) { + // If we found only whitespace in the node, it + // means that we'll need more whitespace to be able + // to expand. For example, can be expanded in + // "A [B]", but not in "A [B]". + needsWhiteSpace = true; + } else { + needsWhiteSpace = !container.getLength(); - if ( container ) { if ( !( sibling = container.getNext() ) ) enlargeable = container.getParent(); } From 965209d17025967e88bbf83effb68f7bddf7d1d1 Mon Sep 17 00:00:00 2001 From: Piotr Jasiun Date: Mon, 2 Dec 2013 17:24:20 +0100 Subject: [PATCH 2/8] Check id offset == container.length before enlarge end. --- core/dom/range.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/dom/range.js b/core/dom/range.js index 497fc293270..7c9729b6cfa 100644 --- a/core/dom/range.js +++ b/core/dom/range.js @@ -1126,7 +1126,9 @@ CKEDITOR.dom.range = function( root ) { } else { needsWhiteSpace = !container.getLength(); - if ( !( sibling = container.getNext() ) ) + // If we are at the end of container and this is the last text node + // we should enlarged end to the parent. + if ( offset == container.getLength() && !( sibling = container.getNext() ) ) enlargeable = container.getParent(); } } else { From abb35f58edf747f298dff2639080d74ec3ae4b76 Mon Sep 17 00:00:00 2001 From: Piotr Jasiun Date: Wed, 4 Dec 2013 14:24:36 +0100 Subject: [PATCH 3/8] Check whitespaces using walker instead of regexp. --- core/dom/range.js | 66 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 61 insertions(+), 5 deletions(-) diff --git a/core/dom/range.js b/core/dom/range.js index 7c9729b6cfa..14468d247e5 100644 --- a/core/dom/range.js +++ b/core/dom/range.js @@ -1115,6 +1115,53 @@ CKEDITOR.dom.range = function( root ) { enlargeable = sibling = null; commonReached = needsWhiteSpace = false; + function onlyWhiteSpaces( startContainer, startOffset ) { + // We need to enlarge range if there is white space at the end of the block, + // because it is not displayed in WYSIWYG mode and user can not select it. So + // "

foo[bar]

" should be changed to "

foo[bar ]

". On the other hand + // we should do nothing if we are not at the end of the block, so this should not + // be changed: "

[foo] bar

". + var walkerRange = new CKEDITOR.dom.range( boundary ); + walkerRange.setStart( startContainer, startOffset ); + // The guard will find the end of range so I put boundary here. + walkerRange.setEndAt( boundary, CKEDITOR.POSITION_BEFORE_END ); + + var walker = new CKEDITOR.dom.walker( walkerRange ), + node; + + walker.guard = function( node, movingOut ) { + // Stop if you exit block. + if ( node.type == CKEDITOR.NODE_ELEMENT && node.isBlockBoundary() ) + return false; + + // Stop if you exit contenteditable. + if ( node.type == CKEDITOR.NODE_ELEMENT && node.getAttribute( 'contenteditable' ) == 'false' ) + return false; + + return true; + }; + + while ( ( node = walker.next() ) ) { + if ( node.type != CKEDITOR.NODE_TEXT ) { + // Stop if you enter to any node (walker.next() will return node only + // it goes out, not if it is go into node). + return false; + } else { + // Trim the first node to startOffset. + if ( node != startContainer ) + siblingText = node.getText(); + else + siblingText = node.substring( startOffset ) + + // Check if it is white space. + if ( ( /[^\s\ufeff]/.test( siblingText ) ) ) + return false; + } + } + + return true; + } + if ( container.type == CKEDITOR.NODE_TEXT ) { // Check if there is only white space after the offset. if ( CKEDITOR.tools.trim( container.substring( offset ) ).length ) { @@ -1126,10 +1173,17 @@ CKEDITOR.dom.range = function( root ) { } else { needsWhiteSpace = !container.getLength(); - // If we are at the end of container and this is the last text node - // we should enlarged end to the parent. - if ( offset == container.getLength() && !( sibling = container.getNext() ) ) - enlargeable = container.getParent(); + if ( offset == container.getLength() ) { + // If we are at the end of container and this is the last text node, + // we should enlarge end to the parent. + if ( !( sibling = container.getNext() ) ) + enlargeable = container.getParent(); + } else { + // If we are in the middle on text node and there are only whitespaces + // till the end of block, we should enlarge element. + if ( onlyWhiteSpaces( container, offset ) ) + enlargeable = container.getParent(); + } } } else { // Get the node right after the boudary to be checked @@ -1166,7 +1220,9 @@ CKEDITOR.dom.range = function( root ) { if ( sibling.type == CKEDITOR.NODE_TEXT ) { siblingText = sibling.getText(); - if ( /[^\s\ufeff]/.test( siblingText ) ) + // Check if there are not whitespace characters till the end of editable. + // If so stop expanding. + if ( !onlyWhiteSpaces( sibling, 0 ) ) sibling = null; isWhiteSpace = /^[\s\ufeff]/.test( siblingText ); From 53459159842ff026035ddf7b9e70fc88e32c7f9d Mon Sep 17 00:00:00 2001 From: Piotr Jasiun Date: Fri, 3 Jan 2014 16:46:44 +0100 Subject: [PATCH 4/8] Removed unneeded condition from walker.guard. --- core/dom/range.js | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/core/dom/range.js b/core/dom/range.js index 14468d247e5..350f993be4f 100644 --- a/core/dom/range.js +++ b/core/dom/range.js @@ -1131,14 +1131,7 @@ CKEDITOR.dom.range = function( root ) { walker.guard = function( node, movingOut ) { // Stop if you exit block. - if ( node.type == CKEDITOR.NODE_ELEMENT && node.isBlockBoundary() ) - return false; - - // Stop if you exit contenteditable. - if ( node.type == CKEDITOR.NODE_ELEMENT && node.getAttribute( 'contenteditable' ) == 'false' ) - return false; - - return true; + return !( node.type == CKEDITOR.NODE_ELEMENT && node.isBlockBoundary() ); }; while ( ( node = walker.next() ) ) { From 1bce25451e13519e333ba86f3c481264250c0ca4 Mon Sep 17 00:00:00 2001 From: Piotr Jasiun Date: Fri, 3 Jan 2014 17:29:23 +0100 Subject: [PATCH 5/8] Compile regexp. --- core/dom/range.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/dom/range.js b/core/dom/range.js index 350f993be4f..9a3a9de90db 100644 --- a/core/dom/range.js +++ b/core/dom/range.js @@ -1127,7 +1127,8 @@ CKEDITOR.dom.range = function( root ) { walkerRange.setEndAt( boundary, CKEDITOR.POSITION_BEFORE_END ); var walker = new CKEDITOR.dom.walker( walkerRange ), - node; + node, + whitespaceRegexp = new RegExp( /[^\s\ufeff]/ ); walker.guard = function( node, movingOut ) { // Stop if you exit block. @@ -1147,7 +1148,7 @@ CKEDITOR.dom.range = function( root ) { siblingText = node.substring( startOffset ) // Check if it is white space. - if ( ( /[^\s\ufeff]/.test( siblingText ) ) ) + if ( ( whitespaceRegexp.test( siblingText ) ) ) return false; } } From 7842a7bf1fda3e6330018e2f2b312e4489dca0da Mon Sep 17 00:00:00 2001 From: Piotr Jasiun Date: Fri, 3 Jan 2014 17:38:11 +0100 Subject: [PATCH 6/8] Added comment to onlyWhiteSpaces. --- core/dom/range.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/core/dom/range.js b/core/dom/range.js index 9a3a9de90db..6b8e22197a3 100644 --- a/core/dom/range.js +++ b/core/dom/range.js @@ -1115,6 +1115,14 @@ CKEDITOR.dom.range = function( root ) { enlargeable = sibling = null; commonReached = needsWhiteSpace = false; + // Function check if there are only whitespaces from the given starting point + // (startContainer and startOffset) till the end on block. + // Examples ("[" is the start point): + // -

foo[

- will return true, + // -

foo[

- will return true, + // -

foo[ bar

- will return false, + // -

foo[ bar

- will return false, + // -

foo[

- will return false. function onlyWhiteSpaces( startContainer, startOffset ) { // We need to enlarge range if there is white space at the end of the block, // because it is not displayed in WYSIWYG mode and user can not select it. So From 94b1ee592d6761b2a433212336c0a598eb2776f2 Mon Sep 17 00:00:00 2001 From: Aleksander Nowodzinski Date: Tue, 7 Jan 2014 10:31:13 +0100 Subject: [PATCH 7/8] Re-used the regex. --- core/dom/range.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/core/dom/range.js b/core/dom/range.js index 6b8e22197a3..e97b52156a9 100644 --- a/core/dom/range.js +++ b/core/dom/range.js @@ -922,6 +922,8 @@ CKEDITOR.dom.range = function( root ) { * @param {Boolean} [excludeBrs=false] Whether include line-breaks when expanding. */ enlarge: function( unit, excludeBrs ) { + var leadingWhitespaceRegex = new RegExp( /[^\s\ufeff]/ ); + switch ( unit ) { case CKEDITOR.ENLARGE_INLINE: var enlargeInlineOnly = 1; @@ -1029,7 +1031,7 @@ CKEDITOR.dom.range = function( root ) { } else if ( sibling.type == CKEDITOR.NODE_TEXT ) { siblingText = sibling.getText(); - if ( /[^\s\ufeff]/.test( siblingText ) ) + if ( leadingWhitespaceRegex.test( siblingText ) ) sibling = null; isWhiteSpace = /[\s\ufeff]$/.test( siblingText ); @@ -1047,7 +1049,7 @@ CKEDITOR.dom.range = function( root ) { siblingText = sibling.getText(); - if ( ( /[^\s\ufeff]/ ).test( siblingText ) ) // Spaces + Zero Width No-Break Space (U+FEFF) + if ( leadingWhitespaceRegex.test( siblingText ) ) // Spaces + Zero Width No-Break Space (U+FEFF) sibling = null; else { var allChildren = sibling.$.getElementsByTagName( '*' ); @@ -1135,8 +1137,7 @@ CKEDITOR.dom.range = function( root ) { walkerRange.setEndAt( boundary, CKEDITOR.POSITION_BEFORE_END ); var walker = new CKEDITOR.dom.walker( walkerRange ), - node, - whitespaceRegexp = new RegExp( /[^\s\ufeff]/ ); + node; walker.guard = function( node, movingOut ) { // Stop if you exit block. @@ -1156,7 +1157,7 @@ CKEDITOR.dom.range = function( root ) { siblingText = node.substring( startOffset ) // Check if it is white space. - if ( ( whitespaceRegexp.test( siblingText ) ) ) + if ( leadingWhitespaceRegex.test( siblingText ) ) return false; } } @@ -1242,7 +1243,7 @@ CKEDITOR.dom.range = function( root ) { siblingText = sibling.getText(); - if ( ( /[^\s\ufeff]/ ).test( siblingText ) ) + if ( leadingWhitespaceRegex.test( siblingText ) ) sibling = null; else { allChildren = sibling.$.getElementsByTagName( '*' ); From 3ee3e3bdf8a346f36f7692998bac780b676049fb Mon Sep 17 00:00:00 2001 From: Piotr Jasiun Date: Tue, 7 Jan 2014 16:32:14 +0100 Subject: [PATCH 8/8] Changelog entry. --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index ceaf72f196b..96d35fee0e8 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -15,6 +15,7 @@ CKEditor 4 Changelog * [#11126](http://dev.ckeditor.com/ticket/11126): Fixed: Native undo executed once reached the bottom of snapshot stack. * [#11131](http://dev.ckeditor.com/ticket/11131): [[Divarea](http://ckeditor.com/addon/divarea)] Fixed: Error thrown when switching to source mode if selection was in widget's nested editable. * [#11139](http://dev.ckeditor.com/ticket/11139): [[Divarea](http://ckeditor.com/addon/divarea)] Fixed: Elements path is not cleared after switching to source mode. +* [#10778](http://dev.ckeditor.com/ticket/10778): Fix bug with range enlarge; range no longer expanded visible whitespace. ## CKEditor 4.3.1