Report an issue
Class

DowncastWriter (engine/view)

@ckeditor/ckeditor5-engine/src/view/downcastwriter

class

View downcast writer.

It provides a set of methods used to manipulate view nodes.

Do not create an instance of this writer manually. To modify a view structure, use the View#change() block.

The DowncastWriter is designed to work with semantic views which are the views that were/are being downcasted from the model. To work with ordinary views (e.g. parsed from a pasted content) use the upcast writer.

Read more about changing the view in the Changing the view section of the Editing engine architecture guide.

Filtering

Properties

  • document : Document

    readonly

  • _cloneGroups : Map.<String, Set>

    private

    Holds references to the attribute groups that share the same id. The keys are ids, the values are Sets holding AttributeElements.

Methods

  • addClass( className, element )

    Adds specified class to the element.

    writer.addClass( 'foo', linkElement );
    writer.addClass( [ 'foo', 'bar' ], linkElement );

    Parameters

    className : Array.<String> | String
    element : Element
  • breakAttributes( positionOrRange ) → Position | Range

    Breaks attribute nodes at provided position or at boundaries of provided range. It breaks attribute elements inside up to a container element.

    In following examples <p> is a container, <b> and <u> are attribute nodes:

       <p>foo<b><u>bar{}</u></b></p> -> <p>foo<b><u>bar</u></b>[]</p>
       <p>foo<b><u>{}bar</u></b></p> -> <p>foo{}<b><u>bar</u></b></p>
       <p>foo<b><u>b{}ar</u></b></p> -> <p>foo<b><u>b</u></b>[]<b><u>ar</u></b></p>
       <p><b>fo{o</b><u>ba}r</u></p> -> <p><b>fo</b><b>o</b><u>ba</u><u>r</u></b></p>

    Note: DocumentFragment is treated like a container.

    Note: Difference between breakAttributes and breakContainer is that breakAttributes breaks all attribute elements that are ancestors of given position, up to the first encountered container element. breakContainer assumes that given position is directly in container element and breaks that container element.

    Throws CKEditorError view-writer-invalid-range-container when start and end positions of a passed range are not placed inside same parent container.

    Throws CKEditorError view-writer-cannot-break-empty-element when trying to break attributes inside EmptyElement.

    Throws CKEditorError view-writer-cannot-break-ui-element when trying to break attributes inside UIElement.

    Parameters

    positionOrRange : Position | Range

    Position where to break attribute elements.

    Returns

    Position | Range

    New position or range, after breaking the attribute elements.

  • breakContainer( position ) → Position

    Breaks container view element into two, at the given position. Position has to be directly inside container element and cannot be in root. Does not break if position is at the beginning or at the end of it's parent element.

       <p>foo^bar</p> -> <p>foo</p><p>bar</p>
       <div><p>foo</p>^<p>bar</p></div> -> <div><p>foo</p></div><div><p>bar</p></div>
       <p>^foobar</p> -> ^<p>foobar</p>
       <p>foobar^</p> -> <p>foobar</p>^

    Note: Difference between breakAttributes and breakContainer is that breakAttributes breaks all attribute elements that are ancestors of given position, up to the first encountered container element. breakContainer assumes that given position is directly in container element and breaks that container element.

    Parameters

    position : Position

    Position where to break element.

    Returns

    Position

    Position between broken elements. If element has not been broken, the returned position is placed either before it or after it.

  • clear( range, element )

    Removes matching elements from given range.

    Throws CKEditorError view-writer-invalid-range-container when start and end positions are not placed inside same parent container.

    Parameters

    range : Range

    Range to clear.

    element : Element

    Element to remove.

  • clearClonedElementsGroup( groupName )

    Cleans up memory by removing obsolete cloned elements group from the writer.

    Should be used whenever all attribute elements with the same id are going to be removed from the view and the group will no longer be needed.

    Cloned elements group are not removed automatically in case if the group is still needed after all its elements were removed from the view.

    Keep in mind that group names are equal to the id property of the attribute element.

    Parameters

    groupName : String

    Name of the group to clear.

  • createAttributeElement( name, [ attributes ], [ options ] = { [options.priority], [options.id] } ) → AttributeElement

    Creates new AttributeElement.

    writer.createAttributeElement( 'strong' );
    writer.createAttributeElement( 'strong', { alignment: 'center' } );
    
    // Make `<a>` element contain other attributes element so the `<a>` element is not broken.
    writer.createAttributeElement( 'a', { href: 'foo.bar' }, { priority: 5 } );
    
    // Set `id` of a marker element so it is not joined or merged with "normal" elements.
    writer.createAttributeElement( 'span', { class: 'myMarker' }, { id: 'marker:my' } );

    Parameters

    name : String

    Name of the element.

    [ attributes ] : Object

    Element's attributes.

    [ options ] : Object

    Element's options.

    Properties
    [ options.priority ] : Number

    Element's priority.

    [ options.id ] : Number | String

    Element's id.

    Returns

    AttributeElement

    Created element.

  • createContainerElement( name, [ attributes ] ) → ContainerElement

    Creates new ContainerElement.

    writer.createContainerElement( 'paragraph' );
    writer.createContainerElement( 'paragraph', { alignment: 'center' } );

    Parameters

    name : String

    Name of the element.

    [ attributes ] : Object

    Elements attributes.

    Returns

    ContainerElement

    Created element.

  • createEditableElement( name, [ attributes ] ) → EditableElement

    Creates new EditableElement.

    writer.createEditableElement( 'div' );
    writer.createEditableElement( 'div', { alignment: 'center' } );

    Parameters

    name : String

    Name of the element.

    [ attributes ] : Object

    Elements attributes.

    Returns

    EditableElement

    Created element.

  • createEmptyElement( name, [ attributes ] ) → EmptyElement

    Creates new EmptyElement.

    writer.createEmptyElement( 'img' );
    writer.createEmptyElement( 'img', { alignment: 'center' } );

    Parameters

    name : String

    Name of the element.

    [ attributes ] : Object

    Elements attributes.

    Returns

    EmptyElement

    Created element.

  • createPositionAfter( item ) → Position

    Creates a new position after given view item.

    Parameters

    item : Item

    View item after which the position should be located.

    Returns

    Position
  • createPositionAt( itemOrPosition, [ offset ] )

    Creates position at the given location. The location can be specified as:

    • a position,
    • parent element and offset (offset defaults to 0),
    • parent element and 'end' (sets position at the end of that element),
    • view item and 'before' or 'after' (sets position before or after given view item).

    This method is a shortcut to other constructors such as:

    Parameters

    itemOrPosition : Item | Position
    [ offset ] : Number | 'end' | 'before' | 'after'

    Offset or one of the flags. Used only when first parameter is a view item.

  • createPositionBefore( item ) → Position

    Creates a new position before given view item.

    Parameters

    item : Item

    View item before which the position should be located.

    Returns

    Position
  • createRange( start, [ end ] ) → Range

    Creates a range spanning from start position to end position.

    Note: This factory method creates it's own Position instances basing on passed values.

    Parameters

    start : Position

    Start position.

    [ end ] : Position

    End position. If not set, range will be collapsed at start position.

    Returns

    Range
  • createRangeIn( element ) → Range

    Creates a range inside an element which starts before the first child of that element and ends after the last child of that element.

    Parameters

    element : Element

    Element which is a parent for the range.

    Returns

    Range
  • createRangeOn( item ) → Range

    Creates a range that starts before given view item and ends after it.

    Parameters

    item : Item

    Returns

    Range
  • createSelection( [ selectable ], [ placeOrOffset ], [ options ] = { [options.backward], [options.fake], [options.label] } ) → Selection

    Creates new Selection instance.

    // Creates empty selection without ranges.
    const selection = writer.createSelection();
    
    // Creates selection at the given range.
    const range = writer.createRange( start, end );
    const selection = writer.createSelection( range );
    
    // Creates selection at the given ranges
    const ranges = [ writer.createRange( start1, end2 ), writer.createRange( star2, end2 ) ];
    const selection = writer.createSelection( ranges );
    
    // Creates selection from the other selection.
    const otherSelection = writer.createSelection();
    const selection = writer.createSelection( otherSelection );
    
    // Creates selection from the document selection.
    const selection = writer.createSelection( editor.editing.view.document.selection );
    
    // Creates selection at the given position.
    const position = writer.createPositionFromPath( root, path );
    const selection = writer.createSelection( position );
    
    // Creates collapsed selection at the position of given item and offset.
    const paragraph = writer.createContainerElement( 'paragraph' );
    const selection = writer.createSelection( paragraph, offset );
    
    // Creates a range inside an element which starts before the
    // first child of that element and ends after the last child of that element.
    const selection = writer.createSelection( paragraph, 'in' );
    
    // Creates a range on an item which starts before the item and ends
    // just after the item.
    const selection = writer.createSelection( paragraph, 'on' );

    Selection's constructor allow passing additional options (backward, fake and label) as the last argument.

    // Creates backward selection.
    const selection = writer.createSelection( range, { backward: true } );

    Fake selection does not render as browser native selection over selected elements and is hidden to the user. This way, no native selection UI artifacts are displayed to the user and selection over elements can be represented in other way, for example by applying proper CSS class.

    Additionally fake's selection label can be provided. It will be used to describe fake selection in DOM (and be properly handled by screen readers).

    // Creates fake selection with label.
    const selection = writer.createSelection( range, { fake: true, label: 'foo' } );

    Parameters

    [ selectable ] : Selection | DocumentSelection | Position | Iterable.<Range> | Range | Item | null
    [ placeOrOffset ] : Number | 'before' | 'end' | 'after' | 'on' | 'in'

    Offset or place when selectable is an Item.

    [ options ] : Object
    Properties
    [ options.backward ] : Boolean

    Sets this selection instance to be backward.

    [ options.fake ] : Boolean

    Sets this selection instance to be marked as fake.

    [ options.label ] : String

    Label for the fake selection.

    Returns

    Selection
  • createText( data ) → Text

    Creates a new text node.

    writer.createText( 'foo' );

    Parameters

    data : String

    The text's data.

    Returns

    Text

    The created text node.

  • createUIElement( name, [ attributes ], [ renderFunction ] ) → UIElement

    Creates new UIElement.

    writer.createUIElement( 'span' );
    writer.createUIElement( 'span', { alignment: 'center' } );

    Custom render function can be provided as third parameter:

    writer.createUIElement( 'span', null, function( domDocument ) {
        const domElement = this.toDomElement( domDocument );
        domElement.innerHTML = '<b>this is ui element</b>';
    
        return domElement;
    } );

    Parameters

    name : String

    Name of the element.

    [ attributes ] : Object

    Elements attributes.

    [ renderFunction ] : function

    Custom render function.

    Returns

    UIElement

    Created element.

  • insert( position, nodes ) → Range

    Insert node or nodes at specified position. Takes care about breaking attributes before insertion and merging them afterwards.

    Throws CKEditorError view-writer-insert-invalid-node when nodes to insert contains instances that are not Texts, AttributeElements, ContainerElements, EmptyElements or UIElements.

    Parameters

    position : Position

    Insertion position.

    nodes : Text | AttributeElement | ContainerElement | EmptyElement | UIElement | Iterable.<(Text | AttributeElement | ContainerElement | EmptyElement | UIElement)>

    Node or nodes to insert.

    Returns

    Range

    Range around inserted nodes.

  • mergeAttributes( position ) → Position

    Merges attribute elements. It also merges text nodes if needed. Only similar attribute elements can be merged.

    In following examples <p> is a container and <b> is an attribute element:

       <p>foo[]bar</p> -> <p>foo{}bar</p>
       <p><b>foo</b>[]<b>bar</b></p> -> <p><b>foo{}bar</b></p>
       <p><b foo="bar">a</b>[]<b foo="baz">b</b></p> -> <p><b foo="bar">a</b>[]<b foo="baz">b</b></p>

    It will also take care about empty attributes when merging:

       <p><b>[]</b></p> -> <p>[]</p>
       <p><b>foo</b><i>[]</i><b>bar</b></p> -> <p><b>foo{}bar</b></p>

    Note: Difference between mergeAttributes and mergeContainers is that mergeAttributes merges two attribute elements or text nodes while mergeContainer merges two container elements.

    Parameters

    position : Position

    Merge position.

    Returns

    Position

    Position after merge.

  • mergeContainers( position ) → Position

    Merges two container elements that are before and after given position. Precisely, the element after the position is removed and it's contents are moved to element before the position.

       <p>foo</p>^<p>bar</p> -> <p>foo^bar</p>
       <div>foo</div>^<p>bar</p> -> <div>foo^bar</div>

    Note: Difference between mergeAttributes and mergeContainers is that mergeAttributes merges two attribute elements or text nodes while mergeContainer merges two container elements.

    Parameters

    position : Position

    Merge position.

    Returns

    Position

    Position after merge.

  • move( sourceRange, targetPosition ) → Range

    Moves nodes from provided range to target position.

    Throws CKEditorError view-writer-invalid-range-container when start and end positions are not placed inside same parent container.

    Parameters

    sourceRange : Range

    Range containing nodes to move.

    targetPosition : Position

    Position to insert.

    Returns

    Range

    Range in target container. Inserted nodes are placed between start and end positions.

  • remove( rangeOrItem ) → DocumentFragment

    Removes provided range from the container.

    Throws CKEditorError view-writer-invalid-range-container when start and end positions are not placed inside same parent container.

    Parameters

    rangeOrItem : Range | Item

    Range to remove from container or an item to remove. If range is provided, after removing, it will be updated to a collapsed range showing the new position.

    Returns

    DocumentFragment

    Document fragment containing removed nodes.

  • removeAttribute( key, element )

    Removes attribute from the element.

    writer.removeAttribute( 'href', linkElement );

    Parameters

    key : String

    Attribute key.

    element : Element
  • removeClass( className, element )

    Removes specified class from the element.

    writer.removeClass( 'foo', linkElement );
    writer.removeClass( [ 'foo', 'bar' ], linkElement );

    Parameters

    className : Array.<String> | String
    element : Element
  • removeCustomProperty( key, element ) → Boolean

    Removes a custom property stored under the given key.

    Parameters

    key : String | Symbol
    element : Element

    Returns

    Boolean

    Returns true if property was removed.

  • removeStyle( property, element )

    Removes specified style from the element.

    writer.removeStyle( 'color', element );  // Removes 'color' style.
    writer.removeStyle( [ 'color', 'border-top' ], element ); // Removes both 'color' and 'border-top' styles.

    Parameters

    property : Array.<String> | String
    element : Element
  • rename( newName, viewElement )

    Renames element by creating a copy of renamed element but with changed name and then moving contents of the old element to the new one. Keep in mind that this will invalidate all positions which has renamed element as a parent.

    New element has to be created because Element#tagName property in DOM is readonly.

    Since this function creates a new element and removes the given one, the new element is returned to keep reference.

    Parameters

    newName : String

    New name for element.

    viewElement : ContainerElement

    Element to be renamed.

  • setAttribute( key, value, element )

    Adds or overwrite element's attribute with a specified key and value.

    writer.setAttribute( 'href', 'http://ckeditor.com', linkElement );

    Parameters

    key : String

    Attribute key.

    value : String

    Attribute value.

    element : Element
  • setCustomProperty( key, value, element )

    Sets a custom property on element. Unlike attributes, custom properties are not rendered to the DOM, so they can be used to add special data to elements.

    Parameters

    key : String | Symbol
    value : *
    element : Element
  • setSelection( selectable, [ placeOrOffset ], [ options ] = { [options.backward], [options.fake], [options.label] } )

    Sets selection's ranges and direction to the specified location based on the given document selection, selection, position, item, range, an iterable of ranges or null.

    Usage:

    // Sets selection to the given range.
    const range = writer.createRange( start, end );
    writer.setSelection( range );
    
    // Sets backward selection to the given range.
    const range = writer.createRange( start, end );
    writer.setSelection( range );
    
    // Sets selection to given ranges.
    const ranges = [ writer.createRange( start1, end2 ), writer.createRange( star2, end2 ) ];
    writer.setSelection( range );
    
    // Sets selection to the other selection.
    const otherSelection = writer.createSelection();
    writer.setSelection( otherSelection );
    
    // Sets collapsed selection at the given position.
    const position = writer.createPositionFromPath( root, path );
    writer.setSelection( position );
    
    // Sets collapsed selection at the position of given item and offset.
    const paragraph = writer.createContainerElement( 'paragraph' );
    writer.setSelection( paragraph, offset );

    Creates a range inside an element which starts before the first child of that element and ends after the last child of that element.

    writer.setSelection( paragraph, 'in' );

    Creates a range on the item which starts before the item and ends just after the item.

    writer.setSelection( paragraph, 'on' );
    
    // Removes all ranges.
    writer.setSelection( null );

    DowncastWriter#setSelection() allow passing additional options (backward, fake and label) as the last argument.

    // Sets selection as backward.
    writer.setSelection( range, { backward: true } );
    
    // Sets selection as fake.
    // Fake selection does not render as browser native selection over selected elements and is hidden to the user.
    // This way, no native selection UI artifacts are displayed to the user and selection over elements can be
    // represented in other way, for example by applying proper CSS class.
    writer.setSelection( range, { fake: true } );
    
    // Additionally fake's selection label can be provided. It will be used to describe fake selection in DOM
    // (and be  properly handled by screen readers).
    writer.setSelection( range, { fake: true, label: 'foo' } );

    Parameters

    selectable : Selection | Position | Iterable.<Range> | Range | Item | null
    [ placeOrOffset ] : Number | 'before' | 'end' | 'after' | 'on' | 'in'

    Sets place or offset of the selection.

    [ options ] : Object
    Properties
    [ options.backward ] : Boolean

    Sets this selection instance to be backward.

    [ options.fake ] : Boolean

    Sets this selection instance to be marked as fake.

    [ options.label ] : String

    Label for the fake selection.

  • setSelectionFocus( itemOrPosition, [ offset ] )

    Moves selection's focus to the specified location.

    The location can be specified in the same form as view.createPositionAt() parameters.

    Parameters

    itemOrPosition : Item | Position
    [ offset ] : Number | 'end' | 'before' | 'after'

    Offset or one of the flags. Used only when first parameter is a view item.

  • setStyle( property, [ value ], element )

    Adds style to the element.

    writer.setStyle( 'color', 'red', element );
    writer.setStyle( {
        color: 'red',
        position: 'fixed'
    }, element );

    Parameters

    property : String | Object

    Property name or object with key - value pairs.

    [ value ] : String

    Value to set. This parameter is ignored if object is provided as the first parameter.

    element : Element

    Element to set styles on.

  • unwrap( range, attribute )

    Unwraps nodes within provided range from attribute element.

    Throws CKEditorError view-writer-invalid-range-container when start and end positions are not placed inside same parent container.

    Parameters

    range : Range
    attribute : AttributeElement
  • wrap( range, attribute ) → Range

    Wraps elements within range with provided AttributeElement. If a collapsed range is provided, it will be wrapped only if it is equal to view selection.

    If a collapsed range was passed and is same as selection, the selection will be moved to the inside of the wrapped attribute element.

    Throws CKEditorError view-writer-invalid-range-container when start and end positions are not placed inside same parent container.

    Throws CKEditorError view-writer-wrap-invalid-attribute when passed attribute element is not an instance of AttributeElement.

    Throws CKEditorError view-writer-wrap-nonselection-collapsed-range when passed range is collapsed and different than view selection.

    Parameters

    range : Range

    Range to wrap.

    attribute : AttributeElement

    Attribute element to use as wrapper.

    Returns

    Range

    range Range after wrapping, spanning over wrapping attribute element.

  • _addToClonedElementsGroup( element )

    private

    Stores the information that an attribute element was added to the tree. Saves the reference to the group in the given element and updates the group, so other elements from the group now keep a reference to the given attribute element.

    The clones group can be obtained using getElementsWithSameId.

    Does nothing if added element has no id.

    Parameters

    element : AttributeElement

    Attribute element to save.

  • _breakAttributes( position, [ forceSplitText ] ) → Position

    private

    Helper function used by other DowncastWriter methods. Breaks attribute elements at given position.

    Throws CKEditorError view-writer-cannot-break-empty-element when break position is placed inside EmptyElement.

    Throws CKEditorError view-writer-cannot-break-ui-element when break position is placed inside UIElement.

    Parameters

    position : Position

    Position where to break attributes.

    [ forceSplitText ] : Boolean

    If set to true, will break text nodes even if they are directly in container element. This behavior will result in incorrect view state, but is needed by other view writing methods which then fixes view state.

    Defaults to false

    Returns

    Position

    New position after breaking the attributes.

  • _breakAttributesRange( range, [ forceSplitText ] ) → Range

    private

    Helper function used by other DowncastWriter methods. Breaks attribute elements at the boundaries of given range.

    Parameters

    range : Range

    Range which start and end positions will be used to break attributes.

    [ forceSplitText ] : Boolean

    If set to true, will break text nodes even if they are directly in container element. This behavior will result in incorrect view state, but is needed by other view writing methods which then fixes view state.

    Defaults to false

    Returns

    Range

    New range with located at break positions.

  • _removeFromClonedElementsGroup( element )

    private

    Removes all the information about the given attribute element from its clones group.

    Keep in mind, that the element will still keep a reference to the group (but the group will not keep a reference to it). This allows to reference the whole group even if the element was already removed from the tree.

    Does nothing if the element has no id.

    Parameters

    element : AttributeElement

    Attribute element to remove.

  • _unwrapAttributeElement( wrapper, toUnwrap ) → Boolean

    private

    Unwraps AttributeElement from another by removing corresponding attributes, classes and styles. All attributes, classes and styles from wrapper should be present inside element being unwrapped.

    Parameters

    wrapper : AttributeElement

    Wrapper AttributeElement.

    toUnwrap : AttributeElement

    AttributeElement to unwrap using wrapper element.

    Returns

    Boolean

    Returns true if elements are unwrapped.

  • _unwrapChildren( parent, startOffset, endOffset, attribute )

    private

    Unwraps children from provided attribute. Only children contained in parent element between startOffset and endOffset will be unwrapped.

    Parameters

    parent : Element
    startOffset : Number
    endOffset : Number
    attribute : Element
  • _wrapAttributeElement( wrapper, toWrap ) → Boolean

    private

    Wraps one AttributeElement into another by merging them if possible. When merging is possible - all attributes, styles and classes are moved from wrapper element to element being wrapped.

    Parameters

    wrapper : AttributeElement

    Wrapper AttributeElement.

    toWrap : AttributeElement

    AttributeElement to wrap using wrapper element.

    Returns

    Boolean

    Returns true if elements are merged.

  • _wrapChildren( parent, startOffset, endOffset, attribute )

    private

    Wraps children with provided attribute. Only children contained in parent element between startOffset and endOffset will be wrapped.

    Parameters

    parent : Element
    startOffset : Number
    endOffset : Number
    attribute : Element
  • _wrapPosition( position, attribute ) → Position

    private

    Helper function for wrap. Wraps position with provided attribute element. This method will also merge newly added attribute element with its siblings whenever possible.

    Throws CKEditorError view-writer-wrap-invalid-attribute when passed attribute element is not an instance of AttributeElement.

    Parameters

    position : Position
    attribute : AttributeElement

    Returns

    Position

    New position after wrapping.

  • _wrapRange( range, attribute ) → Range

    private

    Helper function for view.writer.wrap. Wraps range with provided attribute element. This method will also merge newly added attribute element with its siblings whenever possible.

    Throws CKEditorError view-writer-wrap-invalid-attribute when passed attribute element is not an instance of AttributeElement.

    Parameters

    range : Range
    attribute : AttributeElement

    Returns

    Range

    New range after wrapping, spanning over wrapping attribute element.