This repository has been archived by the owner on Jun 26, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 40
getNearestSelectionPosition changes #717
Merged
Changes from 1 commit
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
71d7624
Change behavior and rename model Document#getNearestSelectionPosition…
szymonkups b8c8396
Minor docs fixes and refactoring.
szymonkups 589d996
Merge branch 'master' into t/712
Reinmar d3a3ae9
Improved wording.
Reinmar 890e50c
Minor changes in model document tests.
szymonkups b1241d9
Fixed DataController insertContent test to not log warning.
szymonkups File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -280,51 +280,55 @@ export default class Document { | |
} | ||
|
||
/** | ||
* Basing on given `position`, finds and returns a {@link module:engine/model/position~Position Position} instance that is nearest | ||
* to that `position` and is a correct position for selection. A position is correct for selection if | ||
* text node can be placed at that position. | ||
* Basing on given `position`, finds and returns a {@link module:engine/model/range~Range Range} instance that is | ||
* nearest to that `position` and is a correct range for selection. | ||
* | ||
* If no correct position is found, the first position in given `position` root is returned. This can happen if no node | ||
* has been added to the root or it may mean incorrect model document state. | ||
* Correct selection range might be collapsed - when it's located in position where text node can be placed. | ||
* Non-collapsed range is returned when selection can be placed around element marked as "object" in | ||
* {@link module:engine/model/schema~Schema schema}. | ||
* | ||
* @param {module:engine/model/position~Position} position Reference position where selection position should be looked for. | ||
* @returns {module:engine/model/position~Position|null} Nearest selection position. | ||
* Direction of searching for nearest correct selection range can be specified as: | ||
* * `both` - searching will be performed in both ways, | ||
* * `forward` - searching will be performed only forward, | ||
* * `backward` - searching will be performed only backward. | ||
* | ||
* When valid selection range cannot be found, `null` value is returned. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. " |
||
* | ||
* @param {module:engine/model/position~Position} position Reference position where new selection range should be looked for. | ||
* @param {'both'|'forward'|'backward'} [direction='both'] Search direction. | ||
* @returns {module:engine/model/range~Range|null} Nearest selection range or `null` if one cannot be found. | ||
*/ | ||
getNearestSelectionPosition( position ) { | ||
getNearestSelectionRange( position, direction = 'both' ) { | ||
// Return collapsed range if provided position is valid. | ||
if ( this.schema.check( { name: '$text', inside: position } ) ) { | ||
return Position.createFromPosition( position ); | ||
return new Range( position ); | ||
} | ||
|
||
const backwardWalker = new TreeWalker( { startPosition: position, direction: 'backward' } ); | ||
const forwardWalker = new TreeWalker( { startPosition: position } ); | ||
let backwardWalker; | ||
let forwardWalker; | ||
|
||
let done = false; | ||
|
||
while ( !done ) { | ||
done = true; | ||
if ( direction == 'both' || direction == 'backward' ) { | ||
backwardWalker = new TreeWalker( { startPosition: position, direction: 'backward' } ); | ||
} | ||
|
||
let step = backwardWalker.next(); | ||
if ( direction == 'both' || direction == 'forward' ) { | ||
forwardWalker = new TreeWalker( { startPosition: position } ); | ||
} | ||
|
||
if ( !step.done ) { | ||
if ( this.schema.check( { name: '$text', inside: step.value.nextPosition } ) ) { | ||
return step.value.nextPosition; | ||
} | ||
for ( let data of getWalkersData( backwardWalker, forwardWalker ) ) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Walker has no data. Walker walks ;). Maybe |
||
const type = ( data.walker == backwardWalker ? 'elementEnd' : 'elementStart' ); | ||
const value = data.value; | ||
|
||
done = false; | ||
if ( value.type == type && this.schema.objects.has( value.item.name ) ) { | ||
return Range.createOn( value.item ); | ||
} | ||
|
||
step = forwardWalker.next(); | ||
|
||
if ( !step.done ) { | ||
if ( this.schema.check( { name: '$text', inside: step.value.nextPosition } ) ) { | ||
return step.value.nextPosition; | ||
} | ||
|
||
done = false; | ||
if ( this.schema.check( { name: '$text', inside: value.nextPosition } ) ) { | ||
return new Range( value.nextPosition ); | ||
} | ||
} | ||
|
||
return new Position( position.root, [ 0 ] ); | ||
return null; | ||
} | ||
|
||
/** | ||
|
@@ -370,9 +374,10 @@ export default class Document { | |
|
||
// Find the first position where the selection can be put. | ||
const position = new Position( defaultRoot, [ 0 ] ); | ||
const selectionPosition = this.getNearestSelectionPosition( position ); | ||
const nearestRange = this.getNearestSelectionRange( position ); | ||
|
||
return new Range( selectionPosition ); | ||
// If valid selection range is not found - return range collapsed at the beginning of the root. | ||
return nearestRange || new Range( position ); | ||
} | ||
|
||
/** | ||
|
@@ -447,3 +452,42 @@ function validateTextNodePosition( rangeBoundary ) { | |
|
||
return true; | ||
} | ||
|
||
// Generator function returning values from provided walkers, switching between them at each iteration. If only one walker | ||
// is provided it will return data only from that walker. | ||
// | ||
// @param {module:engine/module/treewalker~TreeWalker} [backward] Walker iterating in backward direction. | ||
// @param {module:engine/module/treewalker~TreeWalker} [forward] Walker iterating in forward direction. | ||
// @returns {Iterable.<Object>} Object returned at each iteration contains `value` and `walker` (informing which walker returned | ||
// given value) fields. | ||
function *getWalkersData( backward, forward ) { | ||
let done = false; | ||
|
||
while ( !done ) { | ||
done = true; | ||
|
||
if ( backward ) { | ||
const step = backward.next(); | ||
|
||
if ( !step.done ) { | ||
done = false; | ||
yield { | ||
walker: backward, | ||
value: step.value | ||
}; | ||
} | ||
} | ||
|
||
if ( forward ) { | ||
const step = forward.next(); | ||
|
||
if ( !step.done ) { | ||
done = false; | ||
yield { | ||
walker: forward, | ||
value: step.value | ||
}; | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to have every case like this commented. We're not testing else because it's a safe check for some unpredictable edge cases. Also, having a
log.warning()
would be good there, like in the other cases in this method.