Skip to content
ismell edited this page May 30, 2012 · 2 revisions

0.8.0

Many of the new features are not fully documented on the wiki, but there are examples inline in the release notes below.

Getting it

Browser/AMD:

  1. git clone https://github.com/cujojs/wire
  2. cd wire
  3. git submodule init && git submodule update

Or:

  1. download it as a zip.
  2. You'll also need when.js 1.0.4 and aop.js 0.5.3

Node

  1. npm install git://github.com/cujojs/wire#0.8.0

RingoJS

  1. ringo-admin install cujojs/when
  2. ringo-admin install cujojs/aop
  3. ringo-admin install https://github.com/cujojs/wire/zipball/0.8.0

core

  • Runs in Node
    • var wire = require('wire');
  • Runs in RingoJS
    • var wire = require('wire');
  • Uses latest when.js 1.0.4 and aop.js 0.5.3
  • Contexts now have wire-specific methods (wire(), resolve(), and destroy()) on their prototype, and components has own properties. This provides an easy way to iterate over only components, skipping the wire-specific methods.
  • wire factory now has a waitParent option that forces the child to wait until the parent has completed before starting to wire.
    • NOTE: This is a stopgap feature for forcing wire to wait for situations that are outside of it's knowledge or control. It will likely be removed in a future version in favor of a more fine-grained approach
  • Reorganized directory structure that simplifies AMD package config. Example:
packages: [
    { name: 'wire', location: 'path/to/wire', main: 'wire' }
    // other packages...
]

New wire/dom/render plugin

  • Provides render factory that renders simple HTML templates from wire specs, for situations where you don't need a full-blown templating engine.
myNode: {
    render: {
        // HTML template. This must resolve to text, so we can use an AMD
        // text! plugin to load text
        template: { module: 'text!my/template.html' },
        // or a plain string
        // template: '<h1>${title}</h1><h2>${subtitle}</h2>',
        // or a $ref to anything that resolves to a string
        // template: { $ref: 'myTemplate' }

        // CSS can be added via any AMD css loading technique, such as the
        // css! plugin.  Again, $refs work here, too.
        css: { module: 'css!my/layout.css' },

        // The template can contain placeholders that will be replaced
        // with this data.  For example, the placeholder ${title} will be
        // replaced by the value of the title property, etc.
        replace: { title: 'Cool stuff', subtitle: 'Simple templating' }
        // The data can be any standard wire construct, like a create, module,
        // $ref, etc.  For example, you could take advantage of an AMD
        // i18n! plugin to inject localized strings into the template
        // replace: { module: 'i18n!my/localizedStrings' }
    }

    // See wire/dom/render insert info below
    // insert it into the dom
    insert: { at: { $ref: 'dom.first!.container' } }
}

wire/dom, wire/dojo/dom, wire/jquery/dom, wire/sizzle

  • All dom plugins have been standardized. The following features are available no matter which one you use.
  • Available resolvers: dom!, dom.all!, dom.query! (synonym for dom.all!), and dom.first!
// Get a node by id
aNodeById: { $ref: 'dom!nodeId' },

// Get a node list by query, e.g. all phone numbers for all persons
aNodeList: { $ref: 'dom.all!.person .phone' }

// Get the first node that matches a query, e.g. the first person's first phone number
theFirstNodeByQuery: { $ref: 'dom.first!.person .phone' }
  • Note that wire/dom uses the browser's native querySelectorAll and querySelector, and so only supports dom.all/query! and dom.first! in environments where querySelectorAll and querySelector are available.

  • If you need dom.all/query! and dom.first! support in older browsers, use the framework-specific dom plugin that best fits your project: wire/dojo/dom, wire/jquery/dom, wire/sizzle.

  • Adding classes to, and removing classes from <html> during wiring

// <dom-plugin> can be any of the dom plugins
{ module: '<dom-plugin>', classes: { init: 'page-initializing', ready: 'page-ready' } }
  • Injecting a reference to the dom.all/query! and dom.first! functions into components so that those components can be written to be more portable across javascript libraries/frameworks.
