Skip to content

Instantly share code, notes, and snippets.

@lahmatiy
Created July 27, 2016 13:17
Show Gist options
  • Save lahmatiy/c9252232b568515a1a1a84919cdce187 to your computer and use it in GitHub Desktop.
Save lahmatiy/c9252232b568515a1a1a84919cdce187 to your computer and use it in GitHub Desktop.
Implementation of `model` and `visible` for from fields in basis.js
var events = require('basis.event');
var resolveValue = require('basis.data').resolveValue;
module.exports = function createBlockClass(BaseClass, ext) {
return BaseClass.subclass(ext, {
visible: true,
visibleRA_: null,
emit_visibleChanged: events.create('visibleChanged'),
// value could be a function or binding-bridge instance; any other converts to bool
setVisible: function(value) {
value = Boolean(resolveValue(this, this.setVisible, value, 'visibleRA_'));
if (this.visible !== value) {
this.visible = value;
this.emit_visibleChanged();
}
},
binding: {
visible: {
events: 'visibleChanged',
getter: function(node) {
return node.visible;
}
},
hidden: {
events: 'visibleChanged',
getter: function(node) {
return !node.visible;
}
}
},
init: function() {
BaseClass.prototype.init.call(this);
this.visible = Boolean(resolveValue(this, this.setVisible, this.visible, 'visibleRA_'));
},
destroy: function() {
if (this.visibleRA_) {
resolveValue(this, null, null, 'visibleRA_');
}
BaseClass.prototype.destroy.call(this);
}
});
};
var events = require('basis.event');
var resolveValue = require('basis.data').resolveValue;
var Value = require('basis.data').Value;
var isEntity = require('basis.entity').isEntity;
var DATA_HANDLER = {
update: function(sender, delta) {
if (this in delta) {
sender.syncFromModel(sender.data[this]);
}
}
};
var modelInterface = {
data: {
attach: function(model) {
this.addHandler(DATA_HANDLER, model);
this.syncFromModel(this.data[model]);
},
detach: function(model) {
this.removeHandler(DATA_HANDLER, model);
},
get: function(model) {
return this.data[model];
},
set: function(model, value) {
if (this.target) {
if (isEntity(this.target)) {
this.target.set(
model,
this.toModel(value, this.model_.get.call(this, this.model)),
typeof this.target.getId == 'function' ? Boolean(this.target.getId()) : false
);
} else {
var data = {};
data[model] = this.toModel(value);
this.update(data);
}
}
}
},
token: {
attach: function(model) {
model.attach(this.syncFromModel, this);
this.syncFromModel(model.get());
},
detach: function(model) {
model.detach(this.syncFromModel, this);
},
get: function(model) {
return model.get();
},
set: function(model, value) {
model.set(value);
}
},
value: {
attach: function(model) {
model.link(this, this.syncFromModel);
},
detach: function(model) {
model.unlink(this, this.syncFromModel);
},
get: function(model) {
return model.value;
},
set: function(model, value) {
model.set(value);
}
}
};
function getModelInterface(value) {
var type;
if (typeof value == 'string') {
type = 'data';
}
if (value instanceof basis.Token) {
type = 'token';
}
if (value instanceof Value) {
type = 'value';
}
return modelInterface[type];
}
module.exports = function createFieldClass(BaseClass, ext) {
return BaseClass.subclass({
autoDelegate: true,
model: null,
model_: null, // interface for model
fromModel: basis.fn.$self, // model -> field value convertion
toModel: basis.fn.$self, // field -> model value convertion
syncFromModel: function(value) { // model -> field sync
this.setValue(this.fromModel(value, this.getValue()));
},
syncToModel: function(value) { // field -> model sync
if (this.model_) {
this.model_.set.call(this, this.model, this.toModel(value, this.model_.get.call(this, this.model)));
}
},
emit_change: function(oldValue) {
BaseClass.prototype.emit_change.call(this, oldValue);
this.syncToModel(this.getValue());
},
setModel: function(model) {
var modelInterface = null;
if (typeof model == 'function') {
model = model(this);
}
if (!model) {
model = null;
} else {
modelInterface = getModelInterface(model);
if (!modelInterface) {
/** @cut */basis.dev.warn('Bad value for Field#model property (value treats as `null`)');
model = null;
}
}
if (this.model === model) {
return;
}
if (this.model_) {
this.model_.detach.call(this, this.model);
}
this.model = model;
this.model_ = modelInterface;
if (this.model_) {
this.model_.attach.call(this, this.model);
}
},
visible: true,
visibleRA_: null,
emit_visibleChanged: events.create('visibleChanged'),
// value could be a function or binding-bridge instance; any other converts to bool
setVisible: function(value) {
value = Boolean(resolveValue(this, this.setVisible, value, 'visibleRA_'));
if (this.visible !== value) {
this.visible = value;
this.emit_visibleChanged();
}
},
binding: {
visible: {
events: 'visibleChanged',
getter: function(node) {
return node.visible;
}
},
hidden: {
events: 'visibleChanged',
getter: function(node) {
return !node.visible;
}
}
},
init: function() {
BaseClass.prototype.init.call(this);
var model = this.model;
if (this.model) {
this.model = null;
this.setModel(model);
}
this.visible = Boolean(resolveValue(this, this.setVisible, this.visible, 'visibleRA_'));
},
destroy: function() {
this.setModel();
if (this.visibleRA_) {
resolveValue(this, null, null, 'visibleRA_');
}
BaseClass.prototype.destroy.call(this);
}
}, ext);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment