root.libs.composum.nodes.commons.components.js.multiform.js Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of composum-nodes-commons Show documentation
Show all versions of composum-nodes-commons Show documentation
general components and objects to use the Sling API
/**
*
*
*/
(function () {
'use strict';
CPM.namespace('core.components');
(function (components, widgets, core) {
//
// Multi 'Form'
//
components.const = _.extend(components.const || {}, {
multiform: {
css: {
base: 'multi-form-widget',
current: 'current',
selector: {
item: '.multi-form-item',
handle: '.item-select',
widget: '.widget',
richtext: '.richtext-widget',
actions: '.action-bar',
table: '_table'
}
},
data: {
name: 'name'
},
pattern: {
name: {
widget: /(.+\/)?:name$/,
replace: '(\/([^/-]+)(-[^/]+)?\/)?([^/]+)$'
}
}
}
});
/**
* a generic item implementation for a MultiFormWidget item
*/
components.MultiFormItem = Backbone.View.extend({
initialize: function (options) {
var c = components.const.multiform;
widgets.setUp(this.el);
this.$widgets = this.$(c.css.selector.widget);
var self = this;
this.$widgets.each(function () {
if (this.view) {
this.name = this.view.retrieveName();
if (this.name && this.name.match(c.pattern.name.widget)) {
self.nameWidget = this.view;
}
}
});
},
/**
* returns the current set of values of the item
*/
getValue: function () {
var value = {};
this.$widgets.each(function () {
if (this.view) {
if (_.isFunction(this.view.getValue)) {
var name = core.getWidgetName(this.view);
if (name && name !== 'undefined') {
value[name] = this.view.getValue.apply(this.view);
}
}
}
});
var values = _.values(value);
if (values.length === 1) {
value = values[0];
} else if (values.length == 0) {
value = undefined;
}
return value;
},
/**
* presets the values of the item
*/
setValue: function (value) {
this.$widgets.each(function () {
if (this.view) {
if (_.isFunction(this.view.setValue)) {
var name = core.getWidgetName(this.view);
this.view.setValue.apply(this.view, [_.isObject(value) ? value[name] : value]);
}
}
});
},
reset: function () {
if (this.$widgets.length > 0) {
this.$widgets.each(function () {
if (this.view && _.isFunction(this.view.reset)) {
this.view.reset.apply(this.view);
}
});
} else {
this.$('input').val(undefined);
}
},
prepare: function (path, index) {
var c = components.const.multiform;
var pattern = new RegExp('^' + path + c.pattern.name.replace);
var nameValue = this.getNameValue();
var self = this;
this.$widgets.each(function () {
var matcher = pattern.exec(this.name);
if (matcher) {
var name = undefined;
if (nameValue) {
if (this.view !== self.nameWidget) {
name = path + '/' + nameValue + '/' + matcher[4];
}
} else {
name = path + '/' + matcher[2] + '-' + index + '/' + matcher[4];
}
this.view.declareName(name);
}
});
},
getNameValue: function () {
if (this.nameWidget) {
return this.nameWidget.getValue();
}
return undefined;
}
});
/**
* the generic multi form widget manages a set of structured form items
*/
components.MultiFormWidget = widgets.Widget.extend({
initialize: function (options) {
var c = components.const.multiform;
widgets.Widget.prototype.initialize.apply(this, [options]);
this.itemList = [];
this.itemType = options.itemType || components.MultiFormItem;
this.name = this.$el.data(c.data.name) || 'name';
var $itemElements = this.$(c.css.selector.item);
for (var i = 0; i < $itemElements.length; i++) {
this.itemList[i] = this.newItem($itemElements[i]);
}
this.current(this.itemList[0]);
if (this.$(c.css.selector.actions).length === 0) {
this.$el.append(
'
');
}
this.buttons = {
$add: this.$(c.css.selector.actions + ' button.add'),
$remove: this.$(c.css.selector.actions + ' button.remove'),
$up: this.$(c.css.selector.actions + ' button.move-up'),
$down: this.$(c.css.selector.actions + ' button.move-down')
};
this.initRules();
this.buttons.$add.unbind('click').on('click', _.bind(this.add, this));
this.buttons.$remove.unbind('click').on('click', _.bind(this.remove, this));
this.buttons.$up.unbind('click').on('click', _.bind(this.moveUp, this));
this.buttons.$down.unbind('click').on('click', _.bind(this.moveDown, this));
this.setDisabled(this.isDisabled());
},
setDisabled: function (disabled) {
widgets.Widget.prototype.setDisabled.call(this, disabled);
for (var i = 0; i < this.itemList.length; i++) {
if (this.itemList[i].$input) {
this.itemList[i].$input.prop('disabled', disabled);
}
}
this.buttons.$add.prop('disabled', disabled);
this.buttons.$remove.prop('disabled', disabled);
this.buttons.$up.prop('disabled', disabled);
this.buttons.$down.prop('disabled', disabled);
},
declareName: function (name) {
this.$el.data(c.data.name, this.name = name);
this.prepare();
},
getValue: function () {
var valueSet = [];
for (var i = 0; i < this.itemList.length; i++) {
var value = this.itemList[i].getValue();
if (i < this.itemList.length - 1 || !core.isEmptyObject(value)) {
valueSet.push(value);
}
}
return valueSet;
},
setValue: function (valueSet, triggerChange) {
if (valueSet) {
this.reset(valueSet.length);
for (var i = 0; i < this.itemList.length; i++) {
this.itemList[i].setValue(valueSet[i]);
}
} else {
this.reset(0);
}
if (triggerChange) {
this.$el.trigger('change', [valueSet]);
}
},
/**
* prevent from triggering value 'changed' events on item selection change
*/
onWidgetChange: function (event, value) {
var c = components.const.multiform;
if (!$(event.target).is(c.css.selector.handle)) {
widgets.Widget.prototype.onWidgetChange.call(this, event, value);
}
},
prepare: function () {
for (var i = 0; i < this.itemList.length; i++) {
if (_.isFunction(this.itemList[i].prepare)) {
this.itemList[i].prepare(this.name, i);
}
}
},
validate: function (alertMethod) {
var names = [];
for (var i = 0; i < this.itemList.length; i++) {
if (_.isFunction(this.itemList[i].getNameValue)) {
var name = this.itemList[i].getNameValue();
if (name) {
if (_.contains(names, name)) {
this.alert(alertMethod, 'danger', 'name', 'names not unique', name);
return false;
}
}
}
}
return true;
},
reset: function (size) {
if (!size || size < 1) {
size = 1;
}
while (this.itemList.length > size) {
this.remove();
}
for (var i = 0; i < this.itemList.length; i++) {
this.itemList[i].reset();
}
while (this.itemList.length < size) {
this.add();
}
},
newItem: function (element) {
var c = components.const.multiform;
var item = core.getView(element, this.itemType, _.bind(function (item) {
var $handle = item.$(c.css.selector.handle);
if ($handle.length === 0) {
item.$el.prepend('');
$handle = item.$(c.css.selector.handle);
}
$handle.prop('checked', false);
$handle.unbind('click').on('click', _.bind(this.onSelect, this));
CPM.widgets.setUp(item.el);
}, this), this.itemType !== components.MultiFormItem);
return item;
},
onSelect: function (event, item) {
var c = components.const.multiform;
var itemElement = item || $(event.currentTarget).closest('.multi-form-item')[0];
for (var i = 0; i < this.itemList.length; i++) {
if (itemElement === this.itemList[i].el) {
var $handle = this.itemList[i].$(c.css.selector.handle);
$handle.unbind('click');
this.current(this.itemList[i]);
this.$(c.css.selector.handle).not($handle).prop('checked', false);
$handle.on('click', _.bind(this.onSelect, this));
break;
}
}
},
indexOf: function (item) {
return _.indexOf(this.itemList, item);
},
current: function (item) {
var c = components.const.multiform;
if (item && this.indexOf(item) >= 0) {
this.currentItem = item;
for (var i = 0; i < this.itemList.length; i++) {
this.itemList[i].$el.removeClass(c.css.current);
this.itemList[i].$(c.css.selector.handle).attr('value', i);
}
this.currentItem.$el.addClass(c.css.current);
this.currentItem.$(c.css.selector.handle).click();
}
return this.currentItem;
},
add: function () {
var currentState = this.currentItem;
var template = this.itemList[this.itemList.length - 1];
var $clone = (_.isFunction(template.clone) ? template.clone() : template.$el.clone());
template.$el.parent().append($clone);
$clone.each(function () {
widgets.apply(this, 'afterClone');
});
var newItem = this.newItem($clone);
newItem.reset();
this.itemList[this.itemList.length] = newItem;
this.current(currentState);
this.$el.trigger('change', [this.getValue()]);
},
remove: function () {
if (this.itemList.length > 1) {
var currentIndex = this.indexOf(this.currentItem);
if (currentIndex === this.itemList.length - 1) {
currentIndex--;
}
this.currentItem.$el.remove();
this.itemList = _.without(this.itemList, this.currentItem);
this.current(this.itemList[currentIndex]);
} else {
this.itemList[0].reset();
}
this.$el.trigger('change', [this.getValue()]);
},
moveUp: function () {
var index = this.indexOf(this.currentItem);
if (index > 0) {
var head = index > 1 ? _.first(this.itemList, index - 1) : [];
var tail = index < this.itemList.length - 1 ? _.rest(this.itemList, index + 1) : [];
this.itemList = _.union(head, [this.currentItem], [this.itemList[index - 1]], tail);
this.currentItem.$el.insertBefore(this.currentItem.$el.prev());
this.$el.trigger('change', [this.getValue()]);
}
},
moveDown: function () {
var index = this.indexOf(this.currentItem);
if (index < this.itemList.length - 1) {
var head = index > 0 ? _.first(this.itemList, index) : [];
var tail = index < this.itemList.length - 2 ? _.rest(this.itemList, index + 2) : [];
this.itemList = _.union(head, [this.itemList[index + 1]], [this.currentItem], tail);
this.currentItem.$el.insertAfter(this.currentItem.$el.next());
this.$el.trigger('change', [this.getValue()]);
}
},
getWidgetValue: function (element) {
var widget = core.widgetOf(element, this);
if (widget && _.isFunction(widget.getValue)) {
return widget.getValue();
} else {
return _.isFuntion(element.val) ? element.val() : undefined;
}
},
setWidgetValue: function (element, value) {
var widget = core.widgetOf(element, this);
if (widget && _.isFunction(widget.setValue)) {
widget.setValue(value);
} else {
if (_.isFunction(element.val)) {
element.val(value);
}
}
}
});
widgets.register(widgets.const.css.selector.prefix +
components.const.multiform.css.base, components.MultiFormWidget);
})(CPM.core.components, CPM.widgets, CPM.core);
})();
© 2015 - 2025 Weber Informatics LLC | Privacy Policy