在CKEditor5中,在向下转换中,如何在另一个视图元素的开头插入一个视图元素?

时间:2019-06-07 09:55:08

标签: converters ckeditor5

我想在编辑视图的特定位置添加“装饰”(非语义)元素。

我对CKEditor5教程中给出的Block-Widget插件做了一些小的更改 https://ckeditor.com/docs/ckeditor5/latest/framework/guides/tutorials/implementing-a-block-widget.html

我在向下转换代码中添加了3行(“ const badge”等):

_defineConverters() {
    const conversion = this.editor.conversion;

    // <simpleBox> converters
    conversion.for( 'upcast' ).elementToElement( {
        model: 'simpleBox',
        view: {
            name: 'section',
            classes: 'simple-box'
        }
    } );
    conversion.for( 'dataDowncast' ).elementToElement( {
        model: 'simpleBox',
        view: {
            name: 'section',
            classes: 'simple-box'
        }
    } );
    conversion.for( 'editingDowncast' ).elementToElement( {
        model: 'simpleBox',
        view: ( modelElement, viewWriter ) => {
            const section = viewWriter.createContainerElement( 'section', { class: 'simple-box' } );

            const badge = viewWriter.createContainerElement( 'span', { class: 'cause-badge', style: 'font-weight: bold' } );
            viewWriter.insert( viewWriter.createPositionAt( badge, 0 ), viewWriter.createText('Simple Box') );
            viewWriter.insert( viewWriter.createPositionAt( section, 0), badge );

            return toWidget( section, viewWriter, { label: 'simple box widget' } );
        }
    } );
//....

因为我使用的是createPositionAt(section,0),所以我期望在小部件的开头(顶部)出现“简单框”。 但是,相反,我将其显示在小部件的末尾(底部)(在Firefox上)。 screenshot on Firefox

1 个答案:

答案 0 :(得分:0)

我认为最简单的方法是在模型中定义该星级元素,并为其添加适当的转换。

对于editing管道,您需要使用UIElement,它允许使用渲染功能在编辑器编辑区域中渲染任意HTML。您可以在custom UI elements POC中查看使用渲染功能的一些示例。

以下此类功能的简单存根:

// Define schema element
schema.register( 'simpleBoxStars', {
    allowIn: 'simpleBox',
    allowAttributes: [ 'rating' ]
} );

conversion.for( 'upcast' ).elementToElement( {
    model: ( viewElement, writer ) => {
        return writer.createElement( 'simpleBoxStars', { rating: viewElement.getAttribute( 'data-rating' ) } );
    },
    view: {
        name: 'span',
        classes: 'simple-box-stars'
    }
} );

conversion.for( 'editingDowncast' ).elementToElement( {
    model: 'simpleBoxStars',
    view: ( modelElement, writer ) => {
        const uiSpan = writer.createUIElement( 'span', { class: 'simple-box-stars' }, function( domDocument ) {
            const domElement = this.toDomElement( domDocument );

            // Customize this for you needs
            domElement.innerHTML = `This many stars: <span class="stars">${ modelElement.getAttribute( 'rating' ) }</span>`;


            //
            domElement.addEventListener( 'click', evt => {
                // detect which star was clicked
                editor.model.change( writer => {
                    // Change model elment value, ie by using .setAttribute()
                } );
            } );

            return domElement;
        } );

        return uiSpan;
    }
} );

// For editor.getData() just output the data normally:
conversion.for( 'dataDowncast' ).elementToElement( {
    model: 'simpleBoxStars',
    view: {
        name: 'span',
        classes: 'simple-box-stars'
    }
} );