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.
205 lines (179 loc) • 7.45 kB
JavaScript
/**
* Developer: Stepan Burguchev
* Date: 1/28/2015
* Copyright: 2009-2016 Comindware®
* All Rights Reserved
* Published under the MIT license
*/
'use strict';
import { Handlebars, keypress } from 'lib';
import { helpers, comparators } from 'utils';
import dropdown from 'dropdown';
import template from './templates/memberSelectEditor.hbs';
import BaseLayoutEditorView from './base/BaseLayoutEditorView';
import UserService from 'services/UserService';
import DefaultButtonView from './impl/memberSelect/views/DefaultButtonView';
import PanelView from './impl/memberSelect/views/PanelView';
import MemberModel from './impl/common/members/models/MemberModel';
import MembersCollection from './impl/common/members/collections/MembersCollection';
import formRepository from '../formRepository';
const defaultOptions = {
dropdownOptions: {
buttonView: DefaultButtonView,
popoutFlow: 'right',
customAnchor: true
}
};
const ButtonModel = Backbone.AssociatedModel.extend({
relations: [
{
type: Backbone.One,
key: 'member',
relatedModel: MemberModel
}
]
});
/**
* @name MemberSelectEditorView
* @memberof module:core.form.editors
* @class Редактор для выбора пользователя из списка доступных. Поддерживаемый тип данных: <code>String</code>
* (идентификатор пользователя). Например, <code>'user.1'</code>. Список доступных пользователей
* берется из <code>core.services.CacheService</code>.
* @extends module:core.form.editors.base.BaseEditorView
* @param {Object} options Options object. All the properties of {@link module:core.form.editors.base.BaseEditorView BaseEditorView} class are also supported.
* @param {Number} [options.dropdownOptions=Object] Опции используемого PopoutView.
* Полезно для задания направления открытия и кастомизации кнопки. Значения по умолчанию:
* <code>{ buttonView: DefaultButtonView, popoutFlow: 'right', customAnchor: true }</code>
* */
formRepository.editors.MemberSelect = BaseLayoutEditorView.extend(/** @lends module:core.form.editors.MemberSelectEditorView.prototype */{
initialize(options) {
if (options.schema) {
_.extend(this.options, defaultOptions, _.pick(options.schema, _.keys(defaultOptions)));
} else {
_.extend(this.options, defaultOptions, _.pick(options || {}, _.keys(defaultOptions)));
}
_.defaults(this.options.dropdownOptions, defaultOptions.dropdownOptions);
this.reqres = new Backbone.Wreqr.RequestResponse();
this.reqres.setHandler('value:clear', this.onValueClear, this);
this.reqres.setHandler('value:set', this.onValueSet, this);
this.reqres.setHandler('value:navigate', this.onValueNavigate, this);
this.reqres.setHandler('filter:text', this.onFilterText, this);
this.reqres.setHandler('panel:open', this.onPanelOpen, this);
this.viewModel = new Backbone.Model({
button: new ButtonModel({
enabled: this.getEnabled() && !this.getReadonly()
}),
panel: new Backbone.Model({
})
});
this.__initCollection();
},
regions: {
dropdownRegion: '.js-dropdown-region'
},
className: 'users-list editor',
template: Handlebars.compile(template),
setValue(value) {
this.__value(_.isArray(value) ? (value.length ? value[0] : null) : value, false);
},
onRender() {
// dropdown
const dropdownOptions = _.extend({
buttonViewOptions: {},
panelView: PanelView,
panelViewOptions: {
model: this.viewModel.get('panel'),
reqres: this.reqres
},
autoOpen: false
}, this.options.dropdownOptions);
_.extend(dropdownOptions.buttonViewOptions, {
model: this.viewModel.get('button'),
reqres: this.reqres
});
this.dropdownView = dropdown.factory.createPopout(dropdownOptions);
this.listenTo(this.dropdownView, 'panel:cancel', this.__onCancel);
this.dropdownRegion.show(this.dropdownView);
// hotkeys
if (this.keyListener) {
this.keyListener.reset();
}
this.keyListener = new keypress.Listener(this.el);
_.each('down,enter,num_enter'.split(','), function(key) {
this.keyListener.simple_combo(key, () => {
if (this.getEnabled() && !this.getReadonly()) {
this.dropdownView.open();
}
});
}, this);
},
__value(value, triggerChange) {
if (this.value === value) {
return;
}
this.value = value;
this.viewModel.get('button').set('member', this.__findModel(value));
if (triggerChange) {
this.__triggerChange();
}
},
onValueClear() {
this.__value(null, true);
this.focus();
},
onValueSet(value) {
this.__value(value, true);
this.dropdownView.close();
this.$el.focus();
},
onValueNavigate() {
},
onFilterText(options) {
const deferred = $.Deferred();
const text = options.text.toLocaleLowerCase();
this.collection.unhighlight();
if (text === '') {
this.collection.filter(null);
} else {
this.collection.filter(model => {
const fullName = (model.get('name') || '').toLocaleLowerCase();
return fullName.indexOf(text) !== -1;
});
this.collection.highlight(text);
}
deferred.resolve();
return deferred.promise();
},
onPanelOpen() {
if (this.getEnabled() && !this.getReadonly()) {
this.dropdownView.open();
}
},
__initCollection() {
const users = UserService.listUsers();
this.collection = new MembersCollection(new Backbone.Collection(users, {
model: MemberModel
}), {
comparator: helpers.comparatorFor(comparators.stringComparator2Asc, 'name')
});
this.viewModel.get('button').set('member', this.__findModel(this.getValue()));
this.viewModel.get('panel').set('collection', this.collection);
},
__findModel(value) {
return this.collection.findWhere({ id: value });
},
__setEnabled(enabled) {
BaseLayoutEditorView.prototype.__setEnabled.call(this, enabled);
this.viewModel.get('button').set('enabled', this.getEnabled() && !this.getReadonly());
},
__setReadonly(readonly) {
BaseLayoutEditorView.prototype.__setReadonly.call(this, readonly);
this.viewModel.get('button').set('enabled', this.getEnabled() && !this.getReadonly());
this.$el.prop('tabindex', readonly ? -1 : 0);
},
__onCancel() {
this.dropdownView.close();
this.$el.focus();
}
});
export default formRepository.editors.MemberSelect;