This repository has been archived by the owner on Jun 26, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 6
PR: Acknowledge inline widgets #70
Merged
Merged
Changes from all commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
f9f6a3f
Introduce inline widget manual test.
jodator 6b8bcd0
Add toolbar button for creating inline widget in manual test.
jodator 9e8a4a5
Add Clipboard plugin and fix the sample code.
jodator 4cc12ea
Add isInline=true to placeholder's schema definition in manual test.
jodator 9ee4d0b
Add ShiftEnter plugin to inline widget manual sample.
jodator 41aa892
Add description for inline widget manual test.
jodator 0e173b2
Add table feature to inline widget manual test.
jodator e097009
The findOptimalInsertionPosition() function should treat inline eleme…
jodator 90c55d8
Add fake selection indicator to the inline widget manual test.
jodator 0a5cfef
Improve text visibility around selected inline widget in its manual t…
jodator 5f0f2e6
Merge branch 'master' into t/ckeditor5/1096
jodator 0cf4082
Merge branch 'master' into t/ckeditor5/1096
Reinmar 21c2cfd
Minor logic clarification.
Reinmar efbdbf7
Added `utils.viewToModelPositionOutsideModelElement`.
scofalik b7c42b8
Merge branch 'master' into t/ckeditor5/1096
Reinmar 5adcd24
Improved docs.
Reinmar 77fe639
The world's a better place now.
Reinmar File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
<div id="editor"> | ||
<h1>Hello <placeholder>{name}</placeholder>!</h1> | ||
|
||
<p>We would like to invite you to <placeholder>{place}</placeholder> that will take place on <placeholder>{date}</placeholder>.</p> | ||
</div> | ||
|
||
<h2>Model contents:</h2> | ||
|
||
<pre id="model"></pre> | ||
|
||
<style> | ||
placeholder { | ||
background: #ffff00; | ||
padding: 4px 2px; | ||
outline-offset: -2px; | ||
line-height: 1em; | ||
} | ||
|
||
placeholder::selection { | ||
display: none; | ||
} | ||
|
||
/* This will show box when the fake selection is active. */ | ||
.ck.ck-content div[style*="left: -9999px;"]::before { | ||
background: hsla(9,100%,56%,.3); | ||
border: 1px dotted hsl(15, 100%, 43%); | ||
color: #333; | ||
content: 'fake selection set'; | ||
display: block; | ||
height: 20px; | ||
left: calc(50% - 60px); | ||
line-height: 20px; | ||
padding: 2px 5px; | ||
position: fixed; | ||
top: 5px; | ||
z-index: 1; | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
/** | ||
* @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved. | ||
* For licensing, see LICENSE.md. | ||
*/ | ||
|
||
/* global console, window */ | ||
|
||
import { getData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model'; | ||
import global from '@ckeditor/ckeditor5-utils/src/dom/global'; | ||
|
||
import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor'; | ||
import Plugin from '@ckeditor/ckeditor5-core/src/plugin'; | ||
import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold'; | ||
import Enter from '@ckeditor/ckeditor5-enter/src/enter'; | ||
import Heading from '@ckeditor/ckeditor5-heading/src/heading'; | ||
import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph'; | ||
import Typing from '@ckeditor/ckeditor5-typing/src/typing'; | ||
import Undo from '@ckeditor/ckeditor5-undo/src/undo'; | ||
import Widget from '@ckeditor/ckeditor5-widget/src/widget'; | ||
import { toWidget, viewToModelPositionOutsideModelElement } from '../../src/utils'; | ||
import ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview'; | ||
import Clipboard from '@ckeditor/ckeditor5-clipboard/src/clipboard'; | ||
import ShiftEnter from '@ckeditor/ckeditor5-enter/src/shiftenter'; | ||
import Table from '@ckeditor/ckeditor5-table/src/table'; | ||
|
||
class InlineWidget extends Plugin { | ||
constructor( editor ) { | ||
super( editor ); | ||
|
||
editor.model.schema.register( 'placeholder', { | ||
allowWhere: '$text', | ||
isObject: true, | ||
isInline: true, | ||
allowAttributes: [ 'type' ] | ||
} ); | ||
|
||
editor.conversion.for( 'editingDowncast' ).elementToElement( { | ||
model: 'placeholder', | ||
view: ( modelItem, viewWriter ) => { | ||
const widgetElement = createPlaceholderView( modelItem, viewWriter ); | ||
|
||
return toWidget( widgetElement, viewWriter ); | ||
} | ||
} ); | ||
|
||
editor.conversion.for( 'dataDowncast' ).elementToElement( { | ||
model: 'placeholder', | ||
view: createPlaceholderView | ||
} ); | ||
|
||
editor.conversion.for( 'upcast' ).elementToElement( { | ||
view: 'placeholder', | ||
model: ( viewElement, modelWriter ) => { | ||
let type = 'general'; | ||
|
||
if ( viewElement.childCount ) { | ||
const text = viewElement.getChild( 0 ); | ||
|
||
if ( text.is( 'text' ) ) { | ||
type = text.data.slice( 1, -1 ); | ||
} | ||
} | ||
|
||
return modelWriter.createElement( 'placeholder', { type } ); | ||
} | ||
} ); | ||
|
||
editor.editing.mapper.on( | ||
'viewToModelPosition', | ||
viewToModelPositionOutsideModelElement( editor.model, viewElement => viewElement.name == 'placeholder' ) | ||
); | ||
|
||
this._createToolbarButton(); | ||
|
||
function createPlaceholderView( modelItem, viewWriter ) { | ||
const widgetElement = viewWriter.createContainerElement( 'placeholder' ); | ||
const viewText = viewWriter.createText( '{' + modelItem.getAttribute( 'type' ) + '}' ); | ||
|
||
viewWriter.insert( viewWriter.createPositionAt( widgetElement, 0 ), viewText ); | ||
|
||
return widgetElement; | ||
} | ||
} | ||
|
||
_createToolbarButton() { | ||
const editor = this.editor; | ||
const t = editor.t; | ||
|
||
editor.ui.componentFactory.add( 'placeholder', locale => { | ||
const buttonView = new ButtonView( locale ); | ||
|
||
buttonView.set( { | ||
label: t( 'Insert placeholder' ), | ||
tooltip: true, | ||
withText: true | ||
} ); | ||
|
||
this.listenTo( buttonView, 'execute', () => { | ||
const model = editor.model; | ||
|
||
model.change( writer => { | ||
const placeholder = writer.createElement( 'placeholder', { type: 'placeholder' } ); | ||
|
||
model.insertContent( placeholder ); | ||
|
||
writer.setSelection( placeholder, 'on' ); | ||
} ); | ||
} ); | ||
|
||
return buttonView; | ||
} ); | ||
} | ||
} | ||
|
||
ClassicEditor | ||
.create( global.document.querySelector( '#editor' ), { | ||
plugins: [ Enter, Typing, Paragraph, Heading, Bold, Undo, Clipboard, Widget, ShiftEnter, InlineWidget, Table ], | ||
toolbar: [ 'heading', '|', 'bold', '|', 'placeholder', '|', 'insertTable', '|', 'undo', 'redo' ] | ||
} ) | ||
.then( editor => { | ||
window.editor = editor; | ||
|
||
editor.model.document.on( 'change', () => { | ||
printModelContents( editor ); | ||
} ); | ||
|
||
printModelContents( editor ); | ||
} ) | ||
.catch( err => { | ||
console.error( err.stack ); | ||
} ); | ||
|
||
const modelDiv = global.document.querySelector( '#model' ); | ||
|
||
function printModelContents( editor ) { | ||
modelDiv.innerText = formatData( getData( editor.model ) ); | ||
} | ||
|
||
function formatData( data ) { | ||
return data | ||
.replace( /<(paragraph|\/tableRow|tableCell|table|heading[0-5])>/g, '\n<$1>' ) | ||
.replace( /(<tableCell>)\n(<paragraph>)/g, '$1$2' ) | ||
.replace( /\n(<tableCell>)/g, '\n\t$1' ); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
### Inline widget | ||
|
||
* You should be able to type after inline widget (if it is last child of parent <heading> or <paragraph>). | ||
* Select text before/after widget and expand selection beyond widget. The widget should be selected and selection expanded beyond it on further expanding. | ||
* The inline-widget should work in nested editable widget (table). | ||
* Use "insert placeholder" toolbar button to insert inline widget. | ||
* Selected inline widget should have | ||
* widget border (blue) | ||
* activate fake selection - the "fake selection" element will be shown above the editor |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm wondering – shouldn't that placeholder be selected by
insertContent()
? If it was a block, it would be. However, if it was a block, the case is slightly different because the selection should not be set after it. So selecting it is the most reasonable solution. In case of inline objects, we can set the selection after this element (and we do that now). WDYT?cc @scofalik @jodator
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From UX perspective, I think that setting the selection after the inline-widget is defensible. You insert the widget and maybe want to go on with writing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I can asnwer this myself – pasting should not select the placeholder, so should not
insertContent()
.