Ghost/ghost/admin/components/gh-codemirror.js
David Arvelo 2151d8a49f Reach Editor parity with Ember
closes #2426, closes #2781, closes #2913
- Concatenate vendor files on change of js in core/shared/
- Add all the markerManager stuff to its own mixin
- make markers a shared object for all that mix it in. makes it easier to use helper functions in different modules
- add getMarkdown method, returns object with two keys holding the markdown: one with markers, the other without
- Clear markers when codemirror is destroyed
- make Editor subcomponents communicate through the Editor Controller
- Set Codemirror and html preview shared scrolling
- Set CodeMirror, html preview css scroll class with util
- Create 'scratch' property in Editor controller; prevents a model save wiping image markers due to markdown bindings
- Add editor and html preview actions to handle img upload start/finish
- disable codemirror when an image is being uploaded, enables on success or failure
- Fix editor wordcount when there are 0 words
- Add modal dialog when transitioning out of the editor with an unsaved post
- Add window.onbeforeunload handling with `.unloadDirtyMessage()` on editor controller
- and various other things
2014-06-13 18:12:03 -04:00

115 lines
3.5 KiB
JavaScript

/* global CodeMirror*/
import MarkerManager from 'ghost/mixins/marker-manager';
import setScrollClassName from 'ghost/utils/set-scroll-classname';
var onChangeHandler = function (cm, changeObj) {
var line,
component = cm.component,
checkLine = component.checkLine.bind(component),
checkMarkers = component.checkMarkers.bind(component);
// fill array with a range of numbers
for (line = changeObj.from.line; line < changeObj.from.line + changeObj.text.length; line += 1) {
checkLine(line, changeObj.origin);
}
// Is this a line which may have had a marker on it?
checkMarkers();
cm.component.set('value', cm.getDoc().getValue());
};
var onScrollHandler = function (cm) {
var scrollInfo = cm.getScrollInfo(),
component = cm.component;
scrollInfo.codemirror = cm;
// throttle scroll updates
component.throttle = Ember.run.throttle(component, function () {
this.set('scrollInfo', scrollInfo);
}, 10);
};
var Codemirror = Ember.TextArea.extend(MarkerManager, {
didInsertElement: function () {
Ember.run.scheduleOnce('afterRender', this, this.afterRenderEvent);
},
afterRenderEvent: function () {
var initMarkers = this.initMarkers.bind(this);
this.initCodemirror();
this.codemirror.eachLine(initMarkers);
this.sendAction('action', this);
},
// this needs to be placed on the 'afterRender' queue otherwise CodeMirror gets wonky
initCodemirror: function () {
// create codemirror
var codemirror = CodeMirror.fromTextArea(this.get('element'), {
mode: 'gfm',
tabMode: 'indent',
tabindex: '2',
cursorScrollMargin: 10,
lineWrapping: true,
dragDrop: false,
extraKeys: {
Home: 'goLineLeft',
End: 'goLineRight'
}
});
codemirror.component = this; // save reference to this
// propagate changes to value property
codemirror.on('change', onChangeHandler);
// on scroll update scrollPosition property
codemirror.on('scroll', onScrollHandler);
codemirror.on('scroll', Ember.run.bind(Ember.$('.CodeMirror-scroll'), setScrollClassName, {
target: Ember.$('.entry-markdown'),
offset: 10
}));
this.set('codemirror', codemirror);
},
disableCodeMirror: function () {
var codemirror = this.get('codemirror');
codemirror.setOption('readOnly', 'nocursor');
codemirror.off('change', onChangeHandler);
},
enableCodeMirror: function () {
var codemirror = this.get('codemirror');
codemirror.setOption('readOnly', false);
// clicking the trash button on an image dropzone causes this function to fire.
// this line is a hack to prevent multiple event handlers from being attached.
codemirror.off('change', onChangeHandler);
codemirror.on('change', onChangeHandler);
},
removeThrottle: function () {
Ember.run.cancel(this.throttle);
}.on('willDestroyElement'),
removeCodemirrorHandlers: function () {
// not sure if this is needed.
var codemirror = this.get('codemirror');
codemirror.off('change', onChangeHandler);
codemirror.off('scroll');
}.on('willDestroyElement'),
clearMarkerManagerMarkers: function () {
this.clearMarkers();
}.on('willDestroyElement')
});
export default Codemirror;