Here's a short tour of Infusion, based on presentations we've given about it. This tour is in point form, and designed to give you a few of the salient details about each major feature of Infusion, as well as linking you to more information.

What is Infusion?

What Motivated Infusion?

  • Community source projects struggle to build successful user interfaces
  • Our communities have a problem sharing scopes and technologies
  • This is both a technical or a social problem
  • Fluid is about stepping back, and trying to assure common some compatible approaches, at a deeper level

Goals of Infusion

  • Build an architecture to support user interfaces that can be shared and adapted.
  • Develop tools that support the inclusive design process
  • Give users tools to personalize their environment

You Can't Bottle Design

Infusion the Product

Infusion At The High Level

Low-level Technical Goals

Components in Action


Component Families

Infusion's Framework

Value of the Framework

Where does Infusion Fit?

Goals and Features

Change markup without breaking code

DOM Binder

Customize components

Declarative options

Inject custom behaviour into components

Events, Subcomponents

Decouple presentation from model logic


Easily testable

Events, Views, Subcomponents

Make accessibility easier

jquery.keyboard-a11y, ui.core

Stable and secure JavaScript objects


Open, transparent, extensible architecture

ChangeApplier, Events


JavaScript Pitfalls

Namespacing, privacy and versioning

var fluid_0_6 = fluid_0_6 || {};
var fluid = fluid || fluid_0_6;

(function ($, fluid) {

    // Code goes here.

})(jQuery, fluid_0_6);


Putting It All Together

fluid_0_6 = fluid_0_6 || {};
(function ($, fluid) {
    fluid.uiOptions = function (container, options) {
        var that = fluid.initView("fluid.uiOptions", container, options);
        that.save = function () {
        that.refreshView = function () {
        return that;   
})(jQuery, fluid_0_6);


What's a Component?

Component Contract

     * Instantiates a new Uploader component.
     * @param {Object} container the DOM element containing the Uploader markup
     * @param {Object} options configuration options for the component.
    fluid.uploader = function (container, options) { ... }

Declarative Configuration

Customizing Components

What Can Be Configured?

Example: Reorderer

    fluid.defaults("fluid.reorderer", {
        instructionMessageId: "message-bundle:",
        styles: {
            defaultStyle: "orderable-default",
            selected: "orderable-selected",
            dragging: "orderable-dragging",
            mouseDrag: "orderable-dragging",
            hover: "orderable-hover",
            dropMarker: "orderable-drop-marker",
            avatar: "orderable-avatar"
        selectors: {
            dropWarning: ".drop-warning",
            movables: ".movables",
            grabHandle: "",
            stylisticOffset: ""
        avatarCreator: defaultAvatarCreator,
        keysets: fluid.reorderer.defaultKeysets,
        layoutHandler: "fluid.listLayoutHandler",
        events: {
            onShowKeyboardDropWarning: null,
            onSelect: null,
            onBeginMove: "preventable",
            onMove: null,
            afterMove: null,
            onHover: null
        mergePolicy: {
            keysets: "replace",
            "selectors.selectables": "selectors.movables",
            "selectors.dropTargets": "selectors.movables"

DOM Binder

Decoupling Code From Markup

We'll take anything

Declaring interesting things

selectors: {
    fileQueue: ".fluid-uploader-queue",
    browseButton: ".fluid-uploader-browse",
    uploadButton: ".fluid-uploader-upload",
    resumeButton: ".fluid-uploader-resume",
    pauseButton: ".fluid-uploader-pause",
    totalFileProgressBar: ".fluid-scrollertable-foot",
    stateDisplay: "div:first"


that.events.onFileSuccess.addListener(function (file) {
    var row = rowForFile(that, file);
    that.locate("removeButton", row).unbind("click");
    that.locate("removeButton", row).tabindex(-1);
    changeRowState(row, that.options.styles.uploaded);


Managing the presentation layer

View Contract

Becoming A View

    fluid.fileQueueView = function (container, events, parentContainer,
                                    uploadManager, options) {
        var that = fluid.initView("fluid.fileQueueView", container, options);


About the events system

Declaring events

     events: {
            onShowKeyboardDropWarning: null,
            onSelect: null,
            onBeginMove: "preventable",
            onMove: null,
            afterMove: null,
            onHover: null

Types of event

Listening For Events

listeners: {
     afterFinishEdit: function (newValue, oldValue) {
        // Save the data to the server
     modelChanged: function (newValue, oldValue, that) {
         // Update state


Subcomponents Express Dependencies Between Components

Configuring a Subcomponent

var myUploader = fluid.uploader(".fluid-uploader", {
    uploadManager: {
         type: "fluid.gearsUploadManager",
         options: {
             uploadUrl: "../uploads",
              fileTypes: ["img/jpg", "img/gif", "img/png"]

Instantiating Subcomponents

var setupUploader = function (that) {
    // Instantiate the upload manager and file queue view, 
    // passing them smaller chunks of the overall options for the uploader.
    that.uploadManager = fluid.initSubcomponent(that, "uploadManager",   
                                           [that.events, fluid.COMPONENT_OPTIONS]);

    that.fileQueueView = fluid.initSubcomponent(that, "fileQueueView", 

The meaning of Subcomponents

The Renderer

The Fluid Renderer

A Fluid Template

 <div id="testDataRoot">
    <div id="parseTest1">
        <tr id="table-header"><th>Count</th><th>Name</th>
                    <th class="column-header">1</th><th>Median ave</th></tr>

A Component Tree

    var tree = {
      "header:" : [1, 2, 3, 4, 5]

    var templates = fluid.selfRender($("#table-header"), tree, 
        { cutpoints: [{selector: "th.column-header", id: "header:"}]

No Black Boxes

The ChangeApplier

Familiar GUI Pain Point

ChangeApplier Features


ChangeApplier Illustrated

In Summary