Skip to content
This repository was archived by the owner on Jun 26, 2020. It is now read-only.

Commit 0dec72d

Browse files
authored
Merge pull request #1820 from ckeditor/i/6154
Other: Allow selection on object elements. Closes ckeditor/ckeditor5#6154.
2 parents c102fc3 + 007da5b commit 0dec72d

File tree

2 files changed

+322
-54
lines changed

2 files changed

+322
-54
lines changed

src/model/utils/selection-post-fixer.js

+34-20
Original file line numberDiff line numberDiff line change
@@ -92,20 +92,7 @@ function selectionPostFixer( writer, model ) {
9292

9393
// If any of ranges were corrected update the selection.
9494
if ( wasFixed ) {
95-
// The above algorithm might create ranges that intersects each other when selection contains more then one range.
96-
// This is case happens mostly on Firefox which creates multiple ranges for selected table.
97-
let fixedRanges = ranges;
98-
99-
// Fixing selection with many ranges usually breaks the selection in Firefox. As only Firefox supports multiple selection ranges
100-
// we simply create one continuous range from fixed selection ranges (even if they are not adjacent).
101-
if ( ranges.length > 1 ) {
102-
const selectionStart = ranges[ 0 ].start;
103-
const selectionEnd = ranges[ ranges.length - 1 ].end;
104-
105-
fixedRanges = [ new Range( selectionStart, selectionEnd ) ];
106-
}
107-
108-
writer.setSelection( fixedRanges, { backward: selection.isBackward } );
95+
writer.setSelection( mergeIntersectingRanges( ranges ), { backward: selection.isBackward } );
10996
}
11097
}
11198

@@ -140,18 +127,17 @@ function tryFixingCollapsedRange( range, schema ) {
140127
return null;
141128
}
142129

130+
if ( !nearestSelectionRange.isCollapsed ) {
131+
return nearestSelectionRange;
132+
}
133+
143134
const fixedPosition = nearestSelectionRange.start;
144135

145136
// Fixed position is the same as original - no need to return corrected range.
146137
if ( originalPosition.isEqual( fixedPosition ) ) {
147138
return null;
148139
}
149140

150-
// Check single node selection (happens in tables).
151-
if ( fixedPosition.nodeAfter && schema.isLimit( fixedPosition.nodeAfter ) ) {
152-
return new Range( fixedPosition, Position._createAfter( fixedPosition.nodeAfter ) );
153-
}
154-
155141
return new Range( fixedPosition );
156142
}
157143

@@ -263,6 +249,35 @@ function checkSelectionOnNonLimitElements( start, end, schema ) {
263249
return startIsOnBlock || endIsOnBlock;
264250
}
265251

252+
// Returns a minimal non-intersecting array of ranges.
253+
//
254+
// @param {Array.<module:engine/model/range~Range>} ranges
255+
// @returns {Array.<module:engine/model/range~Range>}
256+
function mergeIntersectingRanges( ranges ) {
257+
const nonIntersectingRanges = [];
258+
259+
// First range will always be fine.
260+
nonIntersectingRanges.push( ranges.shift() );
261+
262+
for ( const range of ranges ) {
263+
const previousRange = nonIntersectingRanges.pop();
264+
265+
if ( range.isIntersecting( previousRange ) ) {
266+
// Get the sum of two ranges.
267+
const start = previousRange.start.isAfter( range.start ) ? range.start : previousRange.start;
268+
const end = previousRange.end.isAfter( range.end ) ? previousRange.end : range.end;
269+
270+
const merged = new Range( start, end );
271+
nonIntersectingRanges.push( merged );
272+
} else {
273+
nonIntersectingRanges.push( previousRange );
274+
nonIntersectingRanges.push( range );
275+
}
276+
}
277+
278+
return nonIntersectingRanges;
279+
}
280+
266281
// Checks if node exists and if it's an object.
267282
//
268283
// @param {module:engine/model/node~Node} node
@@ -271,4 +286,3 @@ function checkSelectionOnNonLimitElements( start, end, schema ) {
271286
function isInObject( node, schema ) {
272287
return node && schema.isObject( node );
273288
}
274-

0 commit comments

Comments
 (0)