ui/lib/pipeline/addon/components/pipeline-codemirror/component.js

126 lines
3.3 KiB
JavaScript

import CodeMirror from 'codemirror';
import layout from './template'
import { get } from '@ember/object';
import { observer } from '@ember/object';
import Component from '@ember/component';
import { bind, once, scheduleOnce } from '@ember/runloop';
import { inject as service } from '@ember/service';
export default Component.extend({
codeMirror: service(),
layout,
tagName: 'textarea',
didInsertElement() {
this._super(...arguments);
CodeMirror.registerHelper('hint', 'anyword', (editor /* ,options*/) => {
var cur = editor.getCursor();
var end = cur.ch, start = end;
var matched = get(this, 'codeMirror').getMatchedHint(editor.getValue(), editor);
return {
list: matched.matchedArry,
from: CodeMirror.Pos(cur.line, start - matched.index),
to: CodeMirror.Pos(cur.line, end)
};
});
this._codeMirror = get(this, 'codeMirror').fromTextArea(get(this, 'elementId'), get(this, 'element'));
var arrows = [37, 38, 39, 40, 13]
this._codeMirror.on('keyup', (cm, e) => {
if (arrows.indexOf(e.keyCode) < 0) {
this._codeMirror.showHint({ completeSingle: false })
}
})
// Send a "valueUpdated" action when CodeMirror triggers a "change" event.
this.setupCodeMirrorEventHandler('change', this, this.scheduleValueUpdatedAction);
},
didRender() {
this._super(...arguments);
this.updateCodeMirrorOptions();
this.updateCodeMirrorValue();
},
willDestroyElement() {
this._super(...arguments);
// Remove the editor and restore the original textarea.
this._codeMirror.toTextArea();
get(this, 'codeMirror').unregisterInstance(get(this, 'elementId'));
delete this._codeMirror;
},
isVisibleDidChange: observer('isVisible', function() {
if (this._wasVisible === get(this, 'isVisible')) {
return;
}
scheduleOnce('render', this, this.toggleVisibility);
}),
scheduleValueUpdatedAction(codeMirror, changeObj) {
once(this, this.sendValueUpdatedAction, codeMirror.getValue(), codeMirror, changeObj);
},
setupCodeMirrorEventHandler(event, target, method) {
const callback = bind(target, method);
this._codeMirror.on(event, callback);
this.one('willDestroyElement', this, function() {
this._codeMirror.off(event, callback);
});
},
sendValueUpdatedAction(...args) {
if (this.valueUpdated) {
this.valueUpdated(...args);
}
},
toggleVisibility() {
const isVisible = get(this, 'isVisible');
if (this._wasVisible === isVisible) {
return;
}
this._wasVisible = isVisible;
if (isVisible) {
// Force a refresh when becoming visible, since CodeMirror won't render
// itself onto a hidden element.
this._codeMirror.refresh();
}
},
updateCodeMirrorOption(option, value) {
if (this._codeMirror.getOption(option) !== value) {
this._codeMirror.setOption(option, value);
}
},
updateCodeMirrorOptions() {
const options = get(this, 'options');
if (options) {
Object.keys(options).forEach(function(option) {
this.updateCodeMirrorOption(option, options[option]);
}, this);
}
},
updateCodeMirrorValue() {
const value = get(this, 'value');
if (value !== this._codeMirror.getValue()) {
this._codeMirror.setValue(value || '');
}
},
});