Select Git revision
jsunit.js 3.67 KiB
// event system to include type-checking etc
// dataflow types for javascript objects ...
var verbose = false
function Input(type, fn) {
var input = {
accepts: type,
fn: fn
}
return input
}
function Output(type) {
var output = {
emits: type
}
output.calls = new Array()
output.attach = function(input) {
this.calls.push(input)
}
output.isLinked = function(input) {
// return true if already hooked up
if (this.calls.includes(input)) {
return true
} else {
return false
}
}
output.remove = function(input) {
if (!this.isLinked(input)) {
console.log('attempt to rm input that is not attached')
return false
} else {
this.calls.splice(this.calls.indexOf(input), 1)
}
}
output.removeAllLinks = function() {
this.calls = []
}
output.checkLinks = function(id) {
console.log('checking links', this)
for (index in this.calls) {
if (this.calls[index].parentId == id) {
console.log('popping null entry from', this.calls)
this.calls.splice(index, 1)
console.log('new record', this.calls)
} else {
// all good
}
}
}
output.emit = function(data) {
if (this.calls.length == 0) {
if(verbose) console.log('no inputs bound to this output')
} else {
for (index in this.calls) {
this.calls[index].fn(JSON.parse(JSON.stringify(data)))
}
}
}
return output
}
function State() {
var state = {}
state.emitters = {}
state.parentId = null
state.socket = null
// called when change from UI
state.onUiChange = function(item, fn) {
this.emitters[item] = fn
}
state.emitUIChange = function(item) {
if (this.emitters[item] != null) {
this.emitters[item]()
}
}
state.pushToUI = function(key) {
if (this.socket.send != null) {
var data = {
id: this.parentId,
key: key,
val: this[key]
}
this.socket.send('put state change', data)
} else {
console.log("ERR on state update to UI, socket is", this.socket)
}
}
state.init = function(parentModId, socket) {
// get hookups from top level program
this.parentId = parentModId
this.socket = socket
// and wrap state objects in getters / setters
for (key in this) {
if (isStateKey(key)) {
this['_' + key] = this[key]
this[key] = {}
writeStateGetterSetter(this, key)
}
}
}
return state
}
function writeStateGetterSetter(state, key) {
Object.defineProperty(state, key, {
set: function(x) {
// update internal value
state['_' + key] = x
// console.log('SET', key, this['_' + key])
// push to external view
state.pushToUI(key)
}
})
Object.defineProperty(state, key, {
get: function() {
//console.log('GET', key, this['_' + key])
return state['_' + key]
}
})
}
function isStateKey(key) {
if (key.indexOf('_') == 0 || key == 'parentId' || key == 'socket' || key == 'init' || key == 'pushToUI' || key == 'emitters' || key == 'onUIChange' || key == 'emitUIChange' ) {
return false
} else {
return true
}
}
module.exports = {
Input: Input,
Output: Output,
State: State,
isStateKey: isStateKey
}