src/contrib/modaledit/ModalEdit.js
import _ from 'lodash';
import TextAreaComponent from '../../components/textarea/TextArea';
import ModalEditForm from './ModalEdit.form';
export default class ModalEditComponent extends TextAreaComponent {
static schema(...extend) {
return TextAreaComponent.schema({
type: 'modaledit',
label: 'Modal Edit',
key: 'modalEdit',
modalLayout: 'fixed',
}, ...extend);
}
static get builderInfo() {
return {
title: 'Modal Edit',
group: 'data',
icon: 'font',
weight: 40,
schema: ModalEditComponent.schema()
};
}
/** @override **/
renderElement(content = '') {
return this.renderTemplate('modaledit', { content });
}
/** @override **/
attach(element) {
this.loadRefs(element, {
container: 'single',
edit: 'single'
});
return super.attach(element);
}
/** @override **/
attachElement(element) {
// Allow work with div as if it would be plain input
Object.defineProperty(element, 'value', {
get: function() {
return this.innerHTML;
},
set: function(value) {
this.innerHTML = value;
}
});
const show = this.showModal.bind(this);
this.addEventListener(this.refs.container, 'dblclick', show);
this.addEventListener(this.refs.edit, 'click', show);
}
/** @override **/
createModal(element) {
const self = this;
const dialog = this.ce('div');
this.setContent(dialog, this.renderTemplate('modaldialog'));
dialog.refs = {};
this.loadRefs.call(dialog, dialog, {
overlay: 'single',
content: 'single',
inner: 'single',
close: 'single'
});
const rect = this.getElementRect(this.refs.container);
const layout = this.getModalLayout(rect);
const styles = this.getModalStyle(layout);
Object.assign(dialog.refs.content.style, styles);
dialog.refs.inner.appendChild(element);
this.addEventListener(dialog.refs.overlay, 'click', (event) => {
event.preventDefault();
dialog.close();
});
this.addEventListener(dialog.refs.close, 'click', (event) => {
event.preventDefault();
dialog.close();
});
this.addEventListener(dialog, 'close', () => {
this.removeChildFrom(dialog, document.body);
});
dialog.close = function() {
dialog.dispatchEvent(new CustomEvent('close'));
self.removeChildFrom(dialog, document.body);
};
document.body.appendChild(dialog);
return dialog;
}
/** @override **/
updateOnChange(flags, changed = false) {
if (super.updateOnChange(flags, changed)) {
this.updateContentView(this.dataValue);
}
}
showModal() {
const elt = this.ce('div');
this.setContent(elt, super.renderElement(this.dataValue));
const editor = elt.children[0];
if (this.isPlain) {
editor.style.resize = 'vertical';
}
super.attachElement(editor);
this.createModal(editor);
}
updateContentView(content = '') {
const view = _.get(this, 'refs.input[0]', null);
return this.setContent(view, content);
}
getElementRect(elt) {
return elt.getBoundingClientRect();
}
getModalStyle(args, overrides = {}) {
const defaultStyles = {
position: 'absolute',
height: 'auto',
};
const layout = _.mapValues(
_.pick(args, ['top', 'left', 'width']),
p => `${p}px`
);
return {
...defaultStyles,
...overrides,
...layout
};
}
getModalLayout(rect) {
const { width, height: minHeight } = this.getModalSize(rect.width, rect.height);
return {
left: rect.left,
minHeight,
top: rect.top,
width,
};
}
getModalSize(currentWidth, currentHeight) {
const [dw, dh] = this.defaultModalSize;
const type = _.get(this.component, 'modalLayout', 'fixed');
const { widthProp, heightProp } = this.layoutProps[type];
const width = _.get(this.component, widthProp, dw);
const height = _.get(this.component, heightProp, dh);
if (type === 'fluid') {
return {
width: Math.max(currentWidth, width),
height: Math.max(currentHeight, height)
};
}
return { width, height };
}
get defaultModalSize() {
return [475, 300];
}
get layoutProps() {
return {
fixed: {
widthProp: 'width',
heightProp: 'height'
},
fluid: {
widthProp: 'minWidth',
heightProp: 'minHeight'
}
};
}
}
ModalEditComponent.editForm = ModalEditForm;