Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion packages/ckeditor5-core/src/editor/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
* @module core/editor/editor
*/

/* global document */

import Context from '../context';
import Config from '@ckeditor/ckeditor5-utils/src/config';
import EditingController from '@ckeditor/ckeditor5-engine/src/controller/editingcontroller';
Expand Down Expand Up @@ -175,14 +177,16 @@ export default class Editor {
*/
this.data = new DataController( this.model, stylesProcessor );

const sourceElementRoot = config.sourceElementRoot ? config.sourceElementRoot : document;

/**
* The {@link module:engine/controller/editingcontroller~EditingController editing controller}.
* Controls user input and rendering the content for editing.
*
* @readonly
* @member {module:engine/controller/editingcontroller~EditingController}
*/
this.editing = new EditingController( this.model, stylesProcessor );
this.editing = new EditingController( this.model, stylesProcessor, sourceElementRoot );
this.editing.view.document.bind( 'isReadOnly' ).to( this );

/**
Expand Down
6 changes: 4 additions & 2 deletions packages/ckeditor5-engine/src/controller/editingcontroller.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/

/* global document */

/**
* @module engine/controller/editingcontroller
*/
Expand Down Expand Up @@ -33,7 +35,7 @@ export default class EditingController {
* @param {module:engine/model/model~Model} model Editing model.
* @param {module:engine/view/stylesmap~StylesProcessor} stylesProcessor The styles processor instance.
*/
constructor( model, stylesProcessor ) {
constructor( model, stylesProcessor, sourceElementRoot = document ) {
/**
* Editor model.
*
Expand All @@ -48,7 +50,7 @@ export default class EditingController {
* @readonly
* @member {module:engine/view/view~View}
*/
this.view = new View( stylesProcessor );
this.view = new View( stylesProcessor, sourceElementRoot );

/**
* Mapper which describes the model-view binding.
Expand Down
4 changes: 3 additions & 1 deletion packages/ckeditor5-engine/src/view/domconverter.js
Original file line number Diff line number Diff line change
Expand Up @@ -850,7 +850,9 @@ export default class DomConverter {
* @returns {Boolean}
*/
isDomSelectionBackward( selection ) {
if ( selection.isCollapsed ) {
// Due to a bug with .isCollapsed always returning true when the selection is from a shadowRoot, also check that the selection
// has no ranges or its range is collapsed. More info: https://bugs.chromium.org/p/chromium/issues/detail?id=447523
if ( selection.isCollapsed && ( selection.rangeCount === 0 || selection.getRangeAt( 0 ).collapsed ) ) {
return false;
}

Expand Down
13 changes: 10 additions & 3 deletions packages/ckeditor5-engine/src/view/observer/selectionobserver.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @module engine/view/observer/selectionobserver
*/

/* global setInterval, clearInterval */
/* global setInterval, clearInterval, document */

import Observer from './observer';
import MutationObserver from './mutationobserver';
Expand All @@ -26,7 +26,7 @@ import { debounce } from 'lodash-es';
* @extends module:engine/view/observer/observer~Observer
*/
export default class SelectionObserver extends Observer {
constructor( view ) {
constructor( view, sourceElementRoot = document ) {
super( view );

/**
Expand Down Expand Up @@ -87,6 +87,8 @@ export default class SelectionObserver extends Observer {
* @member {Number} module:engine/view/observer/selectionobserver~SelectionObserver#_loopbackCounter
*/
this._loopbackCounter = 0;

this.sourceElementRoot = sourceElementRoot;
}

/**
Expand Down Expand Up @@ -135,7 +137,12 @@ export default class SelectionObserver extends Observer {

// If there were mutations then the view will be re-rendered by the mutation observer and selection
// will be updated, so selections will equal and event will not be fired, as expected.
const domSelection = domDocument.defaultView.getSelection();
let domSelection;
if ( this.sourceElementRoot === domDocument ) {
domSelection = domDocument.defaultView.getSelection();
} else {
domSelection = this.sourceElementRoot.getSelection();
}
const newViewSelection = this.domConverter.domSelectionToView( domSelection );

// Do not convert selection change if the new view selection has no ranges in it.
Expand Down
10 changes: 6 additions & 4 deletions packages/ckeditor5-engine/src/view/view.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/

/* global document */

/**
* @module engine/view/view
*/
Expand Down Expand Up @@ -65,7 +67,7 @@ export default class View {
/**
* @param {module:engine/view/stylesmap~StylesProcessor} stylesProcessor The styles processor instance.
*/
constructor( stylesProcessor ) {
constructor( stylesProcessor, sourceElementRoot = document ) {
/**
* Instance of the {@link module:engine/view/document~Document} associated with this view controller.
*
Expand Down Expand Up @@ -179,7 +181,7 @@ export default class View {

// Add default observers.
this.addObserver( MutationObserver );
this.addObserver( SelectionObserver );
this.addObserver( SelectionObserver, sourceElementRoot );
this.addObserver( FocusObserver );
this.addObserver( KeyObserver );
this.addObserver( FakeSelectionObserver );
Expand Down Expand Up @@ -333,14 +335,14 @@ export default class View {
* Should create an instance inheriting from {@link module:engine/view/observer/observer~Observer}.
* @returns {module:engine/view/observer/observer~Observer} Added observer instance.
*/
addObserver( Observer ) {
addObserver( Observer, sourceElementRoot ) {
let observer = this._observers.get( Observer );

if ( observer ) {
return observer;
}

observer = new Observer( this );
observer = new Observer( this, sourceElementRoot );

this._observers.set( Observer, observer );

Expand Down