JoJavaScript Framework for HTML5

About

Jo is a lightweight JavaScript framework designed for HTML5 apps.

jo does

jo doesn't

Author

Dave Balmer: davebalmer.wordpress.com, follow @balmer on Twitter, or email dbalmerjr@gmail.com

Downloads

Version 0.4.1 is the latest stable release, check the Release Notes for details.

Available from GitHub as a git repo or a zip file.

Philosophy

If you want to jam an existing web page into an application framework, jo probably isn't for you. jo is designed to create applications. While it will play nicely with a mixture of new and old web development techniques, it uses HTML5 as a development stack and does not require direct DOM manipulation.

Application Stack

JavaScript Application
joPhoneGap (optional)
joViewjoEventjoDataSource
CSS3CanvasDOMEventsXHRSQLiteDevice OS

Documentation

All documentation for the framework is based on Markdown and provides a simple, natural and flexible way to document the code. This simple set of perl scripts has become its own tool called joDoc.


Summary

Jo is a JavaScript framework for HTML5 capable browsers and devices. It was originally designed to work on mobile platforms as a GUI and light data layer on top of PhoneGap. Since its creation, Jo has also been tested successfully as a lightweight framework for mobile browsers, newer desktop browsers, and even Dashboard widgets.

Building

It's pretty easy to build on your own, but to get the most out of it you'll want to get a minifier like jsmin or the YUI Compressor. Minified and gzipped, Jo weighs in around 9K with no other JavaScript library dependancies.

Mac OSX, Linux & BSD

cd jo
./build

Windows

cd jo
build.bat

If you're not up for building the library yourself, there's nothing wrong with downloading the latest stable release, all built and ready to plug in from: jo/downloads">GitHub Downloads

Directory Map

Important files in the directory tree are:

Quick Start

index.html

The complete jo library is small, so in most cases you'll just want to pull it all in, like this:

<html>
<head>
    <link rel="stylesheet" type="text/css" href="css/aluminum.css">
    <link rel="stylesheet" type="text/css" href="css/webkit.css">
    <!-- <link rel="stylesheet" type="text/css" href="css/webos.css"> -->
    <!-- <link rel="stylesheet" type="text/css" href="css/chrome.css"> -->
</head>
<body>

<!-- any static page content goes here -->

<!-- load jo library -->
<script src="jo_min.js"></script>

<!-- any application JavaScript files go here -->
<script src="hello.js"></script>

</body>
</html>

If you're using jo to create all the UI for your application, you won't need any content or tags in your index.html file.

Since the framework is highly dependent on CSS, your mileage may vary across platforms. In particular, Internet Explorer before 9 will have limited eye candy and no animated transitions.

You can also completely skin your app with your own CSS, or augment the basic jo CSS to suit your purposes.

Since jo is geared for HTML5 applications, I recommend you develop and test your apps with Safari or Chrome before moving to mobile devices. In fact, this makes the code/test/debug cycle go very quickly.

hello.js

jo has some initialization which should only be done when your browser is ready to have its DOM fiddled with, so you may want to wrap your code in a function that's called when your page loads, or your device signals that your app is ready to go.

The simplest UI would be something like:

// initialize jo
jo.load();

// define a wrapper for document.body
var scn = new joScreen();

// setup your UI
scn.alert("Hello, Jo!", "This is a simple alert.");

Something more interesting would look like:

// initialize jo
jo.load();

// setup a stack and screen
var stack = new joStackScroller();
var scn = new joScreen(stack);

// create our view card
var card = new joCard([
    new joTitle("Hello"),
    new joCaption("Hello World!"),
    new joDivider(),
    new joButton("OK").selectEvent.subscribe(function() {
        stack.hide();
    })
]);

// put the card on our view stack
stack.push(card);

Notice above that jo supports "chaining", meaning you can make successive calls inline to a given object (see the joButton line above for an example).

