marko
Version:
UI Components + streaming, async, high performance, HTML templating for Node.js and the browser.
335 lines (235 loc) • 6.81 kB
JavaScript
"use strict";
/* jshint newcap:false */
var BaseState;
var BaseComponent;
var inherit;
var req = require("@internal/require");
var registry = require("@internal/components-registry");
var jQuery = require("../../../runtime/components/legacy/jquery");
var ready = require("../../../runtime/components/legacy/ready");
// eslint-disable-next-line no-constant-binary-expression
var hasHowOwnProperty = {}.hasOwnProperty;
var stateToJSONDef = {
enumerable: false,
value: function returnSelf() {
return this;
}
};
function noop() {}
module.exports = function defineWidget(def, renderer) {
def = def.Widget || def;
if (def.y_) {
return def;
}
var ComponentClass = function () {};
var proto;
var legacyInit;
if (typeof def === "function") {
proto = def.prototype;
legacyInit = def;
} else if (typeof def === "object") {
proto = def;
legacyInit = def.init;
} 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.y_) {
// Inherit from Component if they didn't already
ComponentClass.prototype = Object.create(BaseComponent.prototype);
for (var propName in proto) {
if (hasOwnProperty.call(proto, propName)) {
ComponentClass.prototype[propName] = proto[propName];
}
}
}
// 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.z_ = true;
proto.constructor = def.constructor = Component;
Object.defineProperty(proto, "state", {
get: function () {
var raw = this.A_ && this.A_.B_;
if (raw && !raw.toJSON) {
Object.defineProperty(this.A_.B_, "toJSON", stateToJSONDef);
}
return raw;
},
set: function (newState) {
newState = newState || {};
// eslint-disable-next-line no-constant-condition
this.setState(newState);
}
});
Object.defineProperty(proto, "__document", {
get: function () {
// eslint-disable-next-line no-constant-condition
return this.C_;
}
});
Object.defineProperty(proto, "el", {
get: function () {
// eslint-disable-next-line no-constant-condition
return this.D_;
}
});
// get legacy methods
proto.E_ = proto.onRender;
Object.defineProperty(proto, "onRender", {
get: noop,
set: function (v) {
proto.E_ = v;
}
});
proto.F_ = proto.onUpdate;
Object.defineProperty(proto, "onUpdate", {
get: function () {
return modernMountOrUpdate;
},
set: function (v) {
proto.F_ = v;
}
});
proto.G_ = proto.onDestroy;
Object.defineProperty(proto, "onDestroy", {
get: function () {
return modernOnDestory;
},
set: function (v) {
proto.G_ = v;
}
});
proto.getWidget = proto.getComponent;
proto.getWidgets = proto.getComponents;
proto.onMount = modernMountOrUpdate;
if (legacyInit) {
proto.H_ = legacyInit;
}
// convert legacy to modern
proto.I_ = proto.update;
proto.update = function () {
if (this.J_) {
// eslint-disable-next-line no-constant-condition
this.destroy = modernOnDestory;
this.J_ = false;
}
this.K_ = true;
if (this.D_) {
this.onBeforeUpdate && this.onBeforeUpdate();
}
this.I_();
this.K_ = false;
};
function modernMountOrUpdate() {
// eslint-disable-next-line @typescript-eslint/no-this-alias
var self = this;
var el = this.L_["@_wbind"];
var prevEl = this.D_;
if (prevEl !== el) {
this.D_ = el;
if (prevEl) {
this.onBeforeDestroy && this.onBeforeDestroy();
this.G_ && this.G_();
this.M_ = undefined;
this.removeAllListeners();
}
if (el) {
this.H_ && this.H_(this.widgetConfig || {});
this.E_ && this.E_({ firstRender: true });
this.M_ = legacyRender;
// eslint-disable-next-line no-constant-condition
el.__widget = this;
}
} else if (el) {
if (prevEl) {
this.F_ && this.F_();
}
if (this.N_) {
this.E_ &&
this.E_({ firstRender: false });
}
}
this.O_ = this.P_;
this.P_ = null;
this.N_ = false;
}
function legacyRender() {
if (!this.K_) {
this.onBeforeUpdate && this.onBeforeUpdate();
}
this.N_ = true;
}
function modernOnDestory() {
if (this.D_) {
this.onBeforeDestroy && this.onBeforeDestroy();
this.G_ && this.G_();
this.D_ = null;
}
}
// 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.y_ = true;
function State() {
BaseState.apply(this, arguments);
}
inherit(State, BaseState);
proto.Q_ = State;
jQuery.patchComponent(
window.$,
proto,
true /* don't throw error until used if `$` is missing*/
);
ready.patchComponent(proto);
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.R_ = renderer;
Component.render = renderer.render;
Component.renderSync = renderer.renderSync;
}
// eslint-disable-next-line no-constant-condition
Component._isWidget = true;
var template = def.template;
if (template) {
if (typeof template === "string") {
template = req(template);
}
registry.r((template.default || template).S_, function () {
return Component;
});
}
return Component;
};
BaseState = require("../../../runtime/components/State");
BaseComponent = require("../../../runtime/components/Component");
inherit = require("raptor-util/inherit");