Initial commit
This commit is contained in:
44
lib/assets/javascripts/builder/components/table/editors/editor-view-model.js
Executable file
44
lib/assets/javascripts/builder/components/table/editors/editor-view-model.js
Executable file
@@ -0,0 +1,44 @@
|
||||
var Backbone = require('backbone');
|
||||
var CoreView = require('backbone/core-view');
|
||||
|
||||
/**
|
||||
* View model of an editor
|
||||
*/
|
||||
module.exports = Backbone.Model.extend({
|
||||
|
||||
defaults: {
|
||||
show: true,
|
||||
createContentView: function () {
|
||||
return new CoreView();
|
||||
}
|
||||
},
|
||||
|
||||
createContentView: function () {
|
||||
return this.get('createContentView')(this);
|
||||
},
|
||||
|
||||
show: function () {
|
||||
this.set('show', true);
|
||||
},
|
||||
|
||||
hide: function () {
|
||||
this.set('show', false);
|
||||
},
|
||||
|
||||
isHidden: function () {
|
||||
return !this.get('show');
|
||||
},
|
||||
|
||||
confirm: function () {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
this.trigger.apply(this, ['confirm'].concat(args));
|
||||
},
|
||||
|
||||
/**
|
||||
* @override {Backbone.Model.prototype.destroy}
|
||||
*/
|
||||
destroy: function () {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
this.trigger.apply(this, ['destroy'].concat(args));
|
||||
}
|
||||
});
|
||||
48
lib/assets/javascripts/builder/components/table/editors/editor-view.js
Executable file
48
lib/assets/javascripts/builder/components/table/editors/editor-view.js
Executable file
@@ -0,0 +1,48 @@
|
||||
var CoreView = require('backbone/core-view');
|
||||
|
||||
module.exports = CoreView.extend({
|
||||
className: 'CDB-Box-modal Table-editor',
|
||||
|
||||
initialize: function () {
|
||||
this.listenTo(this.model, 'change:show', this._onShowChange);
|
||||
this.listenTo(this.model, 'destroy', this._onDestroy);
|
||||
},
|
||||
|
||||
render: function () {
|
||||
this.clearSubViews();
|
||||
|
||||
var view = this.model.createContentView();
|
||||
this.addView(view);
|
||||
view.render();
|
||||
this.$el.append(view.el);
|
||||
this.$el.css(this.options.position);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
show: function () {
|
||||
this.model.show();
|
||||
},
|
||||
|
||||
hide: function () {
|
||||
this.model.hide();
|
||||
},
|
||||
|
||||
destroy: function () {
|
||||
this.model.destroy();
|
||||
},
|
||||
|
||||
_onShowChange: function (m, show) {
|
||||
this.$el[show ? 'show' : 'hide']();
|
||||
},
|
||||
|
||||
_onClose: function () {
|
||||
this.destroy();
|
||||
},
|
||||
|
||||
_onDestroy: function () {
|
||||
this.hide();
|
||||
this.clean();
|
||||
}
|
||||
|
||||
});
|
||||
117
lib/assets/javascripts/builder/components/table/editors/editors-service-model.js
Executable file
117
lib/assets/javascripts/builder/components/table/editors/editors-service-model.js
Executable file
@@ -0,0 +1,117 @@
|
||||
var _ = require('underscore');
|
||||
var $ = require('jquery');
|
||||
var Backbone = require('backbone');
|
||||
var EditorView = require('./editor-view');
|
||||
var EditorViewModel = require('./editor-view-model');
|
||||
var ESC_KEY_CODE = 27;
|
||||
var DESTROYED_EDITOR_EVENT = 'destroyedEditor';
|
||||
var CONFIRMED_EDITOR_EVENT = 'confirmedEditor';
|
||||
|
||||
/**
|
||||
* Top-level API to handle editor views.
|
||||
*
|
||||
* Example:
|
||||
* // In some entry-point:
|
||||
* table.editors = new EditorsServiceModel();
|
||||
*
|
||||
* // Later, in any view, calling create will create a new editor viewModel
|
||||
* var editorView = table.editors.create(fn);
|
||||
*
|
||||
* Same concept @viddo introduced with Modals.
|
||||
*/
|
||||
module.exports = Backbone.Model.extend({
|
||||
|
||||
/**
|
||||
* Creates a new editor view
|
||||
*
|
||||
* @param {Function} createContentView
|
||||
* @return {View} the new editor view
|
||||
*/
|
||||
create: function (createContentView, position) {
|
||||
if (!_.isFunction(createContentView)) throw new Error('createContentView is required');
|
||||
position = position || {
|
||||
left: '50%',
|
||||
top: '50%'
|
||||
};
|
||||
|
||||
if (!this._editorView) {
|
||||
this._editorView = this._newEditorView(position);
|
||||
document.body.appendChild(this._editorView.el);
|
||||
}
|
||||
|
||||
this._editorView.model.set('createContentView', createContentView);
|
||||
this._editorView.render();
|
||||
|
||||
return this._editorView;
|
||||
},
|
||||
|
||||
/**
|
||||
* Convenience method to add a listener when current editor is destroyed
|
||||
*
|
||||
* This is the same as doing
|
||||
* editors.create(function (model) {
|
||||
* model.once('destroy', callback, context);
|
||||
* return new MyView({ … });
|
||||
* });
|
||||
*
|
||||
* @param {Function} callback
|
||||
* @param {Object} [context = undefined]
|
||||
*/
|
||||
|
||||
confirm: function () {
|
||||
if (this._editorView) {
|
||||
this._editorView.model.confirm();
|
||||
}
|
||||
},
|
||||
|
||||
destroy: function () {
|
||||
if (this._editorView) {
|
||||
this._editorView.model.destroy();
|
||||
}
|
||||
},
|
||||
|
||||
_newEditorView: function (position) {
|
||||
var viewModel = new EditorViewModel();
|
||||
this._destroyOnEsc(viewModel);
|
||||
this.listenToOnce(viewModel, 'destroy', function () {
|
||||
this._editorView = null;
|
||||
this.trigger.apply(this, [DESTROYED_EDITOR_EVENT].concat(Array.prototype.slice.call(arguments)));
|
||||
this.stopListening(viewModel);
|
||||
});
|
||||
this.listenToOnce(viewModel, 'confirm', function () {
|
||||
this.trigger.apply(this, [CONFIRMED_EDITOR_EVENT].concat(Array.prototype.slice.call(arguments)));
|
||||
this.destroy();
|
||||
});
|
||||
var view = new EditorView({
|
||||
model: viewModel,
|
||||
position: position
|
||||
});
|
||||
this._destroyOnClickOutside(view);
|
||||
return view;
|
||||
},
|
||||
|
||||
_destroyOnClickOutside: function (view) {
|
||||
var destroyOnClickOutside = function (ev) {
|
||||
if ($(ev.target).closest(view.el).length === 0) {
|
||||
view.model.confirm();
|
||||
}
|
||||
};
|
||||
document.addEventListener('click', destroyOnClickOutside);
|
||||
this.listenToOnce(view.model, 'destroy', function () {
|
||||
document.removeEventListener('click', destroyOnClickOutside);
|
||||
});
|
||||
},
|
||||
|
||||
_destroyOnEsc: function (viewModel) {
|
||||
var destroyOnEsc = function (ev) {
|
||||
if (ev.which === ESC_KEY_CODE) {
|
||||
viewModel.destroy();
|
||||
}
|
||||
};
|
||||
document.addEventListener('keydown', destroyOnEsc);
|
||||
this.listenToOnce(viewModel, 'destroy', function () {
|
||||
document.removeEventListener('keydown', destroyOnEsc);
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
@@ -0,0 +1,73 @@
|
||||
var CoreView = require('backbone/core-view');
|
||||
var $ = require('jquery');
|
||||
var ENTER_KEY_CODE = 13;
|
||||
|
||||
module.exports = CoreView.extend({
|
||||
|
||||
tagName: 'input',
|
||||
className: 'CDB-InputText CDB-Text',
|
||||
|
||||
events: {
|
||||
'keyup': '_onValueChange',
|
||||
'change': '_onValueChange'
|
||||
},
|
||||
|
||||
initialize: function (opts) {
|
||||
if (!opts.editorModel) throw new Error('editorModel is required');
|
||||
this._editorModel = opts.editorModel;
|
||||
this._onKeyPressed = this._onKeyPressed.bind(this);
|
||||
this._onValueChange = this._onValueChange.bind(this);
|
||||
},
|
||||
|
||||
render: function () {
|
||||
this.$el.val(
|
||||
this.model.get('value')
|
||||
);
|
||||
this._setFocus();
|
||||
this._initDocumentBind();
|
||||
return this;
|
||||
},
|
||||
|
||||
_setFocus: function () {
|
||||
setTimeout(function () {
|
||||
this.$el.focus();
|
||||
}.bind(this), 100);
|
||||
},
|
||||
|
||||
_initDocumentBind: function () {
|
||||
$(document).bind('keydown', this._onKeyPressed);
|
||||
},
|
||||
|
||||
_destroyDocumentBind: function () {
|
||||
$(document).unbind('keydown', this._onKeyPressed);
|
||||
},
|
||||
|
||||
_onKeyPressed: function (ev) {
|
||||
if (ev.which === ENTER_KEY_CODE) {
|
||||
if (this.model.isValid()) {
|
||||
this._editorModel.confirm();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_onValueChange: function () {
|
||||
this._setValue();
|
||||
this._checkValidity();
|
||||
},
|
||||
|
||||
_setValue: function () {
|
||||
this.model.set('value', this.$el.val());
|
||||
},
|
||||
|
||||
_checkValidity: function () {
|
||||
this.$el.toggleClass('has-error', !this.model.isValid());
|
||||
},
|
||||
|
||||
clean: function () {
|
||||
this._destroyDocumentBind();
|
||||
CoreView.prototype.clean.apply(this);
|
||||
}
|
||||
|
||||
});
|
||||
@@ -0,0 +1,40 @@
|
||||
var EditorBaseView = require('./editor-base-view');
|
||||
var $ = require('jquery');
|
||||
var template = require('./editor-boolean.tpl');
|
||||
|
||||
module.exports = EditorBaseView.extend({
|
||||
|
||||
tagName: 'div',
|
||||
className: 'u-flex',
|
||||
|
||||
events: {
|
||||
'change input:radio': '_onRadioChanged'
|
||||
},
|
||||
|
||||
render: function () {
|
||||
var value = this.model.get('value');
|
||||
this.$el.html(
|
||||
template({
|
||||
value: value !== null ? value.toString() : 'null'
|
||||
})
|
||||
);
|
||||
return this;
|
||||
},
|
||||
|
||||
_onRadioChanged: function (ev) {
|
||||
var value = $(ev.target).val();
|
||||
switch (value) {
|
||||
case 'true':
|
||||
value = true;
|
||||
break;
|
||||
case 'false':
|
||||
value = false;
|
||||
break;
|
||||
default:
|
||||
value = null;
|
||||
}
|
||||
this.model.set('value', value);
|
||||
this._editorModel.confirm();
|
||||
}
|
||||
|
||||
});
|
||||
@@ -0,0 +1,15 @@
|
||||
<div class="u-iBlock CDB-Text CDB-Size-medium u-rSpace--xl">
|
||||
<input class="CDB-Radio" type="radio" name="value" value="true" <% if (value === 'true') { %>checked<% } %>>
|
||||
<span class="u-iBlock CDB-Radio-face"></span>
|
||||
<label class="u-iBlock u-lSpace">True</label>
|
||||
</div>
|
||||
<div class="u-iBlock CDB-Text CDB-Size-medium u-rSpace--xl">
|
||||
<input class="CDB-Radio" type="radio" name="value" value="false" <% if (value === 'false') { %>checked<% } %>>
|
||||
<span class="u-iBlock CDB-Radio-face"></span>
|
||||
<label class="u-iBlock u-lSpace">False</label>
|
||||
</div>
|
||||
<div class="u-iBlock CDB-Text CDB-Size-medium u-rSpace--xl">
|
||||
<input class="CDB-Radio" type="radio" name="value" value="null" <% if (value === 'null') { %>checked<% } %>>
|
||||
<span class="u-iBlock CDB-Radio-face"></span>
|
||||
<label class="u-iBlock u-lSpace">Null</label>
|
||||
</div>
|
||||
@@ -0,0 +1,105 @@
|
||||
var Backbone = require('backbone');
|
||||
var moment = require('moment');
|
||||
var Utils = require('builder/helpers/utils');
|
||||
var MONTHS = [
|
||||
{
|
||||
val: 0,
|
||||
label: _t('months.january')
|
||||
}, {
|
||||
val: 1,
|
||||
label: _t('months.february')
|
||||
}, {
|
||||
val: 2,
|
||||
label: _t('months.march')
|
||||
}, {
|
||||
val: 3,
|
||||
label: _t('months.april')
|
||||
}, {
|
||||
val: 4,
|
||||
label: _t('months.may')
|
||||
}, {
|
||||
val: 5,
|
||||
label: _t('months.june')
|
||||
}, {
|
||||
val: 6,
|
||||
label: _t('months.july')
|
||||
}, {
|
||||
val: 7,
|
||||
label: _t('months.august')
|
||||
}, {
|
||||
val: 8,
|
||||
label: _t('months.september')
|
||||
}, {
|
||||
val: 9,
|
||||
label: _t('months.october')
|
||||
}, {
|
||||
val: 10,
|
||||
label: _t('months.november')
|
||||
}, {
|
||||
val: 11,
|
||||
label: _t('months.december')
|
||||
}
|
||||
];
|
||||
|
||||
module.exports = Backbone.Model.extend({
|
||||
|
||||
parse: function (attrs) {
|
||||
var date;
|
||||
|
||||
if (!attrs.date) {
|
||||
date = moment().utc();
|
||||
} else {
|
||||
date = moment(attrs.date).utc();
|
||||
}
|
||||
|
||||
return {
|
||||
day: date.date(),
|
||||
month: date.month(),
|
||||
year: date.year(),
|
||||
time: date.format('HH:mm:ss'),
|
||||
utcOffset: date.utcOffset()
|
||||
};
|
||||
},
|
||||
|
||||
initialize: function () {
|
||||
this.schema = {
|
||||
day: {
|
||||
title: '',
|
||||
type: 'Text',
|
||||
validators: [
|
||||
'required',
|
||||
/^([12]?\d{0,1}|3[01]{0,2})$/,
|
||||
function (value, formValues) {
|
||||
var date = moment(Utils.formatDate(formValues));
|
||||
if (!date.isValid()) {
|
||||
return {
|
||||
type: 'date',
|
||||
message: _t('components.datepicker.invalid-date')
|
||||
};
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
month: {
|
||||
type: 'Select',
|
||||
title: '',
|
||||
options: MONTHS
|
||||
},
|
||||
year: {
|
||||
title: '',
|
||||
type: 'Text',
|
||||
validators: ['required', /^([0-9]{0,4})$/]
|
||||
},
|
||||
time: {
|
||||
title: '',
|
||||
type: 'Text',
|
||||
validators: ['required', /^([01]{1}[0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$/]
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
getFormattedDate: function () {
|
||||
return Utils.formatDate(this.toJSON());
|
||||
}
|
||||
|
||||
});
|
||||
@@ -0,0 +1,48 @@
|
||||
var Backbone = require('backbone');
|
||||
var EditorBaseView = require('./editor-base-view');
|
||||
var EditorDateFormModel = require('./editor-date-form-model');
|
||||
require('builder/components/form-components/index');
|
||||
|
||||
module.exports = EditorBaseView.extend({
|
||||
|
||||
tagName: 'div',
|
||||
className: 'Table-editorDate',
|
||||
|
||||
initialize: function (opts) {
|
||||
EditorBaseView.prototype.initialize.apply(this, arguments);
|
||||
|
||||
this._formModel = new EditorDateFormModel({
|
||||
date: this.model.get('value')
|
||||
}, {
|
||||
parse: true
|
||||
});
|
||||
|
||||
this._setValue();
|
||||
this._formModel.bind('change', this._setValue, this);
|
||||
this.add_related_model(this._formModel);
|
||||
},
|
||||
|
||||
render: function () {
|
||||
this._formView = new Backbone.Form({
|
||||
model: this._formModel
|
||||
});
|
||||
|
||||
this._formView.bind('change', function () {
|
||||
this.commit();
|
||||
});
|
||||
|
||||
this.$el.html(this._formView.render().el);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
_setValue: function () {
|
||||
this.model.set('value', this._formModel.getFormattedDate());
|
||||
},
|
||||
|
||||
clean: function () {
|
||||
this._formView.remove();
|
||||
EditorBaseView.prototype.clean.apply(this);
|
||||
}
|
||||
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
var Backbone = require('backbone');
|
||||
var _ = require('underscore');
|
||||
|
||||
module.exports = Backbone.Model.extend({
|
||||
|
||||
// Error labels will not be showed, not needed to be translated
|
||||
validate: function (attrs, opts) {
|
||||
if (attrs.type === 'number' && isNaN(attrs.value)) {
|
||||
return 'Number not valid';
|
||||
}
|
||||
|
||||
if (attrs.type === 'boolean' && (!_.isBoolean(attrs.value) && attrs.value !== null)) {
|
||||
return 'Boolean not valid';
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
var EditorBaseView = require('./editor-base-view');
|
||||
var ENTER_KEY_CODE = 13;
|
||||
|
||||
module.exports = EditorBaseView.extend({
|
||||
|
||||
tagName: 'textarea',
|
||||
className: 'Table-editorTextarea CDB-Textarea CDB-Text',
|
||||
|
||||
_onKeyPressed: function (ev) {
|
||||
if (!ev.shiftKey && ev.which === ENTER_KEY_CODE) {
|
||||
this._onValueChange();
|
||||
this._editorModel.confirm();
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
Reference in New Issue
Block a user