Of course, it is recommended you use more robust OOP coding patterns to make a proper application. While there's nothing illegal about putting everything in global space in a single JavaScript file, but if you're looking to build something big or more easy to maintain, I recommend you check out "JavaScript: the Good Parts" by Doug Crockford (O'Reilly Press).

Class Hierarchy

The following is a class hierarchy for the framework, organized by general function.

User Interface

Data

Events

Processing

Utility

Debugging

Application

Class Patterns

Instead of a complex set of pseudo-class methods, jo uses a few simple coding patterns: singleton, base class, subclass, and module. All of these are found in modern JavaScript implementations. A good reference to have while developing your app is JavaScript: The Good Parts by Douglas Crockford (O'Reilly Press)

Singleton

The pattern for creating a singleton is really just an object literal. For example:

MyApp = {
    init: function() {
        // some sort of initialization code goes here
    },

    mymethod: function() {
        // some custom method
    },

    // properties can also be declared inline
    myproperty: true
};

Base Class

Prototypal inheritance does well with "fat" base classes which do most everything you anticipate a subclass would want. This type of inheritance benefits greatly from shallow/wide prototypes for a number of reasons. A base class looks something like:

MyClass = function(x) {
    // constructor
    this.x = x;
};
MyClass.prototype = {
    mymethod: function() {
        // some method
    },

    myothermethod: function() {
        // another method
    }
};

Subclass

Strictly speaking, JavaScript doesn't have classes and subclasses. But it does know how to make copies of an object, and keeps track of "inheritance" through its prototype chain. A subclass in jo looks something like this:

MySubclass = function(x, y) {
    //constructor
    this.y = y;

    // call to our "superclass" constructor
    MyClass.call(this, x);
};
MySubclass.extend(MyClass, {
    mynewmethod: function() {
        // this subclass has its own new method
    }
});

A couple things to note. jo augments the Function object in JavaScript to have an extend() method. This is just some syntactic sugar which makes it easier to extend an object, giving us a pseudo-subclass with syntax that's not too awkward. The advantage here is we're using JavaScript's natural object model behind the scenes. We're not creating any extra fluff, just automating the process somewhat.

Note that objects created using prototypal inheritance also get the benefit of using JavaScript's built-in instanceof operator which works up the prototype chain. For example:

// given this new subclass
var someobject = new MySubclass(1, 2);

// both of these tests are "true"
joLog(someobject instanceof MySubclass);
joLog(someobject instanceof MyClass);

You may also notice a "call to super" comment in our MySubclass constructor. This is a convenient coding pattern which makes it easier to create subclasses, with methods that augment the superclass' functionality. Like this:

MySubclass.extend(MyClass, {
    mynewmethod: function() {
        // this subclass has its own new method
    },

    mymethod: function() {
        this.x += 5;

        // call super's mymethod() with this object's context
        MyClass.prototype.mymethod.apply(this, arguments);
    }
});

It may look slightly odd at first, but this approach gives us more of the benefits of subclassing you'd find in other languages without having to step outside of JavaScript's natural object model.

Data Driven Controls

Jo isn't just a pretty face with some DOM fiddling and standard DOM events. It also has a versatile application-level event model (see Observer Pattern). In addition, Jo has a simple event-driven layer for asynchronous data storage and retrieval using extensions of joDataSource.

As a matter of convenience, all children of joControl (which includes most list or widget-driven UI elements) can be easily tied to data.

The most convenient for most purposes is joRecord. This class wraps a property list, which can be used to save or load using whatever your application requires. In addition, this class allows you to link a UI control to the data in one quick action.

For more on this, check out the joRecord docs which include an example or two.

joDoc

joDoc is a plain text code documentation scheme for JavaScript. It was created out of frustration felt working with various documentation systems available.

Source code formatting

/**
    myClass
    =======

    This is my class. It rocks, and this is its _description_, which also
    rocks.

    Extends
    -------
    - someOtherClass

    Methods
    -------
    - setName(name)
      Where `name` is a `String`.

    Use
    ---
        // here is some sample code which shows how to use this class
        var x = new myClass(name);

    > Note: use of the `name` reserved word is probaly a bad idea.
*/

Comment placement

You can put your comments for your code either:

  1. in your source code (anywhere and in as many pieces as you want) denoted with /** ... */ multiline-comment blocks

  2. separate markdown (*.mdown) files, probably (tho not necessarily) named to match your JavaScript files

Can't get much more flexible than that.

Comparison

JavaScript is an extremely expressive language which is often difficult to describe in terms of meta data and fields. Often, important information that needs to be documented just doesn't fit into a neat, tidy spot.

jsdoc

jsdoc in its various incarnations and some of its spawn like yuidoc take the approach that "what is good for Java is good for JavaScript". All these flavors are based on javadoc formatting, and have been in use for some time.

Aside from the regimented markup being a bit odd to read (admit it, even Java developers don't love it), it suffers from an inflexibility with regard to all the coding patterns available with JavaScript. Basically, it fails due for the same reason that all JavaScript libraries which attempt to subvert JavaScript's natural object model fail. These solutions, while influential in the idea that some form consistent coding approach could help us make better code, are not in the spirit of embracing JavaScript.

Why then do so many developers continue to use a documentation tool which was born of the same well-meaning yet misguided logic of "let's pretend JavaScript is Java"?

Natural Docs

Excellent effort, but complex to set up and also tries to make a regimented system for documenting source code. It is extendable, but again, we have a documentation solution which is trying to force JavaScript into a more limited set of features.


Observer Pattern

jo uses a variant on this OOP pattern quite extensively for notifications between objects.

When you think about JavaScript, most of the interesting things that happen are asynchronous: XHR calls, loading scripts, accessing at database, making device-specific system calls; even user interactions are all asynchronous in nature.

Instead of trying to hide from this often complex-looking stuff, jo embraces it and provides a scheme to wrap all these different use cases in a consistent interface using joSubject.

PhoneGap

This excellent, lightweight mobile application library by Nitobi neutralizes device differences and provides a stable webkit application shell. Jo is designed to work with PhoneGap out of the box, and it's highly recommended.

LawnChair

Another tool by Nitobi, LawnChair is a client-side storage solution which stores JSON objects (in SQLite or whatever the device supports). It looks promising, and the jo core has a special subclass of joDataSource called joLawn which folds Nitobi's library into the Jo event model.

Release Notes

Jo 0.4.1

Jo 0.4.0

Jo 0.3.0

CSS Skinning

jo makes extensive use of CSS for its widgets. As a result, it's extremely easy to skin and adapt your user interface for different devices. The project will have a community-driven theme collection to help reduce development time by choosing a stylesheet that most closely matches your application (or device native controls).

HTML Tags

One feature jo exploits is the fact that modern browser engines treat unknown tags as -- tags. So instead of mucking up your application's DOM and CSS space with a horde of div tags with different CSS classes, it uses namespaced tags which are outside of your document's typical CSS name space (except body).

Special Tag Examples

<jocard>
    <jotitle>My title</jotitle>
    <jogroup>
        <jolabel>Username</jolabel>
        <input type="text">
        <jodivider></jodivider>
        <jobutton>Save</jobutton>
    </jogroup>
</jocard>

One side benefit of this is that it is possible to load styled HTML content from another source and not have that content's CSS corrupt your application's user interface.

Bottom line here is the special UI controls you add with Jo can coexist with your standard HTML content-driven tags without undue CSS headaches.

See joInterface and joView for more uses of direct HTML and DOM nodes which are common for all UI elements.


jo

Singleton which the framework uses to store global infomation. It also is responsible for initializing the rest of the framework, detecting your environment, and notifying your application when jo is ready to use.

Methods

Events

Function

jo extends the Function object to add a few goodies which augment JavaScript in a farily non-intrusive way.

Methods

HTMLElement

This is a standard DOM element for JavaScript. Most of the jo views, continers and controls deal with these so your application doesn't need to.

Methods

Not a complete list by any means, but the useful ones for our purposes are:

Properties

jo uses these properties quite a bit:

joCache

A singleton which makes it easy to setup deferred object creation and cached results. This is a performance menchanism initially designed for UI views, but could be extended to handle data requests and other object types.

Methods

Use

Defining a view for on-demand use:

joCache.set("home", function() {
    return new joCard([
        new joTitle("Home"),
        new joMenu([
            "Top Stories",
            "Latest News",
            "Old News",
            "No News"
        ])
    ]);
});

Displaying a view later:

mystack.push(joCache.get("home"));

// the first call to get() will instantiate
// the view, subsequent calls will return the
// view that was created the first time

// you can pass parameters into your view factory
var x = joCache.get("home", "My Title");

// note that if you want to use joCache to cache
// views which differ based on parameters passed in,
// you probably want your own caching mechanism instead.

joChain

Class which strings asyncronous calls together.

In serious need of rework; doesn't meet original goal of sequencing these calls. This class might also become deprecated.

Methods

joClipboard

Singleton which abstracts the system clipboard. Note that this is a platform dependant interface. By default, the class will simply store the contents in a special joPreference named "joClipboardData" to provide clipboard capabilities within your app.

Even if you think you're just going to use the default behavior, it is recommended that you never manipulate the "joClipboardData" preference directly.

Methods

Note: this is not working yet, steer clear (or contribute some working code!)

joDOM

Singleton with utility methods for manipulating DOM elements.

Methods

joEvent

Singleton with DOM event model utility methods. Ideally, application-level code shouldn't have to use this, but library code does.

Methods

joLog

Wrapper for console.log() (or whatever device-specific logging you have). Also could be extended to send log information to a RESTful service as well, handy for devices which don't have decent logging abilities.

Use

It's an all-in-one utility that's smart enough to ferret out whatever you throw at it and display it in the console.

joLog("x=", x, "listdata=", listdata);

Basically, fill it up with strings, variables, objects, arrays and the function will produce a string version of each argument (where appropriate; browser debuggers tend to display objects nicely) in the same console line. Simple, effective, easy to use.

joSubject

Class for custom events using the Observer Pattern. This is designed to be used inside a subject to create events which observers can subscribe to. Unlike the classic observer pattern, a subject can fire more than one event when called, and each observer gets data from the subject. This is very similar to YUI 2.x event model.

You can also "lock" the notification chain by using the capture() method, which tells the event to only notify the most recent subscriber (observer) which requested to capture the event exclusively.

Methods

Use

In the subject (or "publisher") object

// inside the Subject, we setup an event observers can subscribe to
this.changeEvent = new joSubject(this);

// to fire the event inside the Subject
this.changeEvent.fire(somedata);

In the observer (or "subscriber") object

// simple case, using Function.bind()
somesubject.changeEvent.subscribe(this.mymethod.bind());

// explicit context (this)
somesubject.changeEvent.subscribe(this.mymethod, this);

// optional data which gets passed with the event fires
somesubject.changeEvent.subscribe(this.mymethod, this, "hello");

This is a very flexible way to handle messages between objects. Each subject may have multiple events which any number of observer objects can subscribe to.

joTime

Time utility functions. More will be added, but only as needed by the framework. There are entire libraries dedicated to extensive datetime manipulation, and Jo doesn't pretend to be one of them.

Methods

Constants

Use

var twoHoursLater = joTime.timestamp() + (HOUR * 2);

joDefer

Utility function which calls a given method within a given context after n milliseconds with optional static data.

Use

joDefer(Function, context, delay, data);

Note that delay defaults to 100ms if not specified, and data is optional.

joYield

Deprecated, use joDefer instead.


joDatabase

Wrapper class for WebKit SQLite database.

Methods

joDataSource

Wraps data acquisition in an event-driven class. Objects can subscribe to the changeEvent to update their own data.

This base class can be used as-is as a data dispatcher, but is designed to be extended to handle asynchronous file or SQL queries.

Methods

Events

Under construction, use with care.

joFileSource

A special joDataSource which loads and handles a file. This class wraps joFile.

Extends

joFile

A utility method which uses XMLHttpRequest to load a text-like file from either a remote server or a local file.

Note that some browsers and mobile devices will not allow you to load from just any URL, and some will restrict use with local files especially (I'm looking at you, FireFox).

If your aim is to load JavaScript-like data (also, JSON), you may want to look at joScript instead, which uses script tags to accomplish the job.

Calling

joFile(url, call, context, timeout)

Where

Use

// simple call with a global callback
var x = joFile("about.html", App.loadAbout);

// an inline function
var y = joFile("http://joapp.com/index.html", function(data, error) {
    if (error) {
        console.log("error loading file");
        return;
    }

    console.log(data);
});

joPreference

A class used for storing and retrieving preferences in your application.

The interface for this is changing. joPreference will become a specialized application-level extension of joRecord in the near future. Until then, you should use joRecord to achieve this use-case.

Extends

joRecord

An event-driven wrapper for an object and its properties. Useful as a data interface for forms and other collections of UI controls.

Extends

Methods

Use

// setup a joRecord
var r = new joRecord({
    user: "Jo",
    password: "1234",
    active: true
});

// bind it to some fields
var x = new joGroup([
    new joLabel("User"),
    new joInput(r.link("user")),
    new joLabel("Password"),
    new joPasswordInput(r.link("password")),
    new joFlexBox([
        new joLabel("Active"),
        new joToggle(r.link("active"))
    ])
]);

And if you want the data to be persistent, or interact with some cloud service, you'll need to do something like this:

// make something happen to load the data
r.load = function() {
    // some AJAX or SQL call here
};

// make something happen to save the data
r.save = function() {
    // some AJAX or SQL call here
};

You could also make your own subclass of joRecord with your own save and load methods using extend() like this:

var preferences = function() {
    // call to the superclass constructor
    joRecord.apply(this, arguments);
};
preferences.extend(joRecord, {
    save: function() {
        // do an AJAX or SQL call here
    },

    load: function() {
        // do an AJAX or SQL call here
    }
}

See Class Patterns for more details on this method of "subclassing" in JavaScript.

joProperty

Used by joRecord to provide an event-driven binding to properties. This class is instantiated by joRecord and not of much use on its own.

Extends

Use

See joRecord for examples.

joScript

Script tag loader function which can be used to dynamically load script files or make RESTful calls to many JSON services (provided they have some sort of callback ability). This is a low-level utility function.

Need a URL with some examples of this.

Calling

joScript(url, callback, context, errorcallback, errorcontext)

Returns

Calls your handler method and passes a truthy value if there was an error.

Use

joScript("myscript.js", function(error, url) {
    if (error)
        console.log("script " + url + " didn't load.");
}, this);

joSQLDataSource

SQL flavor of joDataSource which uses "HTML5" SQL found in webkit.

Methods

Events

Extends

joYQL

A joDataSource geared for YQL RESTful JSON calls. YQL is like SQL, but for cloud services. Pretty amazing stuff:

The Yahoo! Query Language is an expressive SQL-like language that lets you query, filter, and join data across Web services. With YQL, apps run faster with fewer lines of code and a smaller network footprint.

Yahoo! and other websites across the Internet make much of their structured data available to developers, primarily through Web services. To access and query these services, developers traditionally endure the pain of locating the right URLs and documentation to access and query each Web service.

With YQL, developers can access and shape data across the Internet through one simple language, eliminating the need to learn how to call different APIs.

Yahoo! Query Language Home

Use

A simple one-shot use would look like:

// setup our data source
var yql = new joYQL("select * from rss where url='http://davebalmer.wordpress.com'");

// subscribe to load events
yql.loadEvent.subscribe(function(data) {
    joLog("received data!");
});

// kick off our call
yql.exec();

A more robust example with parameters in the query could look something like this:

// quick/dirty augmentation of the setQuery method
var yql = new joYQL();
yql.setQuery = function(feed, limit) {
    this.query = "select * from rss where url='"
        + feed + "' limit " + limit
        + " | sort(field=pubDate)";
};

// we can hook up a list to display the results
var list = new joList(yql).attach(document.body);
list.formatItem = function(data, index) {
    var html = new joListItem(data.title + " (" + data.pubDate + ")", index);
};

// later, we make our call with our parameters
yql.exec("http://davebalmer.wordpress.com", 10);

Methods

Extends


joBusy

The idea here is to make a generic "spinner" control which you can overlay on other controls. It's still in flux, don't use it just yet.

Extends

Methods

joButton

Button control.

// simple invocation
var x = new joButton("Done");

// optionally pass in a CSS classname to style the button
var y = new joButton("Cancel", "cancelbutton");

// like other controls, you can pass in a joDataSource
// which could be useful, so why not
var z = new joButton(joPreference.bind("processname"));

Extends

Methods

joCaption

Basically, a paragraph of text.

Extends

joCard

Special container for card views, more of an application-level view.

Extends

Methods

joCollect

DEPRECATED use joInterface instead. This function is planned to die when jo goes beta.

joContainer

A view which is designed to contain other views and controls. Subclass to provide different layout types. A container can be used to intantiate an entire tree of controls at once, and is a very powerful UI component in jo.

Use

// plain container
var x = new joContainer();

// HTML or plain text
var y = new joContainer("Some HTML");

// HTMLElement
var w = new joContainer(joDOM.get("mydiv"));

// nested inline structure with text, HTML, joViews or HTMLElements
var z = new joContainer([
    new joTitle("Hello"),
    new joList([
        "Red",
        "Green",
        "Blue"
    ]),
    new joFieldset([
        "Name", new joInput(joPreference.bind("name")),
        "Phone", new joInput(joPreference.bind("phone"))
    ]),
    new joButton("Done")
]);

// set an optional title string, used with joNavbar
z.setTitle("About");

Extends

Events

Methods

joControl

Interactive, data-driven control class which may be bound to a joDataSource, can receive focus events, and can fire off important events which other objects can listen for and react to.

Extends

Events

Methods

See Also

joDialog

This is a higher level container that wraps a joPopup with a joShim.

joDivider

Simple visual divider.

Extends

joExpando

A compound UI element which allows the user to hide/show its contents. The first object passed in becomes the trigger control for the container, and the second becomes the container which expands and contracts. This action is controlled in the CSS by the presence of the "open" class.

Use

This is a typical pattern:

// normal look & feel
var x = new joExpando([
    new joExpandoTitle("Options"),
    new joExpandoContent([
        new joLabel("Label"),
        new joInput("sample field")
    ])
]);

Note that joExpando doesn't care what sort of controls you tell it to use. In this example, we have a joButton that hides and shows a DOM element:

// you can use other things though
var y = new joExpando([
    new joButton("More..."),
    joDOM.get("someelementid")
]);

Extends

Methods

Events

joExpandoContent

New widget to contain expando contents. This is normally used with joExpando, but not required.

Extends

joExpandoTitle

Common UI element to trigger a joExpando. Contains a stylable arrow image which indicates open/closed state.

Extends

Use

See joExpando use.

joFlexrow

Uses the flexible box model in CSS to stretch elements evenly across a row.

Use

// a simple row of things
var x = new joFlexrow([
    new joButton("OK"),
    new joButton("Cancel")
]);

// making a control stretch
var y = new joFlexrow(new joInput("Bob"));

Extends

joFlexcol

Uses the flexible box model in CSS to stretch elements evenly across a column.

Use

// fill up a vertical space with things
var x = new joFlexcol([
    new joNavbar(),
    new joStackScroller()
]);

Extends

joFocus

Singleton which manages global input and event focus among joControl objects.

Methods

joFooter

Attempt to make a filler object which pushed subsequent joView objects further down in the container if possible (to attach its contents to the bottom of a card, for eaxmple).

This behavior requires a working box model to attach properly to the bottom of your container view.

Extends

joGesture

Experimental global gesture handler (keyboard, dpad, back, home, flick?). This needs a lot more fleshing out, so it's not (quite) ready for general consumption.

Events

Note that the events setup here are for the browser or webOS. The setEvents method most likely needs to change based on which OS you're running, although looking more deeply into PhoneGap event layer.

joGroup

Group of controls, purely visual.

Extends

joHTML

A simple HTML content control. One interesting feature is it intercepts all <a> tag interactions and fires off a selectEvent with the contents of the tag's href property.

This is a relatively lightweight approach to displaying arbitrary HTML data inside your app, but it is not recommended you allow external JavaScript inside the HTML chunk in question.

Also keep in mind that your app document already has <html>, <head> and <body> tags. When you use the setData() method on this view, make sure you don't use any of these tags to avoid weird issues.

In a future version, it is feasible to load in stylesheets references in the HTML document's <head> section. For now, that entire can of worms will be avoided, and it's left up to you, the developer, to load in any required CSS files using joDOM.loadCSS().

Extends

Use

// simple html string
var x = new joHTML("<h1>Hello World!</h1><p>Sup?</p>");

// use a joDataSource like a file loader
var y = new joHTML(new joFileSource("sample.html"));

joInput

Single-line text input control. When you instantiate or use setData(), you can either pass in an initial value or a reference to a joDataSource object which it, like other joControl instances, will bind to.

Use

// simple value, simple field
var x = new joInput(a);

// set up a simple joRecord instance with some default data
var pref = new joRecord({
    username: "Bob",
    password: "password"
});

// attach the value to a data structure property
var y = new joInput(pref.link("username"));

Extends

Methods

joInterface

EXPERIMENTAL

This utility method is experimental! Be very careful with it. NOTE that for now, this class requires you to remove whitespace in your HTML. If you don't know a good approach offhand to do that, then this thing probably isn't ready for you yet.

This class parses the DOM tree for a given element and attempts to attach appropriate joView subclasses to all the relevant HTML nodes. Returns an object with references to all elements with the id attribute set. This method helps turn HTML into HTML + JavaScript.

Use

// an HTML element by its ID
var x = new joInterface("someid");

// a known HTML element
var y = new joInterface(someHTMLElement);

// the entire document body (careful, see below)
var z = new joInterface();

Returns

A new object with a property for each element ID found. For example:

<!-- this DOM structure -->
<jocard id="login">
    <jotitle>Login</jotitle>
    <jogroup>
        <jolabel>Username</jolabel>
        <input id="username" type="text">
        <jolabel>Password</jolabel>
        <input id="password" type="password">
    </jogroup>
    <jobutton id="loginbutton">Login</jobutton>
</jocard>

Parsed with this JavaScript:

// walk the DOM, find nodes, create controls for each
var x = new joInterface("login");

Produces these properties:

This in essence flattens your UI to a single set of properties you can use to access the controls that were created from your DOM structure.

In addition, any unrecognized tags which have an id attribute set will also be loaded into the properties.

Parsing complex trees

Yes, you can make a joInterface that encapsulates your entire UI with HTML. This is not recommended for larger or more complex applications, some reasons being:

If you really want to use HTML as your primary means of defining your UI, you're better off putting your major UI components inside of a <div> (or other tag) with display: none set in its CSS property. Like this:

<!-- in your CSS: .hideui { display: none } -->
<div class="hideui" id="cards">
    <jocard id="about">
        <jotitle>About this app</jotitle>
        <johtml>
            This is my app, it is cool.
        </johtml>
        <jobutton>Done</jobutton>
    </jocard>
    <jocard id="login">
        ... etc ...
    </jocard>
</div>

Then in your JavaScript:

// pull in all our card views from HTML
var cards = new joInterface("cards");

Definitely use this class judiciously or you'll end up doing a lot of recatoring as your application grows.

Flattening UI widget references

This is both good and bad, depending on your coding style and complexity of your app. Because all the tags with an ID attribute (regardless of where they are in your tag tree) get a single corresponding property reference, things could get very messy in larger apps. Again, be smart.

joLabel

Label view, purely a visual presentation. Usually placed in front of input fields and other controls.

Extends

joList

A widget class which expects an array of any data type and renders the array as a list. The list control handles DOM interactions with only a single touch event to determine which item was selected.

Extends

Events

Methods

joMenu

Simple menu class with optional icons.

Extends

Methods

Use

// simple inline menu; you can always setup the menu items (or change
// them) but using the `setData()` method, same as any joView
var menu = new joMenu([
    { title: "About" },
    { title: "Frequently Asked Questions", id: "faq" },
    { title: "Visit our website", id: "visit", icon: "images/web" }
]);

// simple inline function event handler
menu.selectEvent.subscribe(function(id) {
    switch (id) {
    case "0":
        // the "About" line; if no id, the index of the menu item is used
        stack.push(aboutCard);
        break;
    case "faq":
        stack.push(faqCard);
        break;
    case "visit":
        stack.push(visitCard);
        break;
    }
});

Advanced Use

This could actually be called "more consistent and simple" use. If your menus are static, you could always setup an id-based dispatch delegate which pushes the appropriate card based on the menu id selected.

You could use the id in conjunction with view keys you create with joCache. The handler would then be something like:

menu.selectEvent.subscribe(function(id) {
    mystack.push(joCache.get(id));
});

joNavbar

Floating navigation control. Usually tied to a joStack or joStackScroller. Will handle display of a "back" button (controllable in CSS) and show the title string of the current view in a stack (if it exists).

Use

// make a stack
var stack = new joStackScroller();

// new navbar
var x = new joNavbar();

// link to a stack
x.setStack(stack);

Methods

joBackButton

A "back" button, which can be made to be shown only in appropriate platforms (e.g. iOS, Safari, Chrome) through CSS styling.

See joNavbar for more information.

Extends

joOption

This controls lets the user select one of a few options. Basically, this is a menu with a horizontal layout (depending on your CSS).

Use

// simple set of options
var x = new joOption([
    "Red",
    "Blue",
    "Green"
]);

// set the current value
x.setValue(2);

// or, associate the value with a joRecord property
var pref = new joRecord();

var y = new joOption([
    "Orange",
    "Banana",
    "Grape",
    "Lime"
], pref.link("fruit"));

// you can even associate the list with a datasource
var fruits = new joDataSource( ... some query stuff ...);
var z = new joOption(fruits, pref.link("fruit"));

Extends

joPasswordInput

Secret data input field (e.g. displays ****** instead of secret).

Extends

Note that this requires CSS3 which is known not to be currently supported in Opera or Internet Explorer.

joPopup

A simple popup control. Pass in the UI contents as you would any other subclass of joContainer (e.g. joCard).

Methods

Extends

Events

joScreen

Abstraction layer for the device screen. Uses document.body as its DOM element and allows other controls to be nested within (usually a joStack or other high-level containers or controls).

Methods

Extends

Use

var x = new joScreen([
    new joNav(),
    new joStack(),
    new joToolbar()
]);

// show a simple alert dialog
x.alert("Hello", "This is an alert");

// a more complex alert
x.alert("Hola", "Do you like this alert?", [
    { label: "Yes", action: yesFunction, context: this },
    { label: "No", action: noFunction, context: this }
]);

// a completely custom popup
x.showPopup(myView);

Events

joScroller

A scroller container. Ultimately, mobile webkit implementations should properly support scrolling elements that have the CSS overflow property set to scroll or auto. Why don't they, anyway? Until some sanity is adopted, we need to handle this scrolling issue ourselves. joScroller expects a single child to manage scrolling for.

Use

// make a scroller and set its child later
var x = new joScroller();
x.setData(myCard);

// or define things inline, not always a good idea
var y = new joScroller(new joList(mydata));

// you can dump a big hunk of HTML in there, too
// since jo wraps strings in a container element, this works
var z = new joScroller('Some giant HTML as a string');

Extends

Methods

joSelect

Multi-select control which presents a set of options for the user to choose from.

Methods

Extends

Consumes

Properties

Use

// pass in an array of options
var x = new joSelect([ "Apples", "Oranges", "Grapes" ]);

// pass in a current value
var y = new joSelect([ "Apples", "Oranges", "Grapes" ], 2);

// respond to the change event
y.changeEvent = function(value, list) {
    console.log("Fruit: " + list.getNodeValue(value));
});

joSelectTitle

joSelect flavor of joExpandoTitle.

Extends

joSelectList

A selection list of options used by joSelect.

Extends

joShim

A simple screen dimmer. Used mostly for popups and other modal use cases.

Methods

Extends

Events

joSlider

Slider control, horizontal presentation (may be extended later to allow for vertical and x/y).

Extends

Methods

Where min/max is a number, either integer or decimal, doesn't matter. If max and min are integers, then snap defaults to 1, otherwise it is set to 0 (no snap, which allows free movement).

The optional snap value adjusts the granularuty of choices. Set to 0 for free-floating, or any other positive number. Any snap that is less than 0 or greater than the total range of possible values will be ignored.

Use

// basic slider, will allow any decimal value
// between 0 and 1, defaults to 0
var x = new joSlider();

// custom range and default value set
var y = new joSlider(0).setRange(-10, 10);

// percent slider, with 5% snap
var z = new joSlider(0).setRange(0, 100, 5);

// responding to change events
var r = new joSlider().changEvent.subscribe(function(value) {
    console.log(value);
}, this);

joSound

Play preloaded sound effects using the HTML5 Audio object. This module could be wildly different for various platforms. Be warned.

Methods

Events

joStack

A UI container which keeps an array of views which can be pushed and popped.

The DOM elements for a given view are removed from the DOM tree when popped so we keep the render tree clean.

Extends

Methods

Events

Notes

Should set classNames to new/old views to allow for CSS transitions to be set (swiping in/out, cross fading, etc). Currently, it does none of this.

Also, some weirdness with the new forward() and back() methods in conjuction with push() -- need to work on that, or just have your app rigged to pop() on back to keep the nesting simple.

joStackScroller

What happens when you mix joStack and joScroller? You get this class. Use exactly as you would joStack, only it automatically puts a scroller in the stack as needed. At some point, this might get folded into joStack, but for now it's a special class.

It also handles the scrollTo() and scrollBy() methods from joScroller.

Extends

joTabBar

Tab bar widget.

Extends

Model

Data is expected to be an array of { type: "", label: ""} objects, in the display order for the bar.

joTable

Table control, purely visual representation of tabular data (usually an array of arrays).

Use

// simple table with inline data
var x = new joTable([
    ["Nickname", "Phone", "Email"],
    ["Bob", "555-1234", "bob@bobco.not"],
    ["Jo", "555-3456", "jo@joco.not"],
    ["Jane", "555-6789", "jane@janeco.not"]
]);

// we can respond to touch events in the table
x.selectEvent.subscribe(function(index, table) {
    // get the current row and column
    joLog("Table cell clicked:", table.getRow(), table.getCol());

    // you can also get at the cell HTML element as well
    joDOM.setStyle(table.getNode(), { fontWeight: "bold" });
});

Extends

Methods

joTextarea

Multi-line text input control. When you instantiate or use setData(), you can either pass in an initial value or a reference to a joDataSource object which it, like other joControl instances, will bind to.

Basically, this is just a multi-line version of joInput.

Use

// simple multi-line field
var sample = "This is some sample text to edit.";
var x = new joTextarea(sample);

// setting the style inline using chaining
var f = new joTextarea(sample).setStyle({
    minHeight: "100px",
    maxHeight: "300px"
});

// adding a simple change event handler using chaining
var h = new joTextarea(sample).changeEvent.subscribe(function(data) {
    joLog("text area changed:", data);
});

// attach the value to a preference
var y = new joTextarea(joPreference.bind("username"));

// attach input control to a custom joDataSource
var username = new joDataSource("bob");
var z = new joTextarea(username);

Extends

joTitle

Title view, purely a visual presentation.

Extends

joToggle

Boolean widget (on or off).

Methods

You can change the labels for this control, which default to "Off" and "On".

Extends

Use

// simple
var x = new joToggle();

// with value
var y = new joToggle(true);

// with custom labels
var z = new joToggle().setLabels(["No", "Yes"]);

See Data Driven Controls for more examples.

joToolbar

Locks UI controls to the bottom of whatever you put this container into.

Extends

joView

Base class for all other views, containers, controls and other visual doo-dads.

Use

var x = new joView(data);

Where data is either a text or HTML string, an HTMLElement, or any joView object or subclass.

Methods

License

Copyright 2010 Dave Balmer, Jr. All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

  2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY DAVE BALMER, JR. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVE BALMER, JR. OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of Dave Balmer, Jr.


Index

A

B

C

D

F

H

J

L

O

P

Q

R

S