Implement Component type 'pane' and merge more functionality with 'row'.

This commit is contained in:
Jürg Lehni 2014-10-02 18:16:38 +02:00
parent 99d46b4478
commit fd6741ce5a
2 changed files with 84 additions and 74 deletions

View file

@ -80,7 +80,8 @@ var Component = Base.extend(Callback, /** @lends Component# */{
}
},
row: {}
row: {},
pane: {}
},
// Default values for internals
@ -97,7 +98,7 @@ var Component = Base.extend(Callback, /** @lends Component# */{
this._row = row;
this._parent = parent; // The parent component, if any.
this._nested = !!parent;
if (!parent)
if (!parent || parent._type !== 'row')
DomElement.set(row, 'id', 'palettejs-row-' + name);
var type = this._type = props.type in this._types
? props.type
@ -108,43 +109,49 @@ var Component = Base.extend(Callback, /** @lends Component# */{
: typeof value,
meta = this._meta = this._types[type] || { type: type },
that = this,
create = DomElement.create;
if (type === 'row') {
var components = this._components = [];
for (var key in props) {
var entry = props[key];
if (Base.isPlainObject(entry))
components.push(new Component(pane, key, entry, values, row,
this));
create = DomElement.create,
element = null,
isRow = type === 'row',
isPane = type === 'pane';
if (isRow || isPane) {
var childPane = this._childPane = new Pane(props, values, this,
isRow && row);
if (isRow) {
pane._numCells = childPane._numCells;
} else { // isPane
element = childPane._table;
}
pane._numCells = Math.max(components.length * 2, pane._numCells || 0);
} else {
element = this._input = create(meta.tag || 'input', {
class: 'palettejs-input',
id: 'palettejs-input-' + name,
type: meta.type,
events: {
change: function() {
that.setValue(DomElement.get(this,
meta.value || 'value'));
},
click: function() {
that.fire('click');
}
}
});
}
if (element) {
DomElement.addChildren(row, [
this._labelCell = create('td', {
class: 'palettejs-label',
id: 'palettejs-label-' + name
}),
this._cell = create('td', {
class: 'palettejs-component',
class: 'palettejs-component palettejs-type-' + type,
id: 'palettejs-component-' + name
}, [
this._input = create(meta.tag || 'input', {
class: 'palettejs-input',
id: 'palettejs-input-' + name,
type: meta.type,
events: {
change: function() {
that.setValue(DomElement.get(this,
meta.value || 'value'));
},
click: function() {
that.fire('click');
}
}
})
])
}, [ element ])
]);
// We just added two cells to the row:
pane._numCells += 2;
}
// Attach default 'change' even that delegates to palette
this.attach('change', function(value) {
if (!this._dontFire)
@ -163,8 +170,6 @@ var Component = Base.extend(Callback, /** @lends Component# */{
this._dontFire = false;
// Store link to component in the pane's components object.
pane._components[name] = this;
// Make sure each component has an entry in values also, so observers
// get installed correctly in the Pane constructor.
values[name] = this._defaultValue = this._value;
},
@ -177,10 +182,12 @@ var Component = Base.extend(Callback, /** @lends Component# */{
},
_setLabel: function(label, nodeName, parent) {
this[nodeName] = DomElement.set(this[nodeName]
|| parent.appendChild(DomElement.create('label',
{ 'for': 'palettejs-input-' + this._name })),
'text', label);
if (parent) {
this[nodeName] = DomElement.set(this[nodeName]
|| parent.appendChild(DomElement.create('label',
{ 'for': 'palettejs-input-' + this._name })),
'text', label);
}
},
getLabel: function() {
@ -219,6 +226,8 @@ var Component = Base.extend(Callback, /** @lends Component# */{
},
setValue: function(value) {
if (this._childPane)
return;
var meta = this._meta,
key = meta.value || 'value',
setValue = meta.setValue;
@ -263,10 +272,8 @@ var Component = Base.extend(Callback, /** @lends Component# */{
}
if (this._input) {
DomElement.set(this._input, 'disabled', !enabled);
} else if (this._components) {
for (var i = 0; i < this._components.length; i++) {
this._components[i].setEnabled(enabled, _fromPalette);
}
} else if (this._childPane) {
this._childPane.setEnabled(enabled);
}
this._enabled = !!enabled;
},
@ -306,6 +313,10 @@ var Component = Base.extend(Callback, /** @lends Component# */{
},
reset: function() {
this.setValue(this._defaultValue);
if (this._childPane) {
this._childPane.reset();
} else {
this.setValue(this._defaultValue);
}
}
});

View file

@ -20,53 +20,52 @@ var Pane = Base.extend(Callback, /** @lends Pane# */{
// Defaults for internals
_enabled: true,
initialize: function Pane(components, values) {
initialize: function Pane(components, values, parent, parentRow) {
if (!values)
values = {};
this._table = DomElement.create('table', { class: 'palettejs-pane' });
// NOTE: We modify the actual passed components and values objects so
// the newly created components and their values can easily be
// referenced from outside.
this._components = components;
this._table = !parentRow && DomElement.create('table', {
class: 'palettejs-pane'
});
// NOTE: We modify the actual passed components in the root pane, and
// also the values objects, so the newly created components and their
// values can easily be referenced from outside.
this._components = parent ? {} : components;
this._values = values;
this._numCells = 2; // 2 cells per row is the default (label / item).
var numCells = 0;
this._numCells = 0;
for (var name in components) {
var component = components[name];
if (Base.isPlainObject(component)) {
var row = DomElement.addChildren(this._table,
var row = parentRow || DomElement.addChildren(this._table,
['tr', { class: 'palettejs-row' }])[0];
new Component(this, name, component, values, row);
} else {
delete components[name];
this._components[name] = new Component(this, name, component,
values, row, parent);
numCells = Math.max(numCells, this._numCells);
if (!parentRow)
this._numCells = 0;
}
}
if (this._numCells > 2) {
this._numCells = numCells;
// Override in case we made a copy, see above.
components = this._components;
Base.each(components, function(component, name) {
// Update colspan in all components that are not nested in another
// component.
for (name in components) {
var component = components[name];
if (component._cell && !component._nested) {
DomElement.set(component._cell, 'colspan',
this._numCells - 1); // Remove first label.
if (numCells > 2 && component._cell && !component._nested) {
DomElement.set(component._cell, 'colspan', numCells - 1);
}
// Now replace each entry in values with a getter / setters so we
// can directly link the value to the component and observe change.
Base.define(values, name, {
enumerable: true,
configurable: true,
get: function() {
return component.getValue();
},
set: function(val) {
component.setValue(val);
}
}
}
// Now replace each entry in values with a getter / setters so we can
// directly link the value to the component and observe change.
Base.each(values, function(value, name) {
var component = components && components[name];
if (component) {
Base.define(values, name, {
enumerable: true,
configurable: true,
get: function() {
return component.getValue();
},
set: function(val) {
component.setValue(val);
}
});
}
});
});
},