Last active
June 27, 2019 16:08
-
-
Save nikitalarionov/e0dbbb580d181e6363b19b49ac1d46d4 to your computer and use it in GitHub Desktop.
Latest ckEditor DailyNotePlugin
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
import Command from '@ckeditor/ckeditor5-core/src/command'; | |
export default class EditDailyNoteCommand extends Command { | |
execute() { | |
const editor = this.editor; | |
const model = editor.model; | |
const doc = model.document; | |
const selection = doc.selection; | |
const selectedElement = selection.getSelectedElement(); | |
if (selectedElement.name === 'dailyNote') { | |
model.enqueueChange(writer => { | |
const text = selectedElement.getAttribute('text'); | |
const src = selectedElement.getAttribute('src'); | |
writer.setAttribute('text', 'new text', selectedElement); | |
console.log(editor.getData()); | |
}); | |
} | |
} | |
} |
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
/** some text text text and: ....<span class="article-note js-tooltip"><span class="article-note__tooltip"><span class="article-body js-tooltip-body"><img src="https://img03.rl0.ru/afisha/290x-/daily.afisha.ru/uploads/images/9/b5/9b50660636a19bb09f4314aa920cda1d.jpg" classes="article-note__img js-article-note-img"></span></span>new text</span> **/ | |
import Plugin from '@ckeditor/ckeditor5-core/src/plugin'; | |
import Widget from '@ckeditor/ckeditor5-widget/src/widget'; | |
import CKEditorInspector from '@ckeditor/ckeditor5-inspector'; | |
import { toWidget, viewToModelPositionOutsideModelElement } from "@ckeditor/ckeditor5-widget/src/utils"; | |
import EditDailyNoteCommand from "./edit_command"; | |
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'); | |
// Register edit command | |
this.editor.commands.add('editDailyNote', new EditDailyNoteCommand(this.editor)); | |
if (name) { | |
setTimeout(() => { | |
// Attach inspector to editor | |
CKEditorInspector.attach(name, this.editor); | |
}, 2000); | |
} | |
this.editor.editing.mapper.on( | |
'viewToModelPosition', | |
viewToModelPositionOutsideModelElement( | |
this.editor.model, | |
viewElement => viewElement.hasClass('dailynote') | |
) | |
); | |
this.listenTo( this.editor.editing.view.document, 'click', ( evt, data ) => { | |
const { domTarget } = data; | |
if (domTarget.classList.contains('dailynote__icon')) { | |
this.editor.execute('editDailyNote', {foo: 'bar'}); | |
} | |
}); | |
} | |
_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' ] | |
}); | |
} | |
_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'), | |
}; | |
return modelWriter.createElement('dailyNote', context); | |
} | |
}); | |
conversion.for('editingDowncast').elementToElement({ | |
model: 'dailyNote', | |
view: (modelItem, viewWriter) => { | |
const widgetElement = createDailyNoteView(modelItem, viewWriter); | |
// Enable widget handling on a daily note element inside the editing view. | |
return toWidget(widgetElement, viewWriter); | |
} | |
}); | |
// Конвектируем dailyNote в выходной формат для фронта дейли | |
conversion.for('dataDowncast').elementToElement({ | |
model: 'dailyNote', | |
view: (modelItem, viewWriter) => { | |
return createDailyNoteOutputView(modelItem, viewWriter, entryType); | |
} | |
}); | |
} | |
} | |
/** | |
* Возвращает View для редактирования внутри CkEditor | |
* @param modelItem | |
* @param viewWriter | |
* @return {*} | |
*/ | |
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); | |
viewWriter.insert(viewWriter.createPositionAt(dailyNoteView, 0), viewWriter.createText(text)); | |
return dailyNoteView; | |
}; | |
/** | |
* Возвращает View для фронта дейли | |
* @param modelItem | |
* @param viewWriter | |
* @param entryType {String} - article, news, etc | |
*/ | |
const createDailyNoteOutputView = (modelItem, viewWriter, entryType = 'article') => { | |
const text = modelItem.getAttribute('text'); | |
const src = modelItem.getAttribute('image'); | |
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` | |
].join(' ') | |
}); | |
viewWriter.insert(viewWriter.createPositionAt(noteBody, 0), emptyImgElement); | |
viewWriter.insert(viewWriter.createPositionAt(containerTooltip, 0), noteBody); | |
viewWriter.insert(viewWriter.createPositionAt(dailyNoteOutputView, 0), containerTooltip); | |
viewWriter.insert(viewWriter.createPositionAt(dailyNoteOutputView, 0), viewWriter.createText(text)); | |
return dailyNoteOutputView; | |
}; | |
const getNoteContainerElement = (viewWriter, classes, div = false) => { | |
return viewWriter.createContainerElement( | |
div ? 'div' : 'span', | |
{ | |
class: classes | |
} | |
); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment