ConstructorInfotron
History Key
- New content
Removed content
Recent Versions
Choose two versions to compare, or click the link to view it.
Dynamically constructs an infotron from an HTML blueprint. It can also destruct the constructed infotron.
Sample Declaration
<div id=""
impl=""
properties=""
script=""></div>Input Terminals
Output Terminals
Properties
Demos that use it
- dynamic_construction.html
How does it work?
Source
/*
Mishmash of old and new code - need to think this better
and how atomic construction and this can become one and the same
intput_termials
request - <type:array>
[id, op, arg1, arg2, ...]
op
["construct", bp_uuid, intrinsic_props, extrinsic_props]
output_terminals
response - <type:array>
[id, op, response1, response2, ...] or [[op, response1, response2, ...], id]
properties
auto_detects_uri - <type: boolean>
uses_blueprint_uuid_as_uri - <type: boolean>
Seung Chan Lim ( slim@maya.com )
*/
BLUEPRINT(
"~01A405A30A314F45feA6C35668FF7819E6",
[
["request_in", "onRequest", 10]
],
[
"response_out"
],
function()
{
var Blueprint = function(id, props, bp_uuid)
{
this.__init__(id, bp_uuid);
/*************************************************************************/
this._URI_REGEX = new RegExp("^([a-zA-Z]+://)|(mailto:)");
this._REQ_HANDLER = {construct: this._add,
destruct : this._remove};
this._NON_ATOMIC_BP = "~01F6227AA626384b31850C90E63C829313";
this._req_id = {}; // keeps track of request id's associated with child
// construction
this._detect_uri = props["auto_detects_uri"];
this._bp_as_uri = props["uses_blueprint_uuid_as_uri"];
this._n = 0;
this._ids = {};
};
Blueprint.prototype = new Infotron;
// override default handling
/*************************************************************************/
Blueprint.prototype._onChildError = function(id, msg)
{
var resp = ["construct_failed", msg];
this.error("Failed to construct " + id + "[" + msg + "]");
if (this._req_id[id] != undefined) {
resp = [resp, this._req_id[id]];
delete this._req_id[id];
}
this.postMessage("response_out", resp);
}
Blueprint.prototype.onRequest = function(msg)
{
var op, id, e;
id = msg[0];
op = msg[1];
// request handlers return a unique id that request id's
// can be associated with
try {
var resp = this._REQ_HANDLER[op].apply(this, [id].concat(msg.slice(2)));
} catch (e) {
this.error(e, "Error handling " + op);
return;
/*****************************************************************/
}
if (id != undefined) {
// keep track of request id associated with the response
this._req_id[resp] = id;
}
}
Blueprint.prototype._createUid = function()
{
var id, now = new Date();
while (1) {
id = this.dom_node.id + "_na_child_" +
now.valueOf() + "_" + new String(Math.random()).substr(2);
if (!__d.getElementById(id)) {
// keep generating id until we have one that is unique
break;
} else {
this.caution("duplicate id generated, trying again...");
}
}
return id;
}
Blueprint.prototype._remove = function(req_id, id)
{
var i, n, e;
this.debug("DESTRUCT " + id);
try {
__star.removeInfotron(id, 1);
this.postMessage("response_out", [req_id, "destruct", id]);
} catch (e) {
this.error(e, "Error destructing " + id);
}
// _onChildShutDown(id, []);
}
Blueprint.prototype._add = function(req_id, bp, iprops, xprops)
{
var w, x, r, d, url;
var qs = "";
var now = new Date();
var id = this._createUid();
var na_props = {constructs_proactively:true};
if (!bp) {
this.error("BP for construction not specified");
return;
/*****************************************************************/
}
for (key in iprops) {
qs += escape(key) + "=" + escape(iprops[key]) + "&";
}
if (typeof(bp) != typeof("")) {
bp = bp.toString();
}
if ((this._detect_uri && this._URI_REGEX.test(bp)) || this._bp_as_uri) {
url = bp;
} else {
url = "";
}
d = __d.createElement("DIV");
if (iprops) {
// this is not architectural, but it at overcomes some issues
// of the web, namely the case where we construct a web page
// that does NOT have a pasteboard at the top (i.e. non-JDA
// web page) which may never resize its window to fit the
// top level pasteboard
w = iprops["width"], h = iprops["height"];
if (!isNaN(w)) {
d.style.width = w + "px";
}
if (!isNaN(h)) {
d.style.height = h + "px";
}
}
if (xprops) {
// setting x,y,z on the container div takes advantage of
// DomRenderer's behavior which inherits these values
// when it deals with pasteboards contained within
// non-atomic infotrons
x = xprops["x"], y = xprops["y"], z = xprops["z"];
if (!isNaN(z)) {
d.style.zIndex = z;
}
if (!isNaN(x)) {
d.style.left = x + "px";
}
if (!isNaN(y)) {
d.style.top = y +"px";
}
if (xprops["_x_is_top_level"]) {
na_props["uses_popup"] = true;
// TODO: fix this architecturally
d.style.position = "absolute";
d.style.zIndex = -10;
}
}
d.setAttribute("is_proxy", "true");
d.id = id;
d.innerHTML = "<a impl=\"" + bp + "\" href='" + url + ((qs) ? ("?" + qs) : "") + "'></a>";
d.className = "non-atomic";
this.dom_node.appendChild(d);
// dynamically construct a non-atomic infotron
// ( well, assume it's non-atomic, really )
this._n ++;
name = this._n + "_ready";
__star.addIterm(this.id, name, 1);
this.onMsg(name, "onReady");
__star.connectTerminals([d.id, "%ready"],
[this.id, name]);
name = this._n + "_error";
__star.addIterm(this.id, name, 10);
this.onMsg(name, "onError");
__star.connectTerminals([d.id, "%error"],
[this.id, name]);
name = this._n + "_shutdown";
__star.addIterm(this.id, name, 1);
this.onMsg(name, "onShutDown");
__star.connectTerminals([d.id, "%shutdown"],
[this.id, name]);
this._ids[id] = req_id;
if (url) {
r = __star.addInfotron(id, this._NON_ATOMIC_BP, na_props);
} else {
this.error("don't know the URL");
}
};
Blueprint.prototype.onReady = function(msg)
{
this.debug(msg[0] + " CONSTRUCTED!");
this.postMessage("response_out", [this._ids[msg[0]], "construct", msg[0], msg[1], msg[2]]);
}
Blueprint.prototype.onShutDown = function(msg)
{
this.debug(msg + " SHUT DOWN!");
}
Blueprint.prototype.onError = function(msg)
{
this.error(msg[0] + "ERROR!");
}
return Blueprint;
}, "NonAtomic Infotron Constructor");