update example

This commit is contained in:
rolux 2012-05-29 12:22:06 +02:00
parent 7dd9169b3f
commit 2223064d35

View file

@ -1,3 +1,16 @@
/*
The following examples explain the common design pattern for Ox.js UI widgets:
an inheritance model that is neither classical nor prototypal, but "parasitical"
(a term coined by <a
href="http://www.crockford.com/javascript/inheritance.html">Douglas
Crockford</a>). In a nutshell, "instances" are created by augmenting other
instances, but in addition to private members (`var foo`) and public members
(`that.bar`), they can have shared private members (`self.baz`). `self` cannot
be accessed from outside, but since `self` itself is an argument of the
"constructor", an instance can inherit its parent's `self` by passing its own
`self`.
*/
'use strict'; 'use strict';
/* /*
@ -14,31 +27,31 @@ Ox.load('UI', function() {
First, lets build the most basic Box widget. A widget is a "constructor" First, lets build the most basic Box widget. A widget is a "constructor"
function that takes two (optional) arguments, `options` and `self`, and function that takes two (optional) arguments, `options` and `self`, and
returns a widget object. It's not a constructor in JavaScript terms though: returns a widget object. It's not a constructor in JavaScript terms though:
It doesn't have to be called with `new`, and doesn't return an instance of It doesn't have to be called with `new`, and doesn't return an `instanceof`
anything. It just enhances another widget object and returns it. anything. It just enhances another widget object and returns it.
*/ */
Ox.My.Box = function(options, self) { Ox.My.Box = function(options, self) {
/* /*
This is how every widget "constructor" begins. `self` is the widget's This is how every widget "constructor" begins. `self` is the widget's
shared private object. It is private since it can only be accessed shared private object.
inside the widget, but shared because it can be passed to a widget upon
its creation.
*/ */
self = self || {}; self = self || {};
/* /*
`that` is the widget itself, its public object, or, in JavaScript terms, `that` is the widget itself, its public object, or, in JavaScript terms,
its `this`. Every widget "inherits" from another widget, by simple its `this`. Every widget "inherits" from another widget by simple
assignment. All public properties of the "super" widget, i.e. all assignment. All public properties of the "super" widget, i.e. all
properties of its `that`, will be present on our own `that`. In this properties of its `that`, will be present on our own `that`. In this
case, we use Ox.Element, the "root" widget at the end of the inheritance case, we use Ox.Element, the "root" widget at the end of the inheritance
chain, and pass an empty options object. But we always pass our own chain, and pass an empty options object. But we always pass our own
`self`, which means that any property that Ox.Element (or any other `self`, which means that any property that Ox.Element (or any other
widget in the inheritance chain) adds to self will be present on our own widget in the inheritance chain) adds to `self` will be present on our
`self`. Then we call the public `defaults` and `options` methods. own `self`. Then we call the public `defaults`, `options` and `update`
`defaults` assigns the defaults object to `self.defaults` and copies it methods of Ox.Element. `defaults` assigns the defaults object to
to `self.options`, then `options` extends `self.options` with the `self.defaults` and copies it to `self.options`, `options` extends
options object. `self.options` with the options object, and `update` adds one or more
callbacks that are invoked whenever, by way of calling the `options`
method, a property of `self.options` is modified or added.
*/ */
var that = Ox.Element({}, self) var that = Ox.Element({}, self)
.defaults({ .defaults({
@ -52,24 +65,13 @@ Ox.load('UI', function() {
}); });
/* /*
Ox.Element, and every widget that inherits from it, has a private The second part of the "constructor" function can be thought of as the
`self.setOption` method that is invoked whenever, by way of calling the "initializer", and contains everything needed to set up the "instance".
public `that.options` method, a property of `self.options` is modified In this case, we just define a minimum and maximum size and then set the
or added. If we don't want to react to such changes, we can leave widget's color and size. We could have used `var minSize` and `var
`self.setOption` untouched. In this case though, we want to update color maxSize` here, but by using `self` for private variables that we want to
and size, so we just overwrite `self.setOption`. be accessible across all the widget's methods, we can be sure that
*/ inside such methods, any local `var` is actually local to the method.
/*
The following part of the "constructor" function can be thought of as
the "initializer", and contains everything needed to set up the
"instance". In this case, we just define a minimum and maximum size and
then set the widget's color and size. We could have used `var minSize`
and `var maxSize` here, but by using `self` for private variables that
we want to be accessible across all the widget's methods, we can be sure
that inside such methods, any local `var` is actually local to the
method. We could have set color and size directly, too, but as we also
need to set them in `self.setOption`, we create methods for both cases.
*/ */
self.minSize = 128; self.minSize = 128;
self.maxSize = 384; self.maxSize = 384;
@ -78,13 +80,13 @@ Ox.load('UI', function() {
setSize(); setSize();
/* /*
Now we declare the widget's private methods. These are simple function Third, we declare the widget's private methods. These are just function
declarations, hoisted to the top of the "constructor". declarations, hoisted to the top of the "constructor".
*/ */
function setColor() { function setColor() {
/* /*
To interact with the DOM, Ox.Element (and any widget derived from To interact with the DOM, Ox.Element (and any widget derived from
it) wraps jQuery. If you type `Ox.Element()` in the console, you it) wraps jQuery. If you type Ox.Element() in the console, you
will get something like `[<div class="OxElement"></div>]`, and the will get something like `[<div class="OxElement"></div>]`, and the
widget's prototype has all the methods of a `$('<div>')`, with widget's prototype has all the methods of a `$('<div>')`, with
proper chaining. If you have `var $d = $('<div>'), $e = proper chaining. If you have `var $d = $('<div>'), $e =
@ -98,8 +100,8 @@ Ox.load('UI', function() {
function setSize() { function setSize() {
/* /*
Before setting the size, we make sure the value is between minSize Before setting the size, we make sure the value is between `minSize`
and maxSize. and `maxSize`.
*/ */
self.options.size = Ox.limit( self.options.size = Ox.limit(
self.options.size, self.minSize, self.maxSize self.options.size, self.minSize, self.maxSize
@ -127,7 +129,7 @@ Ox.load('UI', function() {
}; };
/* /*
At the very end of the "constructor", we always return `that`. And And finally, at the very end of the "constructor", we return `that`. And
that's it. that's it.
*/ */
return that; return that;
@ -135,7 +137,12 @@ Ox.load('UI', function() {
}; };
/* /*
`Ox.My.Box({size: 256}).appendTo(Ox.$body).showOptions()` <pre>
Ox.My.Box({color: [255, 0, 0]})
.appendTo(Ox.$body)
.options({size: 256})
.showOptions();
</pre>
*/ */
Ox.My.RoundedBox = function(options, self) { Ox.My.RoundedBox = function(options, self) {