marko/components/legacy/defineWidget-legacy-browser.js
2017-02-20 16:30:16 -07:00

147 lines
4.2 KiB
JavaScript

'use strict';
/* jshint newcap:false */
var BaseState;
var BaseComponent;
var inherit;
module.exports = function defineWidget(def, renderer) {
def = def.Component || def;
if (def.$__isComponent) {
return def;
}
var ComponentClass = function() {};
var proto;
if (typeof def === 'function') {
proto = def.prototype;
proto.init = def;
} else if (typeof def === 'object') {
proto = def;
} else {
throw TypeError();
}
ComponentClass.prototype = proto;
// We don't use the constructor provided by the user
// since we don't invoke their constructor until
// we have had a chance to do our own initialization.
// Instead, we store their constructor in the "initComponent"
// property and that method gets called later inside
// init-components-browser.js
function Component(id, doc) {
BaseComponent.call(this, id, doc);
}
if (!proto.$__isComponent) {
// Inherit from Component if they didn't already
inherit(ComponentClass, BaseComponent);
}
// The same prototype will be used by our constructor after
// we he have set up the prototype chain using the inherit function
proto = Component.prototype = ComponentClass.prototype;
proto.constructor = def.constructor = Component;
// get legacy methods
var init = proto.init;
var onRender = proto.onRender;
var onBeforeUpdate = proto.onBeforeUpdate;
var onUpdate = proto.onUpdate;
var onBeforeDestroy = proto.onBeforeDestroy;
var onDestroy = proto.onDestroy;
// delete legacy methods
delete proto.init;
delete proto.onRender;
delete proto.onBeforeUpdate;
delete proto.onUpdate;
delete proto.onBeforeDestroy;
delete proto.onDestroy;
// convert legacy to modern
if (init || onRender) {
proto.onMount = function() {
var self = this;
var config = this.$c;
if (init) init.call(this, config);
if (onRender) {
onRender.call(this, { firstRender:true });
this.on('$__legacyRender', function() {
self.$__didUpdate = true;
});
}
};
}
if (onBeforeUpdate || onUpdate) {
proto.onUpdate = function() {
if (onBeforeUpdate) onBeforeUpdate.call(this);
if (onUpdate) onUpdate.call(this);
if (onRender && this.$__didUpdate) {
this.$__didUpdate = false;
onRender.call(this, {});
}
};
}
if (onBeforeDestroy || onDestroy) {
proto.onDestroy = function() {
if (onBeforeDestroy) onBeforeDestroy.call(this);
if (onDestroy) onDestroy.call(this);
};
}
// Set a flag on the constructor function to make it clear this is
// a component so that we can short-circuit this work later
Component.$__isComponent = true;
function State() { BaseState.apply(this, arguments); }
inherit(State, BaseState);
proto.$__State = State;
if (!renderer) {
renderer = ComponentClass.renderer || ComponentClass.prototype.renderer;
if (renderer) {
// Legacy support
var createOut = renderer.createOut;
if (typeof renderer !== 'function') {
var rendererObject = renderer;
renderer = function(input, out) {
var rendererFunc = rendererObject.renderer || rendererObject.render;
rendererFunc(input, out);
};
renderer.createOut = createOut;
}
renderer.render = function(input) {
var out = createOut();
renderer(input, out);
return out.end();
};
}
}
if (renderer) {
// Add the rendering related methods as statics on the
// new component constructor function
Component.renderer = proto.renderer = renderer;
Component.render = renderer.render;
Component.renderSync = renderer.renderSync;
}
return Component;
};
BaseState = require('../State');
BaseComponent = require('../Component');
inherit = require('raptor-util/inherit');