Stackedit/src/components/common/EditorClassApplier.js

85 lines
2.5 KiB
JavaScript
Raw Normal View History

2018-02-17 11:18:30 +00:00
import cledit from '../../services/cledit';
import editorSvc from '../../services/editorSvc';
import utils from '../../services/utils';
let savedSelection = null;
const nextTickCbs = [];
const nextTickExecCbs = cledit.Utils.debounce(() => {
while (nextTickCbs.length) {
nextTickCbs.shift()();
}
if (savedSelection) {
editorSvc.clEditor.selectionMgr.setSelectionStartEnd(
savedSelection.start, savedSelection.end);
}
savedSelection = null;
});
const nextTick = (cb) => {
nextTickCbs.push(cb);
nextTickExecCbs();
};
const nextTickRestoreSelection = () => {
savedSelection = {
start: editorSvc.clEditor.selectionMgr.selectionStart,
end: editorSvc.clEditor.selectionMgr.selectionEnd,
};
nextTickExecCbs();
};
export default class EditorClassApplier {
constructor(classGetter, offsetGetter, properties) {
this.classGetter = typeof classGetter === 'function' ? classGetter : () => classGetter;
this.offsetGetter = typeof offsetGetter === 'function' ? offsetGetter : () => offsetGetter;
this.properties = properties || {};
this.eltCollection = editorSvc.editorElt.getElementsByClassName(this.classGetter()[0]);
this.lastEltCount = this.eltCollection.length;
this.restoreClass = () => {
if (!this.eltCollection.length || this.eltCollection.length !== this.lastEltCount) {
this.removeClass();
this.applyClass();
}
};
editorSvc.clEditor.on('contentChanged', this.restoreClass);
nextTick(() => this.applyClass());
}
applyClass() {
const offset = this.offsetGetter();
if (offset && offset.start !== offset.end) {
const range = editorSvc.clEditor.selectionMgr.createRange(
Math.min(offset.start, offset.end),
Math.max(offset.start, offset.end),
);
const properties = {
...this.properties,
className: this.classGetter().join(' '),
};
editorSvc.clEditor.watcher.noWatch(() => {
utils.wrapRange(range, properties);
});
if (editorSvc.clEditor.selectionMgr.hasFocus()) {
nextTickRestoreSelection();
}
this.lastEltCount = this.eltCollection.length;
}
}
removeClass() {
editorSvc.clEditor.watcher.noWatch(() => {
utils.unwrapRange(this.eltCollection);
});
if (editorSvc.clEditor.selectionMgr.hasFocus()) {
nextTickRestoreSelection();
}
}
stop() {
editorSvc.clEditor.off('contentChanged', this.restoreClass);
nextTick(() => this.removeClass());
}
}