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
API
-
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.
-
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" }
-
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> -
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)).
-
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.
Passing Messages to Parents:
Passing Messages to Children:
Defining HTML Modules:
Interacting with Modules:
Loading Relay:
Copyright © 2012