diff --git a/src/widget.js b/src/widget.js
index 38303d5e..68ef27e3 100644
--- a/src/widget.js
+++ b/src/widget.js
@@ -11,6 +11,7 @@ import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
import MouseObserver from '@ckeditor/ckeditor5-engine/src/view/observer/mouseobserver';
import { getLabel, isWidget, WIDGET_SELECTED_CLASS_NAME } from './utils';
import { getCode, keyCodes, parseKeystroke } from '@ckeditor/ckeditor5-utils/src/keyboard';
+import env from '@ckeditor/ckeditor5-utils/src/env';
import '../theme/widget.css';
@@ -114,8 +115,18 @@ export default class Widget extends Plugin {
const viewDocument = view.document;
let element = domEventData.target;
- // Do nothing if inside nested editable.
+ // Do nothing for single or double click inside nested editable.
if ( isInsideNestedEditable( element ) ) {
+ // But at least triple click inside nested editable causes broken selection in Safari.
+ // For such event, we select the entire nested editable element.
+ // See: https://github.com/ckeditor/ckeditor5/issues/1463.
+ if ( env.isSafari && domEventData.domEvent.detail >= 3 ) {
+ this.editor.editing.view.change( writer => {
+ domEventData.preventDefault();
+ writer.setSelection( element, 'in' );
+ } );
+ }
+
return;
}
diff --git a/tests/widget-integration.js b/tests/widget-integration.js
new file mode 100644
index 00000000..73a3881e
--- /dev/null
+++ b/tests/widget-integration.js
@@ -0,0 +1,232 @@
+/**
+ * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/* global document */
+
+import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor';
+import Typing from '@ckeditor/ckeditor5-typing/src/typing';
+import Widget from '../src/widget';
+import DomEventData from '@ckeditor/ckeditor5-engine/src/view/observer/domeventdata';
+
+import { toWidget } from '../src/utils';
+import { setData as setModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
+import { getData as getViewData } from '@ckeditor/ckeditor5-engine/src/dev-utils/view';
+
+import env from '@ckeditor/ckeditor5-utils/src/env';
+import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils';
+
+describe( 'Widget - integration', () => {
+ let editor, model, view, viewDocument, editorElement;
+
+ testUtils.createSinonSandbox();
+
+ beforeEach( () => {
+ // Most tests assume non-edge environment but we do not set `contenteditable=false` on Edge so stub `env.isEdge`.
+ testUtils.sinon.stub( env, 'isEdge' ).get( () => false );
+ testUtils.sinon.stub( env, 'isSafari' ).get( () => true );
+
+ editorElement = document.createElement( 'div' );
+ document.body.appendChild( editorElement );
+
+ return ClassicEditor.create( editorElement, { plugins: [ Widget, Typing ] } )
+ .then( newEditor => {
+ editor = newEditor;
+ model = editor.model;
+ view = editor.editing.view;
+ viewDocument = view.document;
+
+ model.schema.register( 'widget', {
+ inheritAllFrom: '$block',
+ isObject: true
+ } );
+ model.schema.register( 'paragraph', {
+ inheritAllFrom: '$block',
+ allowIn: '$root'
+ } );
+ model.schema.register( 'nested', {
+ allowIn: 'widget',
+ isLimit: true
+ } );
+ model.schema.extend( '$text', {
+ allowIn: [ 'nested', 'editable', 'inline-widget' ]
+ } );
+ model.schema.register( 'editable', {
+ allowIn: [ 'widget', '$root' ]
+ } );
+ model.schema.register( 'inline-widget', {
+ allowWhere: '$text',
+ isObject: true,
+ isInline: true
+ } );
+
+ editor.conversion.for( 'downcast' )
+ .elementToElement( { model: 'paragraph', view: 'p' } )
+ .elementToElement( { model: 'inline', view: 'figure' } )
+ .elementToElement( { model: 'image', view: 'img' } )
+ .elementToElement( {
+ model: 'widget',
+ view: ( modelItem, viewWriter ) => {
+ const div = viewWriter.createContainerElement( 'div' );
+
+ return toWidget( div, viewWriter, { label: 'element label' } );
+ }
+ } )
+ .elementToElement( {
+ model: 'inline-widget',
+ view: ( modelItem, viewWriter ) => {
+ const span = viewWriter.createContainerElement( 'span' );
+
+ return toWidget( span, viewWriter );
+ }
+ } )
+ .elementToElement( {
+ model: 'nested',
+ view: ( modelItem, viewWriter ) => viewWriter.createEditableElement( 'figcaption', { contenteditable: true } )
+ } )
+ .elementToElement( {
+ model: 'editable',
+ view: ( modelItem, viewWriter ) => viewWriter.createEditableElement( 'figcaption', { contenteditable: true } )
+ } );
+ } );
+ } );
+
+ afterEach( () => {
+ editorElement.remove();
+
+ return editor.destroy();
+ } );
+
+ it( 'should do nothing if clicked inside a nested editable', () => {
+ setModelData( model, '[]
Foo{
' + ); + } ); + + it( 'should does nothing for non-Safari browser', () => { + testUtils.sinon.stub( env, 'isSafari' ).get( () => false ); + + setModelData( model, '[] }Bar