119 lines
4.1 KiB
JavaScript
119 lines
4.1 KiB
JavaScript
import { Plugin, Widget, toWidget, viewToModelPositionOutsideModelElement } from 'ckeditor5';
|
|
import FieldCommand from './fieldcommand';
|
|
|
|
String.prototype.rtrim = function (s) {
|
|
if (s === undefined)
|
|
s = '\\s';
|
|
return this.replace(new RegExp("[" + s + "]*$"), '');
|
|
};
|
|
String.prototype.ltrim = function (s) {
|
|
if (s === undefined)
|
|
s = '\\s';
|
|
return this.replace(new RegExp("^[" + s + "]*"), '');
|
|
};
|
|
|
|
export class FieldConfig{
|
|
fields = [ ]
|
|
}
|
|
|
|
export default class FieldEditing extends Plugin {
|
|
static get requires() {
|
|
return [ Widget ];
|
|
}
|
|
|
|
init() {
|
|
this._defineSchema();
|
|
this._defineConverters();
|
|
|
|
this.editor.commands.add( 'field', new FieldCommand( this.editor ) );
|
|
|
|
this.editor.editing.mapper.on(
|
|
'viewToModelPosition',
|
|
viewToModelPositionOutsideModelElement( this.editor.model, viewElement => viewElement.hasClass( 'field' ) )
|
|
);
|
|
this.editor.config.define( 'fieldConfig', FieldConfig );
|
|
}
|
|
|
|
_defineSchema() {
|
|
const schema = this.editor.model.schema;
|
|
|
|
schema.register( 'field', {
|
|
// Behaves like a self-contained inline object (e.g. an inline image)
|
|
// allowed in places where $text is allowed (e.g. in paragraphs).
|
|
// The inline widget can have the same attributes as text (for example linkHref, bold).
|
|
inheritAllFrom: '$inlineObject',
|
|
|
|
// The field can have many types, like date, name, surname, etc:
|
|
allowAttributes: [ 'field' ]
|
|
} );
|
|
}
|
|
|
|
_defineConverters() {
|
|
const conversion = this.editor.conversion;
|
|
|
|
conversion.for( 'upcast' ).elementToElement( {
|
|
view: {
|
|
name: 'span',
|
|
classes: [ 'field' ]
|
|
},
|
|
model: (viewElement, conversionApi) => {
|
|
// Extract the "name" from "{name}".
|
|
if (viewElement === undefined) {
|
|
return null;
|
|
}
|
|
|
|
const { writer } = conversionApi;
|
|
|
|
const name = viewElement.getChild(0)?._textData;
|
|
|
|
const fieldtype = viewElement.getAttribute("fieldtype");
|
|
const guid = viewElement.getAttribute("guid");
|
|
const fieldid = viewElement.getAttribute("fieldid");
|
|
|
|
const field = {
|
|
name,
|
|
type: fieldtype,
|
|
guid,
|
|
fieldid
|
|
};
|
|
|
|
|
|
return writer.createElement('field', { field });
|
|
}
|
|
} );
|
|
|
|
conversion.for( 'editingDowncast' ).elementToElement( {
|
|
model: 'field',
|
|
view: ( modelItem, { writer: viewWriter } ) => {
|
|
const widgetElement = createfieldView( modelItem, viewWriter );
|
|
|
|
// Enable widget handling on a field element inside the editing view.
|
|
return toWidget( widgetElement, viewWriter );
|
|
}
|
|
} );
|
|
|
|
conversion.for( 'dataDowncast' ).elementToElement( {
|
|
model: 'field',
|
|
view: ( modelItem, { writer: viewWriter } ) => createfieldView( modelItem, viewWriter )
|
|
} );
|
|
|
|
// Helper method for both downcast converters.
|
|
// function createfieldView( modelItem : Element, viewWriter : DowncastWriter ) {
|
|
function createfieldView( modelItem, viewWriter ) {
|
|
const field = modelItem.getAttribute( 'field' ); //todo any is a cop out.
|
|
|
|
const fieldView = viewWriter.createContainerElement( 'span', {
|
|
class: 'field',
|
|
fieldType: field.type,
|
|
guid: field.guid,
|
|
fieldid: (field.guid !== undefined) ? null : field.id
|
|
} );
|
|
|
|
// Insert the field name (as a text).
|
|
const innerText = viewWriter.createText( '{' + field.name.ltrim('{').rtrim('}') + '}' );
|
|
viewWriter.insert( viewWriter.createPositionAt( fieldView, 0 ), innerText );
|
|
|
|
return fieldView;
|
|
}
|
|
}
|
|
} |