comindware.ui
Version:
Comindware Core UI provides the basic components like editors, lists, dropdowns, popups that we so desperately need while creating Marionette-based single-page applications.
238 lines (209 loc) • 6.34 kB
JavaScript
/**
* Developer: Stepan Burguchev
* Date: 1/26/2015
* Copyright: 2009-2016 Comindware®
* All Rights Reserved
* Published under the MIT license
*/
import template from './templates/field.hbs';
import { Handlebars } from 'lib';
import dropdown from 'dropdown';
import ErrorButtonView from './views/ErrorButtonView';
import InfoButtonView from './views/InfoButtonView';
import TooltipPanelView from './views/TooltipPanelView';
import formRepository from '../formRepository';
const classes = {
REQUIRED: 'required',
READONLY: 'readonly',
DISABLED: 'disabled',
ERROR: 'error'
};
export default Marionette.LayoutView.extend({
initialize(options) {
options = options || {};
this.form = options.form;
this.key = options.key;
this.__createSchema(options.schema);
this.__createEditor();
this.__viewModel = new Backbone.Model({
helpText: this.schema.helpText,
errorText: null
});
},
templateHelpers() {
return {
title: this.schema.title
};
},
template: Handlebars.compile(template),
regions: {
editorRegion: '.js-editor-region',
errorTextRegion: '.js-error-text-region',
helpTextRegion: '.js-help-text-region'
},
onShow() {
this.editorRegion.show(this.editor);
const errorPopout = dropdown.factory.createPopout({
buttonView: ErrorButtonView,
panelView: TooltipPanelView,
panelViewOptions: {
model: this.__viewModel,
textAttribute: 'errorText'
},
popoutFlow: 'right',
customAnchor: true
});
this.errorTextRegion.show(errorPopout);
if (this.schema.helpText) {
const infoPopout = dropdown.factory.createPopout({
buttonView: InfoButtonView,
panelView: TooltipPanelView,
panelViewOptions: {
model: this.__viewModel,
textAttribute: 'helpText'
},
popoutFlow: 'right',
customAnchor: true
});
this.helpTextRegion.show(infoPopout);
}
this.__rendered = true;
this.setRequired(this.schema.required);
this.__updateEditorState(this.schema.readonly, this.schema.enabled);
},
/**
* Check the validity of the field
*
* @return {String}
*/
validate() {
const error = this.editor.validate();
if (error) {
this.setError(error.message);
} else {
this.clearError();
}
return error;
},
setError(msg) {
if (!this.__checkUiReady()) {
return;
}
this.$el.addClass(classes.ERROR);
this.__viewModel.set('errorText', msg);
},
clearError() {
if (!this.__checkUiReady()) {
return;
}
this.$el.removeClass(classes.ERROR);
this.__viewModel.set('errorText', null);
},
/**
* Update the model with the new value from the editor
*
* @return {Mixed}
*/
commit() {
return this.editor.commit();
},
/**
* Get the value from the editor
*
* @return {Mixed}
*/
getValue() {
return this.editor.getValue();
},
/**
* Set/change the value of the editor
*
* @param {Mixed} value
*/
setValue(value) {
this.editor.setValue(value);
},
/**
* Give the editor focus
*/
focus() {
this.editor.focus();
},
/**
* Remove focus from the editor
*/
blur() {
this.editor.blur();
},
setRequired(required) {
if (!this.__checkUiReady()) {
return;
}
this.$el.toggleClass(classes.REQUIRED, Boolean(required));
},
__updateEditorState(readonly, enabled) {
if (!this.__checkUiReady()) {
return;
}
this.$el.toggleClass(classes.READONLY, Boolean(readonly));
this.$el.toggleClass(classes.DISABLED, Boolean(readonly || !enabled));
},
__createSchema(schema) {
// Resolving editor type declared as string
const type = _.isString(schema.type) ? formRepository.editors[schema.type] : schema.type || 'Text';
this.schema = Object.assign({
title: this.__createDefaultTitle(),
required: false
}, schema);
this.schema.type = type;
},
/*
* Create the default field title (label text) from the key name.
* (Converts 'camelCase' to 'Camel Case')
*/
__createDefaultTitle() {
let str = this.key;
if (!str) {
return '';
}
//Add spaces
str = str.replace(/([A-Z])/g, ' $1');
//Uppercase first character
str = str.replace(/^./, x => x.toUpperCase());
return str;
},
__createEditor() {
const ConstructorFn = this.schema.type;
this.editor = new ConstructorFn({
schema: this.schema,
form: this.form,
field: this,
key: this.key,
model: this.model,
id: this.__createEditorId(),
value: this.options.value
});
this.editor.on('readonly', readonly => {
this.__updateEditorState(readonly, this.editor.getEnabled());
});
this.editor.on('enabled', enabled => {
this.__updateEditorState(this.editor.getReadonly(), enabled);
});
},
__createEditorId() {
if (!this.key) {
return null;
}
let id = this.key;
//Replace periods with underscores
id = id.replace(/\./g, '_');
//Otherwise, if there is a model use it's CID to avoid conflicts when multiple forms are on the page
if (this.model) {
return `${this.model.cid}_${id}`;
}
return id;
},
__checkUiReady() {
return this.__rendered && !this.isDestroyed;
}
});