Skip to content
This repository has been archived by the owner on Jun 26, 2020. It is now read-only.

Commit

Permalink
Merge 3cb0b59 into ee8eeb3
Browse files Browse the repository at this point in the history
  • Loading branch information
jodator committed Sep 17, 2018
2 parents ee8eeb3 + 3cb0b59 commit f68f913
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 39 deletions.
45 changes: 38 additions & 7 deletions src/model/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -275,12 +275,12 @@ export default class Model {
*
* // insertContent() doesn't have to be used in a change() block. It can, though,
* // so this code could be moved to the callback defined above.
* editor.model.insertContent( docFrag, editor.model.document.selection );
* editor.model.insertContent( docFrag );
*
* Using `insertContent()` with HTML string converted to a model document fragment (similar to the pasting mechanism):
*
* // You can create your own HtmlDataProcessor instance or use editor.data.processor
* // if you haven't overriden the default one (which is HtmlDataProcessor instance).
* // if you haven't overridden the default one (which is HtmlDataProcessor instance).
* const htmlDP = new HtmlDataProcessor();
*
* // Convert an HTML string to a view document fragment.
Expand All @@ -296,15 +296,43 @@ export default class Model {
* // which has a loosened schema.
* const modelFragment = editor.data.toModel( viewFragment );
*
* editor.model.insertContent( modelFragment, editor.model.document.selection );
* editor.model.insertContent( modelFragment );
*
* By default this method will use the document selection but it can also be used with a position, range or selection instance.
*
* // Insert text at the current document selection position.
* editor.model.change( writer => {
* editor.model.insertContent( writer.createText( 'x' ) );
* } );
*
* // Insert text at given position - document selection will not be modified.
* editor.model.change( writer => {
* editor.model.insertContent( writer.createText( 'x' ), Position.createAt( doc.getRoot(), 2 ) );
* } );
*
* If an instance of {module:engine/model/selection~Selection} is passed as `selectable`
* it will be moved to the target position (where the document selection should be moved after the insertion).
*
* // Insert text replacing given selection instance.
* const selection = new Selection( paragraph, 'in' );
*
* editor.model.change( writer => {
* editor.model.insertContent( writer.createText( 'x' ), selection );
*
* // insertContent() modifies the passed selection instance so it can be used to set the document selection.
* // Note: This is not necessary when you passed document selection to insertContent().
* writer.setSelection( selection );
* } );
*
* @fires insertContent
* @param {module:engine/model/documentfragment~DocumentFragment|module:engine/model/item~Item} content The content to insert.
* @param {module:engine/model/selection~Selection|module:engine/model/documentselection~DocumentSelection} selection
* Selection into which the content should be inserted.
* @param {module:engine/model/selection~Selection|module:engine/model/documentselection~DocumentSelection|
* module:engine/model/position~Position|module:engine/model/element~Element|
* Iterable.<module:engine/model/range~Range>|module:engine/model/range~Range|null} [selectable=model.document.selection]
* Selection into which the content should be inserted. If not provided the current model document selection will be used.
*/
insertContent( content, selection ) {
insertContent( this, content, selection );
insertContent( content, selectable ) {
insertContent( this, content, selectable );
}

/**
Expand Down Expand Up @@ -534,6 +562,9 @@ export default class Model {
* The {@link #insertContent default action of that method} is implemented as a
* listener to this event so it can be fully customized by the features.
*
* **Note** The `selectable` parameter for the {@link #insertContent} is optional. When `undefined` value is passed the method uses
* `model.document.selection`.
*
* @event insertContent
* @param {Array} args The arguments passed to the original method.
*/
Expand Down
32 changes: 16 additions & 16 deletions src/model/selection.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,46 +35,46 @@ export default class Selection {
* or on the given {@link module:engine/model/element~Element element},
* or creates an empty selection if no arguments were passed.
*
* // Creates empty selection without ranges.
* // Creates empty selection without ranges.
* const selection = new Selection();
*
* // Creates selection at the given range.
* const range = new Range( start, end );
* const selection = new Selection( range );
*
* // Creates selection at the given ranges
* const ranges = [ new Range( start1, end2 ), new Range( star2, end2 ) ];
* const ranges = [ new Range( start1, end2 ), new Range( star2, end2 ) ];
* const selection = new Selection( ranges );
*
* // Creates selection from the other selection.
* // Note: It doesn't copies selection attributes.
* const otherSelection = new Selection();
* const selection = new Selection( otherSelection );
*
* // Creates selection from the given document selection.
* // Creates selection from the given document selection.
* // Note: It doesn't copies selection attributes.
* const documentSelection = new DocumentSelection( doc );
* const selection = new Selection( documentSelection );
*
* // Creates selection at the given position.
* // Creates selection at the given position.
* const position = new Position( root, path );
* const selection = new Selection( position );
*
* // Creates selection at the start position of the given element.
* // Creates selection at the start position of the given element.
* const paragraph = writer.createElement( 'paragraph' );
* const selection = new Selection( paragraph, offset );
*
* // Creates a range inside an {@link module:engine/model/element~Element element} which starts before the
* // first child of that element and ends after the last child of that element.
* // Creates a range inside an {@link module:engine/model/element~Element element} which starts before the
* // first child of that element and ends after the last child of that element.
* const selection = new Selection( paragraph, 'in' );
*
* // Creates a range on an {@link module:engine/model/item~Item item} which starts before the item and ends
* // just after the item.
* // Creates a range on an {@link module:engine/model/item~Item item} which starts before the item and ends
* // just after the item.
* const selection = new Selection( paragraph, 'on' );
*
* Selection's constructor allow passing additional options (`'backward'`) as the last argument.
*
* // Creates backward selection.
* // Creates backward selection.
* const selection = new Selection( range, { backward: true } );
*
* @param {module:engine/model/selection~Selection|module:engine/model/documentselection~DocumentSelection|
Expand Down Expand Up @@ -326,32 +326,32 @@ export default class Selection {
* {@link module:engine/model/element~Element element}, {@link module:engine/model/position~Position position},
* {@link module:engine/model/range~Range range}, an iterable of {@link module:engine/model/range~Range ranges} or null.
*
* // Removes all selection's ranges.
* // Removes all selection's ranges.
* selection.setTo( null );
*
* // Sets selection to the given range.
* const range = new Range( start, end );
* selection.setTo( range );
*
* // Sets selection to given ranges.
* const ranges = [ new Range( start1, end2 ), new Range( star2, end2 ) ];
* const ranges = [ new Range( start1, end2 ), new Range( star2, end2 ) ];
* selection.setTo( ranges );
*
* // Sets selection to other selection.
* // Note: It doesn't copies selection attributes.
* const otherSelection = new Selection();
* selection.setTo( otherSelection );
*
* // Sets selection to the given document selection.
* // Sets selection to the given document selection.
* // Note: It doesn't copies selection attributes.
* const documentSelection = new DocumentSelection( doc );
* selection.setTo( documentSelection );
*
* // Sets collapsed selection at the given position.
* // Sets collapsed selection at the given position.
* const position = new Position( root, path );
* selection.setTo( position );
*
* // Sets collapsed selection at the position of the given node and an offset.
* // Sets collapsed selection at the position of the given node and an offset.
* selection.setTo( paragraph, offset );
*
* Creates a range inside an {@link module:engine/model/element~Element element} which starts before the first child of
Expand All @@ -365,7 +365,7 @@ export default class Selection {
*
* `Selection#setTo()`' method allow passing additional options (`backward`) as the last argument.
*
* // Sets backward selection.
* // Sets backward selection.
* const selection = new Selection( range, { backward: true } );
*
* @param {module:engine/model/selection~Selection|module:engine/model/documentselection~DocumentSelection|
Expand Down
23 changes: 19 additions & 4 deletions src/model/utils/insertcontent.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,39 @@ import Element from '../element';
import Range from '../range';
import log from '@ckeditor/ckeditor5-utils/src/log';
import DocumentSelection from '../documentselection';
import Selection from '../selection';

/**
* Inserts content into the editor (specified selection) as one would expect the paste
* functionality to work.
*
* If an instance of {module:engine/model/selection~Selection} is passed as `selectable` it will be modified
* to the insertion selection (equal to a range to be selected after insertion).
*
* **Note:** Use {@link module:engine/model/model~Model#insertContent} instead of this function.
* This function is only exposed to be reusable in algorithms
* which change the {@link module:engine/model/model~Model#insertContent}
* This function is only exposed to be reusable in algorithms which change the {@link module:engine/model/model~Model#insertContent}
* method's behavior.
*
* @param {module:engine/model/model~Model} model The model in context of which the insertion
* should be performed.
* @param {module:engine/model/documentfragment~DocumentFragment|module:engine/model/item~Item} content The content to insert.
* @param {module:engine/model/selection~Selection|module:engine/model/documentselection~DocumentSelection} selection
* @param {module:engine/model/selection~Selection|module:engine/model/documentselection~DocumentSelection|
* module:engine/model/position~Position|module:engine/model/element~Element|
* Iterable.<module:engine/model/range~Range>|module:engine/model/range~Range|null} [selectable=model.document.selection]
* Selection into which the content should be inserted.
*/
export default function insertContent( model, content, selection ) {
export default function insertContent( model, content, selectable ) {
model.change( writer => {
let selection;

if ( !selectable ) {
selection = model.document.selection;
} else if ( selectable instanceof Selection || selectable instanceof DocumentSelection ) {
selection = selectable;
} else {
selection = new Selection( selectable );
}

if ( !selection.isCollapsed ) {
model.deleteContent( selection );
}
Expand Down
18 changes: 14 additions & 4 deletions tests/model/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ describe( 'Model', () => {

model.on( 'insertContent', spy );

model.insertContent( new ModelText( 'a' ), model.document.selection );
model.insertContent( new ModelText( 'a' ) );

expect( spy.calledOnce ).to.be.true;
} );
Expand All @@ -357,7 +357,7 @@ describe( 'Model', () => {

setData( model, '<paragraph>fo[]ar</paragraph>' );

model.insertContent( new ModelText( 'ob' ), model.document.selection );
model.insertContent( new ModelText( 'ob' ) );

expect( getData( model ) ).to.equal( '<paragraph>foob[]ar</paragraph>' );
} );
Expand All @@ -367,7 +367,17 @@ describe( 'Model', () => {

setData( model, '<paragraph>fo[]ar</paragraph>' );

model.insertContent( new ModelDocumentFragment( [ new ModelText( 'ob' ) ] ), model.document.selection );
model.insertContent( new ModelDocumentFragment( [ new ModelText( 'ob' ) ] ) );

expect( getData( model ) ).to.equal( '<paragraph>foob[]ar</paragraph>' );
} );

it( 'should use current model selection if no selectable passed', () => {
schema.register( 'paragraph', { inheritAllFrom: '$block' } );

setData( model, '<paragraph>fo[]ar</paragraph>' );

model.insertContent( new ModelText( 'ob' ) );

expect( getData( model ) ).to.equal( '<paragraph>foob[]ar</paragraph>' );
} );
Expand All @@ -377,7 +387,7 @@ describe( 'Model', () => {
setData( model, '<paragraph>[]</paragraph>' );

model.change( writer => {
model.insertContent( new ModelText( 'abc' ), model.document.selection );
model.insertContent( new ModelText( 'abc' ) );
expect( writer.batch.operations ).to.length( 1 );
} );
} );
Expand Down
Loading

0 comments on commit f68f913

Please sign in to comment.