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
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #109 from ckeditor/t/97
Fix: Keyboard navigation should work around widgets in RTL content. Closes #97.
- Loading branch information
Showing
5 changed files
with
239 additions
and
2 deletions.
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,46 @@ | ||
<head> | ||
<style> | ||
body { | ||
max-width: 800px; | ||
margin: 20px auto; | ||
} | ||
|
||
.ck-content .widget { | ||
background: rgba( 0, 0, 0, 0.1 ); | ||
min-height: 50px; | ||
} | ||
|
||
.ck-content placeholder { | ||
background: #ffff00; | ||
padding: 4px 2px; | ||
outline-offset: -2px; | ||
line-height: 1em; | ||
/* Set margins before and after the inline widget so the cursor between two instances is visible when one of them is focused. | ||
Optimized for Firefox due to bug in rendering selection in ZWS on Chrome. See ckeditor5#1607. */ | ||
margin-right: 1px; | ||
margin-left: 3px; | ||
} | ||
|
||
.ck-content placeholder::selection { | ||
display: none; | ||
} | ||
</style> | ||
</head> | ||
|
||
<h2>LTR content</h2> | ||
|
||
<div id="editor-ltr"> | ||
<h2>Heading 1</h2> | ||
<p>Para<placeholder>inline widget</placeholder>graph</p> | ||
<div class="widget"></div> | ||
<p>Paragraph</p> | ||
</div> | ||
|
||
<h2>RTL content</h2> | ||
|
||
<div id="editor-rtl"> | ||
<h2>مرحبا</h2> | ||
<p>مرحبا<placeholder>inline widget</placeholder>مرحبا</p> | ||
<div class="widget"></div> | ||
<p>مرحبا</p> | ||
</div> |
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,130 @@ | ||
/** | ||
* @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved. | ||
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license | ||
*/ | ||
|
||
/* globals console, window, document */ | ||
|
||
import Widget from '../../src/widget'; | ||
import { toWidget, viewToModelPositionOutsideModelElement } from '../../src/utils'; | ||
import Plugin from '@ckeditor/ckeditor5-core/src/plugin'; | ||
import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor'; | ||
import ArticlePluginSet from '@ckeditor/ckeditor5-core/tests/_utils/articlepluginset'; | ||
|
||
function BlockWidget( editor ) { | ||
editor.model.schema.register( 'div', { | ||
allowIn: [ '$root' ], | ||
isObject: true | ||
} ); | ||
|
||
editor.conversion.for( 'downcast' ).elementToElement( { | ||
model: 'div', | ||
view: ( modelElement, writer ) => { | ||
return toWidget( | ||
writer.createContainerElement( 'div', { | ||
class: 'widget' | ||
} ), | ||
writer, | ||
{ hasSelectionHandler: true } | ||
); | ||
} | ||
} ); | ||
|
||
editor.conversion.for( 'upcast' ).elementToElement( { | ||
model: 'div', | ||
view: 'div' | ||
} ); | ||
} | ||
|
||
class InlineWidget extends Plugin { | ||
constructor( editor ) { | ||
super( editor ); | ||
|
||
editor.model.schema.register( 'placeholder', { | ||
allowWhere: '$text', | ||
isObject: true, | ||
isInline: true | ||
} ); | ||
|
||
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: 'placeholder' | ||
} ); | ||
|
||
editor.editing.mapper.on( | ||
'viewToModelPosition', | ||
viewToModelPositionOutsideModelElement( editor.model, viewElement => viewElement.name == 'placeholder' ) | ||
); | ||
|
||
function createPlaceholderView( modelItem, viewWriter ) { | ||
const widgetElement = viewWriter.createContainerElement( 'placeholder' ); | ||
const viewText = viewWriter.createText( '{placeholder}' ); | ||
|
||
viewWriter.insert( viewWriter.createPositionAt( widgetElement, 0 ), viewText ); | ||
|
||
return widgetElement; | ||
} | ||
} | ||
} | ||
|
||
const config = { | ||
plugins: [ ArticlePluginSet, Widget, InlineWidget, BlockWidget ], | ||
toolbar: [ | ||
'heading', | ||
'|', | ||
'bold', | ||
'italic', | ||
'link', | ||
'bulletedList', | ||
'numberedList', | ||
'blockQuote', | ||
'insertTable', | ||
'mediaEmbed', | ||
'undo', | ||
'redo' | ||
], | ||
image: { | ||
toolbar: [ 'imageStyle:full', 'imageStyle:side', '|', 'imageTextAlternative' ] | ||
}, | ||
table: { | ||
contentToolbar: [ | ||
'tableColumn', | ||
'tableRow', | ||
'mergeTableCells' | ||
] | ||
} | ||
}; | ||
|
||
ClassicEditor | ||
.create( document.querySelector( '#editor-ltr' ), config ) | ||
.then( editor => { | ||
window.editorLtr = editor; | ||
} ) | ||
.catch( err => { | ||
console.error( err.stack ); | ||
} ); | ||
|
||
ClassicEditor | ||
.create( document.querySelector( '#editor-rtl' ), Object.assign( {}, config, { | ||
language: 'ar' | ||
} ) ) | ||
.then( editor => { | ||
window.editorRtl = editor; | ||
} ) | ||
.catch( err => { | ||
console.error( err.stack ); | ||
} ); |
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,20 @@ | ||
# Keyboard navigation across widgets | ||
|
||
1. Put a selection at the beginning of the document. | ||
2. Use the **right arrow** key to navigate forwards. | ||
3. Go through inline and block widgets. | ||
4. The navigation should | ||
* be uninterrupted, | ||
* go always forward, | ||
* select widgets on its way. | ||
5. Reach the end of the document. | ||
6. Go backwards using the **left arrow** key and repeat the entire scenario. | ||
|
||
## RTL (right–to–left) content navigation | ||
|
||
In this scenario the content is written in Arabic. | ||
|
||
1. Repeat the scenario from the previous section but note that the content is mirrored, i.e. the beginning is on the right–hand side. | ||
2. Forwards navigation is done by pressing the **left arrow** key. | ||
3. To go backwards, use the **right arrow** key. | ||
4. Just like with the LTR content, the navigation should be seamless, always in the same direction. |
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