IMPORTANT: Did you click the button yet? =). All the editors live compile OJ. Click stuff, and change the code to see what happens!
The benefit is that OJ objects have no dependencies. There is no need to read the docs to be sure the HTML is correct, or see if the CSS is included. Everything just works.
Allow me to demonstrate: In this example, the oj.Button generates its own
oj.js are the built-in objects that are the basic building blocks of the web. These include creation and manipulation of the common
<select> and <option>
<ol> and <li>
<tbody>, and more.
Once you are comfortable using those, take a look at the objects that come with OJ plugins. The whole point of OJ is to make creating these objects as easy as possible
(Check out createType if you want to learn more about how they are made).
Head to the download page, and get going by downloading
oj.js and any of the plugins currently available.
For inspiration, take a look at some example projects that use OJ client-side or on the command-line.
Yes, jQuery 2.0 is a required dependency of OJ. This is how OJ supports event binding and direct DOM manipulation as objects change. Including this dependency took some soul searching, but OJ lives and breaths DOM creation and manipulation, and that is what jQuery does best.
Let's start from the beginning and see how OJ objects are made.
<tag> has an analogous tag function by the same name. For example,
Attributes are created by passing objects as arguments. This example defines an
href attribute on an anchor tag:
Order doesn't matter for attributes; add as many as you need, and the attribute objects will be unioned. For example, this
<div> has both an
id and an inline
To make life easier, style attributes can be set with
camelCase in addition to
Like tag functions, CSS is defined by its own function:
oj.css. It accepts an object of objects:
css function fully supports selectors with
@media queries, and nested definitions with
&. Here is an example with classes and a nested hover selector:
The class attribute is abbreviated as
Nesting tags can be done a couple ways. The most powerful is to use a function:
At first, the function notation seems a little verbose--but it's worth it because it allows structure to be created through code. Here is the same structure generated with a for loop:
Just to show the power, here is FizzBuzz =):
OJ tag functions have built-in support for jQuery events. If any event is passed as an attribute it will be automatically bound. Here, the
oj.button tag function binds
The supported list of jQuery events are:
Here is an example of
In addition OJ supports an
insert event. It is specified the same way as the jQuery events above and triggers when a tag element is inserted in the page.
This example shows an element triggering a fade-in animation when
insert is detected:
Just to be clear
insert doesn't use the deprecated DOMNodeInserted or any of the clever hacks that have emerged using CSS animation. Instead, OJ has full control over DOM element insertion so it can call events at the right time without special magic.
oj.button is the tag function but
oj.Button is the Type. The biggest difference is that objects remember their dom element so they can change themselves or even remove themselves from the page.
For example this BulletList instance can edit itself once inserted.
Notice that these objects don't use new. One of OJ's goals was to make Objects that can be used exactly like tag functions--so using div feels just the same as using a YouTubeVideo!
Using 'new' has a special effect in OJ: it creates an element without emitting it--that is, without immediately adding it to the DOM. Once you're ready to inset the element, just call 'emit' and it'll appear!
In OJ, partials are just functions. Let's create a function that makes twitter links:
Just like partials, templates are also functions in OJ. The difference is that partials create parts of websites and templates create basic structure to fill in the rest.
Lets create a template function that renders a header and takes the body and title as an argument:
In the MVC sense, OJ is entirely focused on creating Views and nothing else. It doesn't create Models. It doesn't create Controllers or Routing, or help with Page Navigation or Server Syncing. Instead it tries to do only one thing well: make awesome View objects.
That said, a good View should update from Models and vice versa. OJ supports two-way model binding to Backbone models by default. It depends on nothing other then on-off-trigger event syntax, so creating adapters to bind to other model systems should be straightforward.
There are three kinds of model binding supported by OJ: ModelKeyView, ModelView, and CollectionView. The first is used by form elements to bind to a part of a model, the second binds to an entire model, and the last binds to a collection of models.
Here we use ModelKeyView binding to link several controls together to the key of
name. Changing one will change the model, which will then trigger a change in the rest:
Similarly to Model Binding by default OJ understands binding to Backbone Collections. In this example, let's render a List from a collection of users:
Included in OJ is a sophisticated type system inspired by CoffeeScript. This lets you create types with:
That said, OJ types have two big differences from CoffeeScript types:
OJ types directly support first-class properties. So if you choose, you can define properties with get / set methods to better abstract your data access.
As an example of this powerful type system, let's create a Rectangle type that has properties
height, with a readonly first-class property
In this example a new view is created called
OrangeButton. This view contains default styling with CSS, and editing the
label property will change its text.
(Clearly this example is a bit contrived, but it does show how createType unifies HTML, CSS, and JS into a new View Object).