|
9 | 9 |
|
10 | 10 | import ViewText from './text'; |
11 | 11 | import ViewPosition from './position'; |
| 12 | +import Selection from './selection'; |
12 | 13 | import { INLINE_FILLER, INLINE_FILLER_LENGTH, startsWithFiller, isInlineFiller, isBlockFiller } from './filler'; |
13 | 14 |
|
14 | 15 | import mix from '@ckeditor/ckeditor5-utils/src/mix'; |
15 | 16 | import diff from '@ckeditor/ckeditor5-utils/src/diff'; |
16 | 17 | import insertAt from '@ckeditor/ckeditor5-utils/src/dom/insertat'; |
17 | 18 | import remove from '@ckeditor/ckeditor5-utils/src/dom/remove'; |
| 19 | +import log from '@ckeditor/ckeditor5-utils/src/log'; |
18 | 20 | import ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin'; |
19 | 21 | import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror'; |
20 | 22 |
|
@@ -580,6 +582,17 @@ export default class Renderer { |
580 | 582 | return; |
581 | 583 | } |
582 | 584 |
|
| 585 | + if ( oldViewSelection && areSimilarSelections( oldViewSelection, this.selection ) ) { |
| 586 | + const data = { |
| 587 | + oldSelection: oldViewSelection, |
| 588 | + currentSelection: this.selection |
| 589 | + }; |
| 590 | + |
| 591 | + log.warn( 'renderer-skipped-selection-rendering: The selection was not rendered due to its similarity to the current one.', data ); |
| 592 | + |
| 593 | + return; |
| 594 | + } |
| 595 | + |
583 | 596 | // Multi-range selection is not available in most browsers, and, at least in Chrome, trying to |
584 | 597 | // set such selection, that is not continuous, throws an error. Because of that, we will just use anchor |
585 | 598 | // and focus of view selection. |
@@ -642,3 +655,35 @@ export default class Renderer { |
642 | 655 | } |
643 | 656 |
|
644 | 657 | mix( Renderer, ObservableMixin ); |
| 658 | + |
| 659 | +// Checks if two given selections are similar. Selections are considered similar if they are non-collapsed |
| 660 | +// and their trimmed (see {@link #_trimSelection}) representations are equal. |
| 661 | +// |
| 662 | +// @private |
| 663 | +// @param {module:engine/view/selection~Selection} selection1 |
| 664 | +// @param {module:engine/view/selection~Selection} selection2 |
| 665 | +// @returns {Boolean} |
| 666 | +function areSimilarSelections( selection1, selection2 ) { |
| 667 | + return !selection1.isCollapsed && trimSelection( selection1 ).isEqual( trimSelection( selection2 ) ); |
| 668 | +} |
| 669 | + |
| 670 | +// Creates a copy of a given selection with all of its ranges |
| 671 | +// trimmed (see {@link module:engine/view/range~Range#getTrimmed getTrimmed}). |
| 672 | +// |
| 673 | +// @private |
| 674 | +// @param {module:engine/view/selection~Selection} selection |
| 675 | +// @returns {module:engine/view/selection~Selection} Selection copy with all ranges trimmed. |
| 676 | +function trimSelection( selection ) { |
| 677 | + const newSelection = Selection.createFromSelection( selection ); |
| 678 | + const ranges = newSelection.getRanges(); |
| 679 | + |
| 680 | + let trimmedRanges = []; |
| 681 | + |
| 682 | + for ( let range of ranges ) { |
| 683 | + trimmedRanges.push( range.getTrimmed() ); |
| 684 | + } |
| 685 | + |
| 686 | + newSelection.setRanges( trimmedRanges, newSelection.isBackward ); |
| 687 | + |
| 688 | + return newSelection; |
| 689 | +} |
0 commit comments