2014-06-17 01:44:09 +04:00
|
|
|
/*global CodeMirror */
|
|
|
|
|
2014-06-06 05:18:03 +04:00
|
|
|
import MarkerManager from 'ghost/mixins/marker-manager';
|
2014-06-24 05:17:57 +04:00
|
|
|
import mobileCodeMirror from 'ghost/utils/codemirror-mobile';
|
2014-06-06 05:18:03 +04:00
|
|
|
import setScrollClassName from 'ghost/utils/set-scroll-classname';
|
2014-06-24 05:17:57 +04:00
|
|
|
import codeMirrorShortcuts from 'ghost/utils/codemirror-shortcuts';
|
|
|
|
|
2014-10-25 01:09:50 +04:00
|
|
|
var onChangeHandler,
|
|
|
|
onScrollHandler,
|
|
|
|
Codemirror;
|
|
|
|
|
2014-06-24 05:17:57 +04:00
|
|
|
codeMirrorShortcuts.init();
|
2014-06-06 05:18:03 +04:00
|
|
|
|
2014-10-25 01:09:50 +04:00
|
|
|
onChangeHandler = function (cm, changeObj) {
|
2014-06-06 05:18:03 +04:00
|
|
|
var line,
|
2014-10-04 20:38:15 +04:00
|
|
|
component = cm.component;
|
2014-06-06 05:18:03 +04:00
|
|
|
|
|
|
|
// fill array with a range of numbers
|
|
|
|
for (line = changeObj.from.line; line < changeObj.from.line + changeObj.text.length; line += 1) {
|
2014-08-01 00:29:35 +04:00
|
|
|
component.checkLine.call(component, line, changeObj.origin);
|
2014-06-06 05:18:03 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Is this a line which may have had a marker on it?
|
2014-08-01 00:29:35 +04:00
|
|
|
component.checkMarkers.call(component);
|
2014-03-02 18:30:35 +04:00
|
|
|
|
2014-06-24 05:17:57 +04:00
|
|
|
cm.component.set('value', cm.getValue());
|
2014-10-08 18:53:20 +04:00
|
|
|
|
2014-10-20 22:03:11 +04:00
|
|
|
component.sendAction('typingPause');
|
2014-03-02 18:30:35 +04:00
|
|
|
};
|
|
|
|
|
2014-10-25 01:09:50 +04:00
|
|
|
onScrollHandler = function (cm) {
|
2014-03-02 18:30:35 +04:00
|
|
|
var scrollInfo = cm.getScrollInfo(),
|
|
|
|
component = cm.component;
|
|
|
|
|
2014-06-06 05:18:03 +04:00
|
|
|
scrollInfo.codemirror = cm;
|
|
|
|
|
2014-03-02 18:30:35 +04:00
|
|
|
// throttle scroll updates
|
|
|
|
component.throttle = Ember.run.throttle(component, function () {
|
2014-06-06 05:18:03 +04:00
|
|
|
this.set('scrollInfo', scrollInfo);
|
|
|
|
}, 10);
|
2014-03-02 18:30:35 +04:00
|
|
|
};
|
|
|
|
|
2014-10-25 01:09:50 +04:00
|
|
|
Codemirror = Ember.TextArea.extend(MarkerManager, {
|
2014-10-18 15:16:43 +04:00
|
|
|
focus: true,
|
2014-11-16 03:05:28 +03:00
|
|
|
focusCursorAtEnd: false,
|
2014-10-18 15:16:43 +04:00
|
|
|
|
|
|
|
setFocus: function () {
|
2014-11-16 03:05:28 +03:00
|
|
|
if (this.get('focus')) {
|
2014-10-18 15:16:43 +04:00
|
|
|
this.$().val(this.$().val()).focus();
|
|
|
|
}
|
|
|
|
}.on('didInsertElement'),
|
|
|
|
|
2014-06-06 05:18:03 +04:00
|
|
|
didInsertElement: function () {
|
|
|
|
Ember.run.scheduleOnce('afterRender', this, this.afterRenderEvent);
|
|
|
|
},
|
|
|
|
|
|
|
|
afterRenderEvent: function () {
|
2014-11-17 22:35:04 +03:00
|
|
|
var self = this,
|
|
|
|
codemirror;
|
2014-06-06 05:18:03 +04:00
|
|
|
|
2014-06-24 05:17:57 +04:00
|
|
|
// replaces CodeMirror with TouchEditor only if we're on mobile
|
|
|
|
mobileCodeMirror.createIfMobile();
|
|
|
|
|
2014-11-16 03:05:28 +03:00
|
|
|
codemirror = this.initCodemirror();
|
|
|
|
this.set('codemirror', codemirror);
|
|
|
|
|
2014-06-24 05:17:57 +04:00
|
|
|
this.sendAction('setCodeMirror', this);
|
2014-11-16 03:05:28 +03:00
|
|
|
|
|
|
|
if (this.get('focus') && this.get('focusCursorAtEnd')) {
|
|
|
|
codemirror.execCommand('goDocEnd');
|
|
|
|
}
|
2014-11-17 22:35:04 +03:00
|
|
|
|
|
|
|
codemirror.eachLine(function initMarkers() {
|
|
|
|
self.initMarkers.apply(self, arguments);
|
|
|
|
});
|
2014-06-06 05:18:03 +04:00
|
|
|
},
|
|
|
|
|
|
|
|
// this needs to be placed on the 'afterRender' queue otherwise CodeMirror gets wonky
|
2014-03-02 18:30:35 +04:00
|
|
|
initCodemirror: function () {
|
|
|
|
// create codemirror
|
2014-11-16 03:05:28 +03:00
|
|
|
var codemirror,
|
|
|
|
self = this;
|
|
|
|
|
|
|
|
codemirror = CodeMirror.fromTextArea(this.get('element'), {
|
2014-06-06 05:18:03 +04:00
|
|
|
mode: 'gfm',
|
|
|
|
tabMode: 'indent',
|
|
|
|
tabindex: '2',
|
|
|
|
cursorScrollMargin: 10,
|
|
|
|
lineWrapping: true,
|
|
|
|
dragDrop: false,
|
|
|
|
extraKeys: {
|
|
|
|
Home: 'goLineLeft',
|
2014-09-24 19:08:10 +04:00
|
|
|
End: 'goLineRight',
|
|
|
|
'Ctrl-U': false,
|
|
|
|
'Cmd-U': false,
|
|
|
|
'Shift-Ctrl-U': false,
|
|
|
|
'Shift-Cmd-U': false,
|
|
|
|
'Ctrl-S': false,
|
|
|
|
'Cmd-S': false,
|
|
|
|
'Ctrl-D': false,
|
|
|
|
'Cmd-D': false
|
2014-06-06 05:18:03 +04:00
|
|
|
}
|
2014-03-02 18:30:35 +04:00
|
|
|
});
|
2014-06-06 05:18:03 +04:00
|
|
|
|
2014-11-16 03:05:28 +03:00
|
|
|
// Codemirror needs a reference to the component
|
|
|
|
// so that codemirror originating events can propogate
|
|
|
|
// up the ember action pipeline
|
|
|
|
codemirror.component = this;
|
2014-03-02 18:30:35 +04:00
|
|
|
|
|
|
|
// propagate changes to value property
|
2014-06-06 05:18:03 +04:00
|
|
|
codemirror.on('change', onChangeHandler);
|
2014-03-02 18:30:35 +04:00
|
|
|
|
|
|
|
// on scroll update scrollPosition property
|
2014-06-06 05:18:03 +04:00
|
|
|
codemirror.on('scroll', onScrollHandler);
|
|
|
|
|
|
|
|
codemirror.on('scroll', Ember.run.bind(Ember.$('.CodeMirror-scroll'), setScrollClassName, {
|
2014-09-03 07:42:03 +04:00
|
|
|
target: Ember.$('.js-entry-markdown'),
|
2014-06-06 05:18:03 +04:00
|
|
|
offset: 10
|
|
|
|
}));
|
|
|
|
|
2014-10-18 15:16:43 +04:00
|
|
|
codemirror.on('focus', function () {
|
2014-11-16 03:05:28 +03:00
|
|
|
self.sendAction('onFocusIn');
|
2014-10-18 15:16:43 +04:00
|
|
|
});
|
|
|
|
|
2014-11-16 03:05:28 +03:00
|
|
|
return codemirror;
|
2014-06-06 05:18:03 +04:00
|
|
|
},
|
|
|
|
|
|
|
|
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);
|
|
|
|
},
|
2014-03-02 18:30:35 +04:00
|
|
|
|
|
|
|
removeThrottle: function () {
|
|
|
|
Ember.run.cancel(this.throttle);
|
2014-03-04 00:18:10 +04:00
|
|
|
}.on('willDestroyElement'),
|
2014-03-02 18:30:35 +04:00
|
|
|
|
|
|
|
removeCodemirrorHandlers: function () {
|
|
|
|
// not sure if this is needed.
|
2014-06-06 05:18:03 +04:00
|
|
|
var codemirror = this.get('codemirror');
|
|
|
|
codemirror.off('change', onChangeHandler);
|
|
|
|
codemirror.off('scroll');
|
|
|
|
}.on('willDestroyElement'),
|
|
|
|
|
|
|
|
clearMarkerManagerMarkers: function () {
|
|
|
|
this.clearMarkers();
|
2014-03-04 00:18:10 +04:00
|
|
|
}.on('willDestroyElement')
|
|
|
|
});
|
2014-03-02 18:30:35 +04:00
|
|
|
|
2014-05-28 23:26:05 +04:00
|
|
|
export default Codemirror;
|