myComponent: {
    create: 'my/Component',
    properties: {
        // Inject a reference to a dom selector function without
        // it having to know what the underlying implementation is.  This
        // could be native querySelectorAll, dojo.query, jQuery, sizzle, etc.
        _querySelectorAll: { $ref: 'dom.all!' },

        // Works with dom! and dom.first! too
        _querySelector: { $ref: 'dom.first!' },

        _byId: { $ref: 'dom!' }
    }
}

// myComponent can now do:
var people = this._querySelectorAll('.person');

var firstPerson = this._querySelector('.person');

var personById = this._byId('Bob');
  • All dom plugins provide an insert facet that allows inserting nodes into the dom. Combine with wire/dom/render for templating directly from wire specs.
myNode: {
    // Create a node using wire/dom/render.  See above.
    render: {
        // ...
    }

    // Insert into the DOM.  The format is:
    // position: refNode
    // position can be "at", "first", "last", "before", or "after"
    // refNode can be a $ref to any other node
    insert: {
        // "at" inserts myNode as the only child, removing any existing children
        // Any dom $ref will work here, as long as it resolves to a single node.
        at: { $ref: 'dom!anotherNodeId' }

        // Other examples:
        // at: { $ref: 'dom.first!.container' }
        // at: { $ref: 'anotherNode' }

        // Insert myNode as first child of anotherNode
        // first: { $ref: 'anotherNode' }

        // Or as the last child
        // last: { $ref: 'anotherNode' }

        // Before anotherNode (i.e. previous sibling)
        // before: { $ref: 'anotherNode' }

        // After anotherNode (i.e. next sibling)
        // after: { $ref: 'anotherNode' }
    }
}

wire/aop

  • Easy single advices: before, on, after, afterReturning, afterThrowing
// Include the wire/aop plugin
plugins: [
    { module: 'wire/aop' },
    // other plugins ...
],

component1: {
    create: //...
    before: {
        // This will call component2's doSomethingBefore method
        // before component1's doSomething method
        doSomething: 'component2.doSomethingBefore'

        // Can add multiple methods here
        doSomethingElse: 'component2.doSomethingElseBefore'
    }

    // Similarly for other advice types
    afterReturning: {
        // component2.doSomethingAfterReturning will be invoked after
        // component1.doSomething returns (but not if it throws, see
        // afterThrowing below)
        doSomething: 'component2.doSomethingAfterReturning'
    },

    afterThrowing: {
        // component2.handleError will be invoked after component1.doSomething,
        // but only if it throws.
        doSomething: 'component2.handleError'
    },

    after: {
        // component2.alwaysDoSomethingAfter will be invoked after
        // component1.doSomething regardless of whether it returns normally
        // or throw.
        doSomething: 'component2.alwaysDoSomethingAfter'
    }
}
  • Meant for simple, single advices. More complex aspects, advice, or connections can still use: * wire/aop's aspect weaving * wire/connect * wire/dojo/events

  • AOP on promises via single advice types: afterResolving, afterRejecting, and afterPromise (a.k.a. "always")

// Include the wire/aop plugin
plugins: [
    { module: 'wire/aop' },
    // other plugins ...
],

component1: {
    create: //...
    afterResolving: {
        // This will call component2.doSomethingAfterResolving when
        // the promise returned by component1.doSomethingAsync resolves
        doSomethingAsync: 'component2.doSomethingAfterResolving'

        // Can add multiple methods here
        doSomethingElseAsync: 'component2.doSomethingElseAfterResolving'
    }

    // Similarly for afterRejecting
    afterRejecting: {
        // component2.doSomethingAfterRejecting will be invoked when
        // the promise returned by component1.doSomethingAsync rejects
        doSomethingAsync: 'component2.doSomethingAfterRejecting'
    },

    afterPromise: {
        // component2.doSomethingAfterRejecting will be invoked when
        // the promise returned by component1.doSomethingAsync either
        // resolves or rejects
        doSomethingAsync: 'component2.doSomethingAfterRejecting'
    }
}

wire/dojo/store

  • The resource! resolver allows specifying the store's idProperty for data sources that don't use id. This can be combined with any of the existing options, such as query, get, and wait.
// For example, if we have a data source uses 'name' as the primary key:
myStore: { $ref: 'resource!url/to/data/endpoint', idProperty: 'name' }

wire/debug

  • Improved output on wiring time-out, lists components and their current lifecycles state.
  • Improved stack traces
Clone this wiki locally