relay

RelayJS is a javascript based framework for organizing web applications into scoped modules and communication is done by passing messages along the HTML tree structure, thereby eliminating the need to pass object references around.

How to set up event listeners:

<style> ins {text-decoration:none} </style>
<body>
  <ins cite="js:Spinner">
    <input type=text value="0">
    <input type=button onclick="relay('spinDownClick', this);">
    <input type=button onclick="relay('spinUpClick', this);">
  </ins>
</body>

<script language=javascript>
function Spinner(name, node) {...}

Spinner.prototype = {
  value: 0,
  spinDownClick: function() {
    this.relayBaseNode.getElementsByTagName("input")[0].value -= 1;
  },
  spinUpClick: function() {
    this.relayBaseNode.getElementsByTagName("input")[0].value += 1;
  }
};
</script>

How to pass messages up the HTML tree:

<body>
  <ins cite="js:CartItem">
    ...
    <ins cite="js:Spinner">
      <input type=text value="0">
      <input type=button onclick="relay('spinDownClick', this);">
      <input type=button onclick="relay('spinUpClick', this);">
    </ins>
    ...
  </ins>
</body>

<script language=javascript>
function Spinner(name, node) {...}

Spinner.prototype = {
  value: 0,
  spinDownClick: function() {
    var elm = this.relayBaseNode.getElementsByTagName("input")[0];
    elm.value -= 1;
    relay("quantityChanged", elm.value, this);
  },
  spinUpClick: function() {
    var elm = this.relayBaseNode.getElementsByTagName("input")[0];
    elm.value += 1;
    relay("quantityChanged", elm.value, this);
  }
};

function CartItem(name, node) {...}

CartItem.prototype = {
  quantityChanged: function(num) {
    //...
  }
};
</script>

Interacting with the module hidden by the node:

<body>
  <ins id="pics" cite="js:acme.Photos"></ins>
</body>

<script language=javascript>
var acme = {
  Photos: function(name, node) {...}
};

acme.Photos.prototype = {
  fitToScreen: function() {...}
};
...
function action() {
  relay.byId("pics").fitToScreen();

  // or by using jQuery:
  jQuery("#pics").each(function() {
    relay.byId(this).fitToScreen();
  });
}
</script>

Features

Relay

Module Framework

For writing standalone HTML components that are de-coupled from each other. HTML components have a Javascript class from which it derives it's methods and properties. HTML components can be nested within one another without knowing it.

Messaging Framework

Upstream

HTML components can pass messages to parent components. Unlike the event listener model, you do not need to know of the existence of a parent to pass messages to a parent. And you do not need to know the existence of children to listen in on children calling. Messages can return values allowing for the root node to provide a response to the leaf node.

Downstream

HTML components can broadcast messages like the publish-subscribe model, but messages are scoped to the current node, so only it's children can receive them. Objects are implicitly subscribed if they are part of the HTML tree and are implicitly unsubscribed if they are removed from the HTML tree.

Download

Relay on Github View Source Download Minified (2k) View Bug Reports

API

Passing Messages to Parents:

Syntax: relay(name, [parameters]*, this)
Example: relay("mailto", "spam@hotmail.com", false, 9, this)mailto("spam@hotmail.com", false, 9)
Walks down the node tree starting from the current node until it finds a Javascript object with a function called name and calls it while passing in the supplied parameters. If the name function returns the object relay.BUBBLE, then we continue to walk down the node tree to the next node with a Javascript object with the same method and try again.

The return value of the name function is also returned by relay.

Syntax: relay(inlineFunction, [parameters]*, this)
Example: relay(function() {this.chatName = ""}, this)
Same behavior as above, but does not match to a function name, but instead executes on the first object found in the HTML tree.

Passing Messages to Children:

Syntax: relay.forward(name, [parameters]*, this)
Example: relay.forward("refresh", this)
Gets a list of descendant elements of the current node, which are modules and check if the module has a subscribe property on it. If so, check if the subscribe object has a property called name that points to a function. If so, execute the function with the this scope set to the module.

Folder = { subscribe: { "refresh": function() { alert(this.name); } }, name: "Inbox" }

Defining HTML Modules:

Syntax: <INS cite="js:name"></INS>
Example: <INS cite="js:acme.DatePicker"></INS>new acme.DatePicker("acme.widgets.DatePicker", node)
Finds and initializes the object called name. A reference to the object is kept privately inside Relay and can be retrieved by calling relay.byId(document.getElementById("item1")) or relay.byId("item1") assuming that the element has an id of "item1".

Be sure to reset the natural CSS styles of <INS> elements or else everything will turn up underlined:
<style> ins {text-decoration:none} </style>

Interacting with Modules:

Syntax: obj = relay.byId(nodeOrID)
Get's the Javascript object hidden by the supplied node or supplied node ID. This is the same as calling relay.byId(document.getElementById(id)).

Loading Relay:

Syntax: relay.start() or relay.initTree(node)
Example: window.onload = function() { relay.start(); }
Called when the webpage is first loaded to parse the HTML document for modules and to initialize the modules. If parts of the HTML are created dynamically, then you can call initTree(node) to initialize new sections of the webpage. Calling it multiple times won't create duplicates as checks are added to avoid this.

You should call this at the bottom of your webpage before the ending </BODY> tag.

Copyright © 2012