Last active
June 26, 2019 15:05
-
-
Save nikitalarionov/61d56a0dacf8d63d8474854938b94643 to your computer and use it in GitHub Desktop.
Note plugin example
This file contains hidden or 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
// Example of data provided in ckEditor | |
// DATA = '`some text text text and: .... <div class="article-note js-tooltip">листовки<span class="article-note__tooltip"><span class="article-note__body js-tooltip-body" data-referal=""><img src="https://img03.rl0.ru/afisha/290x-/daily.afisha.ru/uploads/images/9/b5/9b50660636a19bb09f4314aa920cda1d.jpg" class="article-note__img js-article-note-img"></span></span></div>`;' | |
import Plugin from '@ckeditor/ckeditor5-core/src/plugin'; | |
import Widget from '@ckeditor/ckeditor5-widget/src/widget'; | |
import CKEditorInspector from '@ckeditor/ckeditor5-inspector'; | |
import {toWidget, toWidgetEditable, viewToModelPositionOutsideModelElement} from "@ckeditor/ckeditor5-widget/src/utils"; | |
const baseEditingCls = 'dailynote'; | |
export default class DailyNote extends Plugin { | |
static get requires() { | |
return [ Widget ]; | |
} | |
init() { | |
this._defineSchema(); | |
this._defineConverters(); | |
const name = this.editor.config.get('instanceName'); | |
if (name) { | |
setTimeout(() => { | |
// Attach inspector to editor | |
CKEditorInspector.attach(name, this.editor); | |
}, 2000); | |
} | |
} | |
_defineSchema() { | |
const schema = this.editor.model.schema; | |
schema.register( 'dailyNote', { | |
// Allow wherever text is allowed: | |
allowWhere: '$text', | |
// The daily note will act as an inline node: | |
isInline: true, | |
// The inline widget is self-contained | |
// It cannot be split by the caret and can be selected | |
isObject: true, | |
allowAttributes: [ 'text' , 'src' ] | |
}); | |
schema.register('dailyNoteText', { | |
allowWhere: 'dailyNote', | |
isInline: true, | |
allowAttributes: [ 'text' ] | |
}); | |
} | |
_defineConverters() { | |
const conversion = this.editor.conversion; | |
const entryType = this.editor.config.get('entryType'); | |
conversion.for( 'upcast' ).elementToElement({ | |
view: { | |
name: 'div', | |
classes: [ 'js-tooltip' ] | |
}, | |
model: (viewElement, modelWriter) => { | |
const text = viewElement.getChild(0).data; | |
const img = viewElement.getChild(1).getChild(0).getChild(0); | |
const context = { | |
text, | |
image: img.getAttribute('src'), | |
}; | |
const dailyNote = modelWriter.createElement('dailyNote', context); | |
modelWriter.appendElement('dailyNoteText', { text }, dailyNote); | |
return dailyNote; | |
} | |
}); | |
conversion.for('editingDowncast').elementToElement({ | |
model: 'dailyNote', | |
view: (modelItem, viewWriter) => { | |
const widgetElement = createDailyNoteView(modelItem, viewWriter); | |
return toWidget(widgetElement, viewWriter); | |
} | |
}); | |
conversion.for( 'editingDowncast' ).elementToElement( { | |
model: 'dailyNoteText', | |
view: ( modelElement, viewWriter ) => { | |
const text = modelElement.getAttribute('text'); | |
// Note: You use a more specialized createEditableElement() method here. | |
const spanEl = viewWriter.createEditableElement( 'span', { | |
class: `${baseEditingCls}__text` | |
}); | |
viewWriter.insert(viewWriter.createPositionAt(spanEl, 0), viewWriter.createText(text)); | |
return toWidgetEditable( spanEl, viewWriter ); | |
} | |
}); | |
conversion.for('dataDowncast').elementToElement({ | |
model: 'dailyNote', | |
view: (modelItem, viewWriter) => { | |
return createDailyNoteOutputView(modelItem, viewWriter, entryType); | |
} | |
}); | |
} | |
} | |
const createDailyNoteView = (modelItem, viewWriter) => { | |
const noteIconSrc = '/assets/icons/note-icon.svg'; | |
const text = modelItem.getAttribute('text'); | |
const dailyNoteView = getNoteContainerElement(viewWriter, baseEditingCls); | |
const imgIconEmptyElement = viewWriter.createEmptyElement( 'img' , { | |
'src': noteIconSrc, | |
'class': `${baseEditingCls}__icon` | |
}); | |
viewWriter.insert(viewWriter.createPositionAt(dailyNoteView, 0), imgIconEmptyElement); | |
return dailyNoteView; | |
}; | |
const createDailyNoteOutputView = (modelItem, viewWriter, entryType = 'article') => { | |
const text = modelItem.getAttribute('text'); | |
const src = modelItem.getAttribute('src'); | |
const className = `${entryType}-note js-tooltip`; | |
const tooltipClassName = `${entryType}-note__tooltip`; | |
const bodyClassName = `${entryType}-body js-tooltip-body`; | |
const dailyNoteOutputView = getNoteContainerElement(viewWriter, [className]); | |
const containerTooltip = getNoteContainerElement(viewWriter, [tooltipClassName]); | |
const noteBody = getNoteContainerElement(viewWriter, [bodyClassName]); | |
const emptyImgElement = viewWriter.createEmptyElement('img', { | |
src, | |
classes: [ | |
`${entryType}-note__img`, | |
`js-${entryType}-note-img` | |
] | |
}); | |
viewWriter.insert(viewWriter.createPositionAt(dailyNoteOutputView, 0), viewWriter.createText(text)); | |
viewWriter.insert(viewWriter.createPositionAt(noteBody, 0), emptyImgElement); | |
viewWriter.insert(viewWriter.createPositionAt(containerTooltip, 0), noteBody); | |
viewWriter.insert(viewWriter.createPositionAt(dailyNoteOutputView, 0), containerTooltip); | |
return dailyNoteOutputView; | |
}; | |
const getNoteContainerElement = (viewWriter, classes) => { | |
return viewWriter.createContainerElement( | |
'span', | |
{ | |
class: classes | |
} | |
); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment