From 2223064d352c9e2196cc7add2be43fda7bd21e11 Mon Sep 17 00:00:00 2001 From: rolux Date: Tue, 29 May 2012 12:22:06 +0200 Subject: [PATCH] update example --- examples/widget_design_patterns/js/example.js | 75 ++++++++++--------- 1 file changed, 41 insertions(+), 34 deletions(-) diff --git a/examples/widget_design_patterns/js/example.js b/examples/widget_design_patterns/js/example.js index b8067389..d7e11cf0 100644 --- a/examples/widget_design_patterns/js/example.js +++ b/examples/widget_design_patterns/js/example.js @@ -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 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'; /* @@ -14,31 +27,31 @@ Ox.load('UI', function() { 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 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. */ Ox.My.Box = function(options, self) { /* This is how every widget "constructor" begins. `self` is the widget's - shared private object. It is private since it can only be accessed - inside the widget, but shared because it can be passed to a widget upon - its creation. + 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 + 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` and `options` methods. - `defaults` assigns the defaults object to `self.defaults` and copies it - to `self.options`, then `options` extends `self.options` with the - options object. + 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({ @@ -52,24 +65,13 @@ Ox.load('UI', function() { }); /* - Ox.Element, and every widget that inherits from it, has a private - `self.setOption` method that is invoked whenever, by way of calling the - public `that.options` method, a property of `self.options` is modified - or added. If we don't want to react to such changes, we can leave - `self.setOption` untouched. In this case though, we want to update color - and size, so we just overwrite `self.setOption`. - */ - - /* - 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. + 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; @@ -78,13 +80,13 @@ Ox.load('UI', function() { 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". */ 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 + 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 `$('
')`, with proper chaining. If you have `var $d = $('
'), $e = @@ -98,8 +100,8 @@ Ox.load('UI', function() { function setSize() { /* - Before setting the size, we make sure the value is between minSize - and maxSize. + Before setting the size, we make sure the value is between `minSize` + and `maxSize`. */ self.options.size = Ox.limit( 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. */ return that; @@ -135,7 +137,12 @@ Ox.load('UI', function() { }; /* - `Ox.My.Box({size: 256}).appendTo(Ox.$body).showOptions()` +
+    Ox.My.Box({color: [255, 0, 0]})
+        .appendTo(Ox.$body)
+        .options({size: 256})
+        .showOptions();
+    
*/ Ox.My.RoundedBox = function(options, self) {