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

Commit

Permalink
Merge pull request #1820 from ckeditor/i/6154
Browse files Browse the repository at this point in the history
Other: Allow selection on object elements. Closes ckeditor/ckeditor5#6154.
  • Loading branch information
Reinmar authored Feb 3, 2020
2 parents c102fc3 + 007da5b commit 0dec72d
Show file tree
Hide file tree
Showing 2 changed files with 322 additions and 54 deletions.
54 changes: 34 additions & 20 deletions src/model/utils/selection-post-fixer.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,20 +92,7 @@ function selectionPostFixer( writer, model ) {

// If any of ranges were corrected update the selection.
if ( wasFixed ) {
// The above algorithm might create ranges that intersects each other when selection contains more then one range.
// This is case happens mostly on Firefox which creates multiple ranges for selected table.
let fixedRanges = ranges;

// Fixing selection with many ranges usually breaks the selection in Firefox. As only Firefox supports multiple selection ranges
// we simply create one continuous range from fixed selection ranges (even if they are not adjacent).
if ( ranges.length > 1 ) {
const selectionStart = ranges[ 0 ].start;
const selectionEnd = ranges[ ranges.length - 1 ].end;

fixedRanges = [ new Range( selectionStart, selectionEnd ) ];
}

writer.setSelection( fixedRanges, { backward: selection.isBackward } );
writer.setSelection( mergeIntersectingRanges( ranges ), { backward: selection.isBackward } );
}
}

Expand Down Expand Up @@ -140,18 +127,17 @@ function tryFixingCollapsedRange( range, schema ) {
return null;
}

if ( !nearestSelectionRange.isCollapsed ) {
return nearestSelectionRange;
}

const fixedPosition = nearestSelectionRange.start;

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

// Check single node selection (happens in tables).
if ( fixedPosition.nodeAfter && schema.isLimit( fixedPosition.nodeAfter ) ) {
return new Range( fixedPosition, Position._createAfter( fixedPosition.nodeAfter ) );
}

return new Range( fixedPosition );
}

Expand Down Expand Up @@ -263,6 +249,35 @@ function checkSelectionOnNonLimitElements( start, end, schema ) {
return startIsOnBlock || endIsOnBlock;
}

// Returns a minimal non-intersecting array of ranges.
//
// @param {Array.<module:engine/model/range~Range>} ranges
// @returns {Array.<module:engine/model/range~Range>}
function mergeIntersectingRanges( ranges ) {
const nonIntersectingRanges = [];

// First range will always be fine.
nonIntersectingRanges.push( ranges.shift() );

for ( const range of ranges ) {
const previousRange = nonIntersectingRanges.pop();

if ( range.isIntersecting( previousRange ) ) {
// Get the sum of two ranges.
const start = previousRange.start.isAfter( range.start ) ? range.start : previousRange.start;
const end = previousRange.end.isAfter( range.end ) ? previousRange.end : range.end;

const merged = new Range( start, end );
nonIntersectingRanges.push( merged );
} else {
nonIntersectingRanges.push( previousRange );
nonIntersectingRanges.push( range );
}
}

return nonIntersectingRanges;
}

// Checks if node exists and if it's an object.
//
// @param {module:engine/model/node~Node} node
Expand All @@ -271,4 +286,3 @@ function checkSelectionOnNonLimitElements( start, end, schema ) {
function isInObject( node, schema ) {
return node && schema.isObject( node );
}

Loading

0 comments on commit 0dec72d

Please sign in to comment.