UNPKG

ember-simplemde

Version:

A component wrapper for SimpleMDE markdown editor

135 lines (117 loc) 3.48 kB
import { once } from '@ember/runloop'; import { getOwner } from '@ember/application'; import TextArea from '@ember/component/text-area'; import { assign, merge } from '@ember/polyfills'; import { get, computed } from '@ember/object'; import { typeOf, isEmpty } from '@ember/utils'; import Ember from 'ember'; import layout from '../templates/components/simple-mde'; const { testing } = Ember; /*global SimpleMDE*/ const options = {}; export default TextArea.extend({ layout, /** * @private * @variable * to hold the SimpleMDE instance */ currentEditor: null, /** * action to call when the value on the editor changes */ change: null, /** * instance options to pass to simpleMDE */ options: options, /** * default simpleMDE options */ defaultSimpleMdeOptions: computed(function () { return { showIcons: ['table'], }; }), /** * global options defined in consuming apps config */ globalSimpleMdeOptions: computed(function() { if(testing) { return {}; } else { return get(getOwner(this).resolveRegistration('config:environment'), 'simpleMDE') || {}; } }), /** * @method * @private * get the list of options to pass to init the SimpleMDE instance */ buildSimpleMDEOptions: computed(function () { let builtOptions = assign({}, this.get('defaultSimpleMdeOptions'), this.get('globalSimpleMdeOptions'), this.get('options')); if(builtOptions.toolbar && typeOf(builtOptions.toolbar) === 'array') { builtOptions.toolbar.forEach(this.unpackToolbarOption); } return builtOptions; }), /** * @method * @private * Because simpleMDE needs toolbar options action handler to be a function reference, * and if toolbar options are passed in from the consuming apps config they are passed in as strings. * Thus, we unpack them and restore the global reference. * If the toolbar action handler is a string, we attempt to reference the global function reference matching that string. */ unpackToolbarOption: function(toolbarOption) { if(typeOf(toolbarOption.action) === 'string') { toolbarOption.action = toolbarOption.action .split('.') .reduce(function(accumulator, value) { if(!accumulator) { accumulator = window[value]; } else { accumulator = accumulator[value]; } return accumulator; }, null); } }, /** * @event * @public * instantiate the editor with the contents of value */ didInsertElement () { this.set('currentEditor', new SimpleMDE( merge({ element: document.getElementById(this.elementId) }, this.get('buildSimpleMDEOptions') ) )); this.get('currentEditor').value(this.get('value') || ''); this.get('currentEditor').codemirror.on('change', () => once(this, function() { if (this.change) { this.change(this.get('currentEditor').value()) } })); }, willDestroyElement() { this.get('currentEditor').toTextArea(); this.set('currentEditor', null); }, /** * @event * @public * updates the editor when the value property change from the outside */ didReceiveAttrs () { let editor = this.get('currentEditor'); if (isEmpty(editor)) { return; } let cursor = editor.codemirror.getDoc().getCursor(); editor.value(this.get('value') || ''); editor.codemirror.getDoc().setCursor(cursor); } });