diff --git a/src/domain_abstract/model/TypeableCollection.js b/src/domain_abstract/model/TypeableCollection.js
index faf6affdc..40b43ee13 100644
--- a/src/domain_abstract/model/TypeableCollection.js
+++ b/src/domain_abstract/model/TypeableCollection.js
@@ -124,6 +124,11 @@ export default {
? view
: ViewInst.extend(view || {});
+ // New API
+ if (this.extendViewApi && !definition.model && !definition.view) {
+ view = view.extend(definition);
+ }
+
if (type) {
type.model = model;
type.view = view;
diff --git a/src/style_manager/index.js b/src/style_manager/index.js
index 3b7fe8675..257d964f1 100644
--- a/src/style_manager/index.js
+++ b/src/style_manager/index.js
@@ -204,7 +204,7 @@ export default () => {
/**
* Get property by its CSS name and sector id
* @param {string} sectorId Sector id
- * @param {string} name CSS property name, eg. 'min-height'
+ * @param {string} name CSS property name (or id), eg. 'min-height'
* @return {Property|null}
* @example
* var property = styleManager.getProperty('mySector','min-height');
@@ -214,8 +214,11 @@ export default () => {
let prop = null;
if (sector) {
- prop = sector.get('properties').where({ property: name });
- prop = prop.length == 1 ? prop[0] : prop;
+ prop = sector
+ .get('properties')
+ .filter(
+ prop => prop.get('property') === name || prop.get('id') === name
+ )[0];
}
return prop;
diff --git a/src/style_manager/model/Properties.js b/src/style_manager/model/Properties.js
index a865439ec..b2fbda89b 100644
--- a/src/style_manager/model/Properties.js
+++ b/src/style_manager/model/Properties.js
@@ -18,6 +18,8 @@ import PropertyIntegerView from './../view/PropertyIntegerView';
import PropertyView from './../view/PropertyView';
export default Backbone.Collection.extend(TypeableCollection).extend({
+ extendViewApi: 1,
+
types: [
{
id: 'stack',
diff --git a/src/style_manager/view/PropertyView.js b/src/style_manager/view/PropertyView.js
index a59e9e24e..9d3b9ed60 100644
--- a/src/style_manager/view/PropertyView.js
+++ b/src/style_manager/view/PropertyView.js
@@ -1,20 +1,16 @@
import Backbone from 'backbone';
import { bindAll, isArray, isUndefined, debounce } from 'underscore';
-import { camelCase } from 'utils/mixins';
+import { camelCase, isObject } from 'utils/mixins';
import { includes, each } from 'underscore';
const clearProp = 'data-clear-style';
export default Backbone.View.extend({
- template(model) {
- const pfx = this.pfx;
+ template() {
+ const { pfx, ppfx } = this;
return `
-
- ${this.templateLabel(model)}
-
-
- ${this.templateInput(model)}
-
+
+
`;
},
@@ -46,7 +42,7 @@ export default Backbone.View.extend({
},
initialize(o = {}) {
- bindAll(this, 'targetUpdated');
+ bindAll(this, 'targetUpdated', '__change', '__updateStyle');
this.config = o.config || {};
const em = this.config.em;
this.em = em;
@@ -63,6 +59,7 @@ export default Backbone.View.extend({
const pfx = this.pfx;
this.inputHolderId = '#' + pfx + 'input-holder';
this.sector = model.collection && model.collection.sector;
+ this.__destroyFn = this.destroy ? this.destroy.bind(this) : () => {};
model.view = this;
if (!model.get('value')) {
@@ -100,6 +97,11 @@ export default Backbone.View.extend({
init && init();
},
+ remove() {
+ Backbone.View.prototype.remove.apply(this, arguments);
+ this.__destroyFn(this._getClbOpts());
+ },
+
/**
* Triggers when the status changes. The status indicates if the value of
* the proprerty is changed or inherited
@@ -191,6 +193,7 @@ export default Backbone.View.extend({
*/
inputValueChanged(ev) {
ev && ev.stopPropagation();
+ if (this.emit) return;
this.model.setValueFromInput(this.getInputValue());
this.elementUpdated();
},
@@ -588,6 +591,7 @@ export default Backbone.View.extend({
setValue(value) {
const model = this.model;
let val = isUndefined(value) ? model.getDefaultValue() : value;
+ if (this.update) return this.__update(val);
const input = this.getInputEl();
input && (input.value = val);
},
@@ -625,16 +629,63 @@ export default Backbone.View.extend({
this.$input = null;
},
+ __update(value) {
+ const update = this.update && this.update.bind(this);
+ update &&
+ update({
+ ...this._getClbOpts(),
+ value
+ });
+ },
+
+ __change(...args) {
+ const emit = this.emit && this.emit.bind(this);
+ emit && emit(this._getClbOpts(), ...args);
+ },
+
+ __updateStyle(value, { complete, ...opts } = {}) {
+ const final = complete !== false;
+
+ if (isObject(value)) {
+ this.getTargets().forEach(target =>
+ target.addStyle(value, { avoidStore: !final })
+ );
+ } else {
+ this.model.setValueFromInput(value, complete, opts);
+ }
+
+ final && this.elementUpdated();
+ },
+
+ _getClbOpts() {
+ const { model, el } = this;
+ return {
+ el,
+ props: model.attributes,
+ setProps: (...args) => model.set(...args),
+ change: this.__change,
+ updateStyle: this.__updateStyle,
+ targets: this.getTargets()
+ };
+ },
+
render() {
this.clearCached();
- const pfx = this.pfx;
- const model = this.model;
- const el = this.el;
+ const { pfx, model, el, $el } = this;
const property = model.get('property');
const full = model.get('full');
const cls = model.get('className') || '';
const className = `${pfx}property`;
- el.innerHTML = this.template(model);
+
+ this.createdEl && this.__destroyFn(this._getClbOpts());
+ $el.empty().append(this.template(model));
+ $el.find('[data-sm-label]').append(this.templateLabel(model));
+ const create = this.create && this.create.bind(this);
+ this.createdEl = create && create(this._getClbOpts());
+ $el
+ .find('[data-sm-fields]')
+ .append(this.createdEl || this.templateInput(model));
+
el.className = `${className} ${pfx}${model.get(
'type'
)} ${className}__${property} ${cls}`.trim();
diff --git a/src/utils/mixins.js b/src/utils/mixins.js
index bde2e5c7e..9f44d76c4 100644
--- a/src/utils/mixins.js
+++ b/src/utils/mixins.js
@@ -210,6 +210,8 @@ const getPointerEvent = ev =>
const getKeyCode = ev => ev.which || ev.keyCode;
const getKeyChar = ev => String.fromCharCode(getKeyCode(ev));
const isEscKey = ev => getKeyCode(ev) === 27;
+const isObject = val =>
+ val !== null && !Array.isArray(val) && typeof val === 'object';
const capitalize = str => str && str.charAt(0).toUpperCase() + str.substring(1);
const isComponent = obj => obj && obj.toHTML;
@@ -242,6 +244,7 @@ export {
getViewEl,
setViewEl,
appendStyles,
+ isObject,
isComponent,
isRule
};