1
0
Fork 0
mirror of https://github.com/TryGhost/Ghost-Admin.git synced 2023-12-14 02:33:04 +01:00
Ghost-Admin/app/components/gh-editor.js
Kevin Ansfield 4b48328e6d SimpleMDE editor (#682)
no issue

* move "save on first change" behaviour into editor controller
* allow TAB events to be specified in keyEvents hash of gh-input
* replace mobiledoc-kit/gh-koenig with a SimpleMDE based editor
    - remove `gh-koenig` in-repo-addon from `package.json` so that test files etc aren't loaded
    - remove `mobiledoc-kit` dependencies
    - extends `gh-editor` to handle file drag/drop
    - adds `gh-uploader` and `gh-progress-bar` components to handle file uploads in a more composable manner
    - adds `gh-simplemde` component that wraps SimpleMDE
2017-05-08 11:35:42 +01:00

158 lines
4 KiB
JavaScript

import Component from 'ember-component';
import run from 'ember-runloop';
import {
IMAGE_MIME_TYPES,
IMAGE_EXTENSIONS
} from 'ghost-admin/components/gh-image-uploader';
const {debounce} = run;
export default Component.extend({
classNameBindings: ['isDraggedOver:-drag-over'],
// Public attributes
navIsClosed: false,
// Internal attributes
droppedFiles: null,
headerClass: '',
imageExtensions: IMAGE_EXTENSIONS,
imageMimeTypes: IMAGE_MIME_TYPES,
isDraggedOver: false,
uploadedImageUrls: null,
// Closure actions
toggleAutoNav() {},
// Private
_dragCounter: 0,
_fullScreenEnabled: false,
_navIsClosed: false,
_onResizeHandler: null,
_viewActionsWidth: 190,
init() {
this._super(...arguments);
this._onResizeHandler = (evt) => {
debounce(this, this._setHeaderClass, evt, 100);
};
},
didInsertElement() {
this._super(...arguments);
window.addEventListener('resize', this._onResizeHandler);
this._setHeaderClass();
},
didReceiveAttrs() {
let navIsClosed = this.get('navIsClosed');
if (navIsClosed !== this._navIsClosed) {
this._fullScreenEnabled = navIsClosed;
run.scheduleOnce('afterRender', this, this._setHeaderClass);
}
this._navIsClosed = navIsClosed;
},
_setHeaderClass() {
let $editorTitle = this.$('.gh-editor-title');
if ($editorTitle.length > 0) {
let boundingRect = $editorTitle[0].getBoundingClientRect();
let maxRight = window.innerWidth - this._viewActionsWidth;
if (boundingRect.right >= maxRight) {
this.set('headerClass', 'gh-editor-header-small');
return;
}
}
this.set('headerClass', '');
},
// dragOver is needed so that drop works
dragOver(event) {
if (!event.dataTransfer) {
return;
}
// this is needed to work around inconsistencies with dropping files
// from Chrome's downloads bar
let eA = event.dataTransfer.effectAllowed;
event.dataTransfer.dropEffect = (eA === 'move' || eA === 'linkMove') ? 'move' : 'copy';
event.preventDefault();
event.stopPropagation();
},
// dragEnter is needed so that the drag class is correctly removed
dragEnter(event) {
if (!event.dataTransfer) {
return;
}
event.preventDefault();
event.stopPropagation();
// the counter technique prevents flickering of the drag class when
// dragging across child elements
this._dragCounter++;
this.set('isDraggedOver', true);
},
dragLeave(event) {
event.preventDefault();
event.stopPropagation();
this._dragCounter--;
if (this._dragCounter === 0) {
this.set('isDraggedOver', false);
}
},
drop(event) {
event.preventDefault();
event.stopPropagation();
this._dragCounter = 0;
this.set('isDraggedOver', false);
if (event.dataTransfer.files) {
this.set('droppedFiles', event.dataTransfer.files);
}
},
willDestroyElement() {
this._super(...arguments);
window.removeEventListener('resize', this._onResizeHandler);
// reset fullscreen mode if it was turned on
if (this._fullScreenEnabled) {
this.toggleAutoNav();
}
},
actions: {
toggleFullScreen() {
if (!this._fullScreenWasToggled) {
this._fullScreenEnabled = !this.get('isNavOpen');
this._fullScreenWasToggled = true;
} else {
this._fullScreenEnabled = !this._fullScreenEnabled;
}
this.toggleAutoNav();
},
uploadComplete(uploads) {
this.set('uploadedImageUrls', uploads.mapBy('url'));
this.set('droppedFiles', null);
},
uploadCancelled() {
this.set('droppedFiles', null);
}
}
});