/* The following examples explain the common design pattern for OxJS UI widgets: an inheritance model that is neither classical nor prototypal, but "parasitical" (a term coined by Douglas Crockford). 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'; /* Load the UI module. */ Ox.load('UI', function() { /* Create our own namespace. */ Ox.My = {}; /* First, lets build the most basic Box widget. A widget is a "constructor" function that takes two (optional) arguments, `options` and `self`, and 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 `instanceof` anything. It just enhances another widget object and returns it. */ Ox.My.Box = function(options, self) { /* This is how every widget "constructor" begins. `self` is the widget's shared private object. */ self = self || {}; /* `that` is the widget itself, its public object, or, in JavaScript terms, its `this`. Every widget "inherits" from another widget by simple assignment. All public properties of the "super" widget, i.e. all 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 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 widget in the inheritance chain) adds to `self` will be present on our own `self`. Then we call the public `defaults`, `options` and `update` methods of Ox.Element. `defaults` assigns the defaults object to `self.defaults` and copies it to `self.options`, `options` extends `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) .defaults({ color: [128, 128, 128], size: 128 }) .options(options || {}) .update({ color: setColor, size: setSize }); /* The second 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. */ self.minSize = 128; self.maxSize = 384; setColor(); setSize(); /* Third, we declare the widget's private methods. These are just function declarations, hoisted to the top of the "constructor". */ function setColor() { /* To interact with the DOM, Ox.Element (and any widget derived from it) wraps jQuery. If you type Ox.Element() in the console, you will get something like `[
]`, and the widget's prototype has all the methods of a `$('Ox.My.Box({color: [255, 0, 0]}) .appendTo(Ox.$body) .options({size: 256}) .showOptions();*/ Ox.My.RoundedBox = function(options, self) { self = self || {}; var that = Ox.My.Box({}, self); that.defaults(Ox.extend(that.defaults(), { radius: 16 })) .options(options || {}) .update(function(key, value) { if (key == 'radius') { setRadius(); } }); setRadius(); function setRadius() { that.css({ MozBorderRadius: self.options.radius + 'px', OBorderRadius: self.options.radius + 'px', WebkitBorderRadius: self.options.radius + 'px' }); } return that; }; window.myBox = Ox.My.Box().appendTo(Ox.$body); window.myRoundedBox = Ox.My.RoundedBox().appendTo(Ox.$body); return; Ox.My.Box = function(options, self) { self = self || {}; var that = Ox.Element('