diff --git a/ghost/admin/app/components/gh-input.js b/ghost/admin/app/components/gh-input.js index cf54344a17..9ccb972cf2 100644 --- a/ghost/admin/app/components/gh-input.js +++ b/ghost/admin/app/components/gh-input.js @@ -2,14 +2,5 @@ import OneWayInput from 'ember-one-way-controls/components/one-way-input'; import TextInputMixin from 'ghost-admin/mixins/text-input'; export default OneWayInput.extend(TextInputMixin, { - classNames: 'gh-input', - - // prevent default TAB behaviour if we have a keyEvent for it - keyDown(event) { - if (event.keyCode === 9 && this.get('keyEvents.9')) { - event.preventDefault(); - } - - this._super(...arguments); - } + classNames: 'gh-input' }); diff --git a/ghost/admin/app/components/gh-textarea.js b/ghost/admin/app/components/gh-textarea.js index ed9437c8ce..4f69ce17b0 100644 --- a/ghost/admin/app/components/gh-textarea.js +++ b/ghost/admin/app/components/gh-textarea.js @@ -1,6 +1,68 @@ import OneWayTextarea from 'ember-one-way-controls/components/one-way-textarea'; import TextInputMixin from 'ghost-admin/mixins/text-input'; +import run from 'ember-runloop'; +import injectService from 'ember-service/inject'; export default OneWayTextarea.extend(TextInputMixin, { - classNames: 'gh-input' + resizeDetector: injectService(), + + classNames: 'gh-input', + + autoExpand: false, + + willInsertElement() { + this._super(...arguments); + + // disable the draggable resize element that browsers add to textareas + if (this.get('autoExpand')) { + this.element.style.resize = 'none'; + } + }, + + didInsertElement() { + this._super(...arguments); + + // set up resize handler on element insert so that we can autoexpand + // when the element container changes size + if (this.get('autoExpand')) { + run.scheduleOnce('afterRender', this, this._setupAutoExpand); + } + }, + + didReceiveAttrs() { + this._super(...arguments); + + // trigger auto-expand any time the value changes + if (this.get('autoExpand')) { + run.scheduleOnce('afterRender', this, this._autoExpand); + } + }, + + willDestroyElement() { + this._teardownAutoExpand(); + this._super(...arguments); + }, + + _autoExpand() { + let el = this.element; + + // collapse the element first so that we can shrink as well as expand + // then set the height to match the text height + el.style.height = 0; + el.style.height = `${el.scrollHeight}px`; + }, + + _setupAutoExpand() { + this._resizeCallback = run.bind(this, this._onResize); + this.get('resizeDetector').setup(this.get('autoExpand'), this._resizeCallback); + this._autoExpand(); + }, + + _onResize() { + this._autoExpand(); + }, + + _teardownAutoExpand() { + this.get('resizeDetector').teardown(this.get('autoExpand'), this._resizeCallback); + } }); diff --git a/ghost/admin/app/components/gh-trim-focus-input.js b/ghost/admin/app/components/gh-trim-focus-input.js index 5569333f90..59070f8719 100644 --- a/ghost/admin/app/components/gh-trim-focus-input.js +++ b/ghost/admin/app/components/gh-trim-focus-input.js @@ -1,5 +1,3 @@ -/* global device */ -import computed from 'ember-computed'; import GhostInput from 'ghost-admin/components/gh-input'; /** @@ -12,25 +10,6 @@ const TrimFocusInputComponent = GhostInput.extend({ shouldFocus: true, - attributeBindings: ['autofocus'], - - autofocus: computed(function () { - if (this.get('shouldFocus')) { - return (device.ios()) ? false : 'autofocus'; - } - - return false; - }), - - init() { - this._super(...arguments); - }, - - didInsertElement() { - this._super(...arguments); - this._focus(); - }, - focusOut(event) { this._trimInput(event.target.value); }, @@ -41,14 +20,6 @@ const TrimFocusInputComponent = GhostInput.extend({ } this._processNewValue(value); - }, - - _focus() { - // Until mobile safari has better support - // for focusing, we just ignore it - if (this.get('shouldFocus') && !device.ios()) { - this.element.focus(); - } } }); diff --git a/ghost/admin/app/mixins/text-input.js b/ghost/admin/app/mixins/text-input.js index 144b90ba34..2aceca01dd 100644 --- a/ghost/admin/app/mixins/text-input.js +++ b/ghost/admin/app/mixins/text-input.js @@ -1,9 +1,27 @@ +/* global device */ import Mixin from 'ember-metal/mixin'; +import computed from 'ember-computed'; export default Mixin.create({ + attributeBindings: ['autofocus'], + selectOnClick: false, + shouldFocus: false, stopEnterKeyDownPropagation: false, + autofocus: computed(function () { + if (this.get('shouldFocus')) { + return (device.ios()) ? false : 'autofocus'; + } + + return false; + }), + + didInsertElement() { + this._super(...arguments); + this._focus(); + }, + click(event) { if (this.get('selectOnClick')) { event.currentTarget.select(); @@ -12,12 +30,36 @@ export default Mixin.create({ keyDown(event) { // stop event propagation when pressing "enter" - // most useful in the case when undesired (global) keyboard shortcuts are getting triggered while interacting - // with this particular input element. + // most useful in the case when undesired (global) keyboard shortcuts + // are getting triggered while interacting with this particular input element. if (this.get('stopEnterKeyDownPropagation') && event.keyCode === 13) { event.stopPropagation(); return true; } + + // prevent default TAB behaviour if we have a keyEvent for it + if (event.keyCode === 9 && this.get('keyEvents.9')) { + event.preventDefault(); + } + + this._super(...arguments); + }, + + keyPress(event) { + // prevent default ENTER behaviour if we have a keyEvent for it + if (event.keyCode === 13 && this.get('keyEvents.13')) { + event.preventDefault(); + } + + this._super(...arguments); + }, + + _focus() { + // Until mobile safari has better support + // for focusing, we just ignore it + if (this.get('shouldFocus') && !device.ios()) { + this.element.focus(); + } } }); diff --git a/ghost/admin/app/templates/editor/edit.hbs b/ghost/admin/app/templates/editor/edit.hbs index 3be68d342a..2e096c238d 100644 --- a/ghost/admin/app/templates/editor/edit.hbs +++ b/ghost/admin/app/templates/editor/edit.hbs @@ -50,12 +50,12 @@ as |markdown| }}