Ghost/ghost/admin/lib/gh-koenig/addon/components/gh-koenig.js

155 lines
5.0 KiB
JavaScript
Raw Normal View History

import Ember from 'ember';
2017-03-01 21:50:08 +03:00
import layout from '../templates/components/gh-koenig';
import Mobiledoc from 'mobiledoc-kit';
import {MOBILEDOC_VERSION} from 'mobiledoc-kit/renderers/mobiledoc';
import createCardFactory from '../libs/card-factory';
import defaultCommands from '../options/default-commands';
import editorCards from '../cards/index';
//import { VALID_MARKUP_SECTION_TAGNAMES } from 'mobiledoc-kit/models/markup-section'; //the block elements supported by mobile-doc
export const BLANK_DOC = {
version: MOBILEDOC_VERSION,
atoms: [],
markups: [],
cards: [],
sections: []
};
export default Ember.Component.extend({
layout,
classNames: ['editor-holder'],
emberCards: Ember.A([]),
init() {
this._super(...arguments);
this.container = document.querySelector(".gh-editor-container")[0];
let mobiledoc = this.get('value') || BLANK_DOC;
let userCards = this.get('cards') || [];
if (typeof mobiledoc === "string") {
mobiledoc = JSON.parse(mobiledoc);
}
//if the doc is cached then the editor is loaded and we don't need to continue.
if (this._cached_doc && this._cached_doc === mobiledoc) {
return;
}
let createCard = createCardFactory.apply(this, {}); //need to pass the toolbar
const options = {
mobiledoc: mobiledoc,
//temp
cards: createCard(editorCards.concat(userCards)),
atoms: [{
name: 'soft-return',
type: 'dom',
render() {
return document.createElement('br');
}
}],
spellcheck: true,
autofocus: this.get('shouldFocusEditor'),
placeholder: 'Click here to start ...'
};
this.editor = new Mobiledoc.Editor(options);
},
willRender() {
if(this._rendered) {
return;
}
let editor =this.editor;
editor.willRender(() => {
//console.log(Ember.run.currentRunLoop);
//if (!Ember.run.currentRunLoop) {
// this._startedRunLoop = true;
// Ember.run.begin();
//}
});
editor.didRender(() => {
this.sendAction('loaded', editor);
//Ember.run.end();
});
editor.postDidChange(()=> {
Ember.run.join(() => {
//store a cache of the local doc so that we don't need to reinitialise it.
this._cached_doc = editor.serialize(MOBILEDOC_VERSION);
this.sendAction('onChange', this._cached_doc);
if (this._cached_doc !== BLANK_DOC && !this._firstChange) {
this._firstChange = true;
this.sendAction('onFirstChange', this._cached_doc);
}
});
});
},
didRender() {
if(this._rendered) {
return;
}
let editorDom = this.$('.surface')[0];
this.domContainer = editorDom.parentNode.parentNode.parentNode.parentNode; // nasty nasty nasty.
this.editor.render(editorDom);
this._rendered = true;
window.editor = this.editor;
defaultCommands(this.editor); // initialise the custom text handlers for MD, etc.
// shouldFocusEditor is only true when transitioning from new to edit, otherwise it's false or undefined.
// therefore, if it's true it's after the first lot of content is entered and we expect the caret to be at the
// end of the document.
if (this.get('shouldFocusEditor')) {
var range = document.createRange();
range.selectNodeContents(this.editor.element);
range.collapse(false);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
this.editor._ensureFocus();
}
this.editor.cursorDidChange(() => this.cursorMoved());
},
// drag and drop images onto the editor
drop(event) {
if(event.dataTransfer.files.length) {
event.preventDefault();
for (let i = 0; i < event.dataTransfer.files.length; i++) {
let file = [event.dataTransfer.files[i]];
this.editor.insertCard('image-card', {pos: 'top', file});
}
}
},
// makes sure the cursor is on screen.
cursorMoved() {
const scrollBuffer = 33; // the extra buffer to scroll.
const range = window.getSelection().getRangeAt(0); // get the actual range within the DOM.
const position = range.getBoundingClientRect();
const windowHeight = window.innerHeight;
if(position.bottom > windowHeight ) {
this.domContainer.scrollTop += position.bottom - windowHeight + scrollBuffer;
} else if(position.top < 0) {
this.domContainer.scrollTop += position.top - scrollBuffer;
}
},
willDestroy() {
this.editor.destroy();
}
});