UNPKG

@danielkalen/simplybind

Version:

Magically simple, framework-less one-way/two-way data binding for frontend/backend in ~5kb.

133 lines (109 loc) 3.06 kB
var h = require('./rendering').html; var VText = require("virtual-dom/vnode/vtext.js") var domComponent = require('./domComponent'); function ComponentWidget(state, vdom) { if (!vdom) { throw new Error('plastiq.html.component([options], vdom) expects a vdom argument'); } this.state = state; this.key = state.key; if (typeof vdom === 'function') { this.render = function () { if (h.currentRender) { h.currentRender.eventHandlerWrapper = state.on; } return vdom.apply(this.state, arguments); }; this.canRefresh = true; } else { vdom = vdom || new VText(''); this.render = function () { return vdom; } } this.cacheKey = state.cacheKey; this.component = domComponent(); var renderFinished = h.currentRender && h.currentRender.finished; if (renderFinished) { this.afterRender = function (fn) { renderFinished.then(fn); }; } else { this.afterRender = function () {}; } } ComponentWidget.prototype.type = 'Widget'; ComponentWidget.prototype.init = function () { var self = this; if (self.state.onbeforeadd) { self.state.onbeforeadd(); } var vdom = this.render(this); if (vdom instanceof Array) { throw new Error('vdom returned from component cannot be an array'); } var element = this.component.create(vdom); if (self.state.onadd) { this.afterRender(function () { self.state.onadd(element); }); } if (self.state.detached) { return document.createTextNode(''); } else { return element; } }; ComponentWidget.prototype.update = function (previous) { var self = this; var refresh = !this.cacheKey || this.cacheKey !== previous.cacheKey; if (refresh) { if (self.state.onupdate) { this.afterRender(function () { self.state.onupdate(self.component.element); }); } } this.component = previous.component; if (previous.state && this.state) { var keys = Object.keys(this.state); for(var n = 0; n < keys.length; n++) { var key = keys[n]; previous.state[key] = self.state[key]; } this.state = previous.state; } if (refresh) { var element = this.component.update(this.render(this)); if (self.state.detached) { return document.createTextNode(''); } else { return element; } } }; ComponentWidget.prototype.refresh = function () { this.component.update(this.render(this)); if (this.state.onupdate) { this.state.onupdate(this.component.element); } }; ComponentWidget.prototype.destroy = function (element) { var self = this; if (self.state.onremove) { this.afterRender(function () { self.state.onremove(element); }); } this.component.destroy(); }; module.exports = function (state, vdom) { if (typeof state === 'function') { return new ComponentWidget({}, state); } else if (state.constructor === Object) { return new ComponentWidget(state, vdom); } else { return new ComponentWidget({}, state); } }; module.exports.ComponentWidget = ComponentWidget;