Comparing versions 3 and 4.

ConstructorInfotron

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 - 
          [id, op, arg1, arg2, ...]

      op
         ["construct", bp_uuid, intrinsic_props, extrinsic_props]

  output_terminals
      response - 
          [id, op, response1, response2, ...] or [[op, response1, response2, ...], id]

  properties
      auto_detects_uri - 
      uses_blueprint_uuid_as_uri - 
      

  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 = "