JS Autowire Documentation

Connect Javascript classes to DOM Nodes, auto-assign event listeners, and access other Autowired nodes with ease.

Newly Added:

  • Requests can be sent and responded to more easily. In an Autowire class, call this.send(url, data, this.responseMethod, requestMethod="POST");. responseMethod will be auto-bound with the same this which calls this.send. this.responseMethod accepts one paramater, which is a JSON Object. If the request does not return a JSON object, it will not work.
  • (no tests) Set this.context = this.nodeContext(node.parentNode,contextName='default') to set the context based upon a node. A unique id is generated for the node passed to nodeContext(...). contextName is optional & usually not necessary
  • (no tests) autoprops always return an array now. Previous it returned null if not found, the object if only one found, and an array if > 1 found
  • (no tests) this.oneProp will load a single object for _prop(){ return 'ClassNameOfTarget' }. If one item, returns it. If multiple items, returns the first (no intentional ordering). If no items, returns null

Features

  • Automatically attach a Javascript class/object to a DOM Node
  • Reference other AutoWire objects (& their attached nodes) with 1-line autoproperty methods.
  • Create multiple contexts in which AutoWire objects can relate
  • Declare event listeners (like onclick) in your class to add the listeners to the nodes.

Demonstration

This is the final code & a demonstration of it in action. Look below for details on how we built this simple class.

<script type="text/javascript">
    class Increment extends RB.WireContext {
        _count(){ return 'RB_Count'; } // this.count will return the .RB_Count Object (not the node directly). 
        __attach(){ this.context = "RB"; }

        onclick(event){
            const count = parseInt(this.count.node.innerText.trim())+1;
            this.count.node.innerText = count;
        }
    }
    // Increment.querySelector = ".rb-Increment";
    Increment.className = "rb-Increment";
    Increment.autowire();
    class RB_Count extends RB.WireContext{
        __attach(){ this.context = "RB"; }
    }
    RB_Count.autowire();
</script>
<button class="rb-Increment">Add 1</button>
<div class="RB_Count">0</div>

Note: This will only work if these docs are hosted on a site that is delivering the framework.

0

The Gist

  • Declare class YourClass extends RB.WireContext to enable this framework on a class & make it auto-wireable
  • this.node refers to the attached node
  • Auto-matic Event listeners:
    • Specify onclick(event){} for a click-listener, ontouch(event){} for ontouch, and so on. Any on prefix results in a listener being set
  • Override __attach() or __construct() to do setup-operations
  • Autowiring Class/Object to Node:
    • Match classnames for autowire(): class YourClass with <div class="YourClass">
    • Specify YourClass.className='CSSClassName' or YourClass.querySelector = '.CssClassName'; To specify what will be attached with .autowire() calls
    • Call YourClass.autowire('.querySelector') to override the default
  • Context & AutoProps
    • Declare this.context='ContextName' in __construct(). All nodes in the same 'ContextName' will be able to reference each other with _autoProps...
    • Specify _propName(){return 'ClassName';} to allow nodes attached to 'ClassName' to be referenced with this.propName;
    • Declare this.context=['ContextName','OtherContext']; to have multiple contexts
    • Specify _propName(){return [null,'ClassName'];} to auto-prop from your 'OtherContext'

Install

  • Download/copy Autowire-min.js & deliver it on your own server
  • TODO: <script type="text/javascript" href="#PATH-TO-CDN"></script> (Because who doesn't host their js package on a CDN?)
  • TODO: composer require rbear/js-autowire (a PHP universe thing...)
  • TODO: npm something something (A world I'm new to)

Wiring up a node

Create a javascript class that extends RB.WireContext. (Note: This will be changed to a better name):

class Increment extends RB.WireContext {}
class RB_Count extends RB.WireContext{}

& and some HTML:

<button class="rb-Increment">Add 1</button>
<div class="RB_Count">0</div>

Now we have to specify the class name & call autowire:

Increment.className = 'rb-Increment';
Increment.autowire();
//Notice we included the vendor prefix in the javascript class name. So this will be mapped to the HTML node w/ class="RB_Count"
// So we don't declare `RB_Count.className = 'RB_Count';`
RB_Count.autowire();

But they don't do ANYTHING at this point. Full examples are below

Wiring Options

  • Pass a query-selector to autowire like: Increment.autowire('.rb-Increment');
  • Specify the query-slector on the class: Increment.querySelector = '.rb-Increment';
    • Any query selector works. Such as Increment.querySelector = 'div#TheIncrementor'; will attach <div id="TheIncrementor"> to Increment
  • Direct Wiring (static): Increment.wireNode(someNodeObject);
  • Direct Wiring (instance): new \Increment(someNodeObject);
  • Specify the css class name: Increment.className = "rb-Increment";
  • Use the declared class name: class BigDiv extends RB.WireContext maps to <anytag class="BigDiv">

Initialization Methods

Every class can implement the initialization methods __construct() && __attach().

  • __construct() is called before a node is attached to the JS Object
  • __attach() is called post-attach.
    • The associated node can be referenced with this.node from inside __attach()
    • Warning: It is not safe to use the auto-properties (see below) at this point, as there's no guarantee that everything has been wired up.
  • TODO: __allReady(): Once made, this method will be called after all initial loading is done.
    __attach is demonstrated in the context example below

Using Context

  1. Specify this.context in the __attach() method.
  2. Add _paramName() methods to make auto-getters.

Modify the above classes like so:

    class Increment extends RB.WireContext {
        _count(){ return 'RB_Count'; } // this.count will return the .RB_Count node. 
        __attach(){
            this.context = "RB";
        }
    }
    class RB_Count extends RB.WireContext{
        //RB_Count is only here to be referenced by Increment... so We don't need any auto-properties
        __attach(){
            this.context = "RB";
        }
    }

Warning: It is not safe to use the auto-properties during __attach, as there's no guarantee that everything has been wired up.

Event auto-wiring

Prefix a function name with on & an event listener will automatically be added to the node.
Note: Inside the listener, this will refer to your JS Object, NOT to the node object. The node can be retrieved with this.node, and usually event.target will be the same.
We'll modify our Increment class to demonstrate.

    class Increment extends RB.WireContext {
        _count(){ return 'RB_Count'; } // this.count will return the .RB_Count Object (not the node directly). 
        __attach(){ this.context = "RB"; }

        onclick(event){
            const count = parseInt(this.count.node.innerText.trim())+1;
            this.count.node.innerText = count;
        }
    }