diff --git a/examples/documentation/oxdoc/js/example.js b/examples/documentation/oxdoc/js/example.js index fef29e26..2b98a8f2 100644 --- a/examples/documentation/oxdoc/js/example.js +++ b/examples/documentation/oxdoc/js/example.js @@ -50,10 +50,11 @@ This defines a new section named 'Objects'. Lines that start with `#` are inline comments. The follwing lines document properties of the `My.favorites` object. This example shows all possible values for `type`. These values can be shortened, it's sufficient to specify their -first character. +first character. A line that starts with `>` is an inline test statement, +followed by its expected result. */ /*@ -My.favorites ... +My.favorite ... # Properties -------------------------------------------------------------- array My favorite array boolean My favorite boolean value @@ -73,15 +74,23 @@ My.favorites ... any <*> Favorite of the day # Events ------------------------------------------------------------------- event Fires when My.favorite['function'] is called + > My.favorite.array.length + My.favorite.string.length + 0 + > My.favorite['function'].length + My.favorite.arguments.length + 0 + > My.favorite.number + Object.keys(My.favorite.object).length + 0 + > My.favorite.regexp.toString() + '/(?:)/' */ -My.favorites = (function() { - var favorites = { +My.favorite = (function() { + var favorite = { array: [], boolean: false, date: new Date(), error: new Error(), 'function': function() { - My.triggerEvent(this, 'event'); + My.Event.trigger(favorite, 'event'); }, arguments: (function() { return arguments; }()), htmlelement: document.createElement('a'), @@ -94,11 +103,11 @@ My.favorites = (function() { 'window': window, other: document }, - keys = Object.keys(favorites); - favorites.any = favorites[ + keys = Object.keys(favorite); + favorite.any = favorite[ keys[Math.floor(+new Date / 86400) * keys.length] ]; - return favorites; + return favorite; }()); /* @@ -117,6 +126,10 @@ My.HTMLUtils HTML Utilities numericEntities Can be passed to `String.prototype.replace` 0 Matches numeric entities 1 Decodes numeric entities + > ''.replace.apply('&', My.HTMLUtils.replace.namedEntities) + '&' + > ''.replace.apply('☠', My.HTMLUtils.replace.numericEntities) + '☠' */ My.HTMLUtils = (function() { var chars = '"&\'<>', @@ -199,7 +212,9 @@ My.readURL = function(url, method, callback) { /* If a function's return value depends on the absence or presence of optional -arguments, there can be multiple `(arguments) -> summary` lines. +arguments, there can be multiple `(arguments) -> summary` lines. And to +test asynchronous functions, call `Ox.test(actual, expected)` in the +callback. */ /*@ My.isOdd Synchronously or asynchronously computes if a given number is odd @@ -209,6 +224,10 @@ My.isOdd Synchronously or asynchronously computes if a given number is odd callback Callback function isOdd True if the number is odd ms Time it took to compute the result, in milliseconds + > My.isOdd(0) + false + > My.isOdd(1, function(isOdd, ms) { Ox.test(isOdd, true); }) + undefined */ My.isOdd = function(number, callback) { var time = +new Date, isOdd = !!(number % 2); @@ -231,6 +250,12 @@ My.range Returns a python-style range (b) -> <[n]> Integers from 0 (inclusive) to b (exclusive) (a, b) -> <[n]> Integers from a (inclusice) to b (exclusive) (a, b, c) -> <[n]> Numbers from a (inclusive) to b (exclusive), growing by c + > My.range(2) + [0, 1] + > My.range(1, 3) + [1, 2] + > My.range(2, 6, 2) + [2, 4] */ My.range = function() { var a = []; @@ -241,8 +266,9 @@ My.range = function() { }; /* -In case a function has properties or methods that need documentation, they get -prefixed with `.`, in order to differentiate them from arguments. +As functions are objects in JavaScript, they may have their own properties or +methods that need documentation. These get prefixed with `.`, in order to +differentiate them from arguments. */ /*@ My.localStorage Returns a localStorage handler for a given namespace @@ -258,46 +284,51 @@ My.localStorage Returns a localStorage handler for a given namespace (key[, ...]) -> Deletes one or more pairs, returns the handler key Any string ns Namespace + > Ox.typeOf((My.test = {storage: My.localStorage('My')}).storage) + 'function' + > My.test.storage({foo: 'bar'})('baz') + undefined + > My.test.storage('bar', 'baz')('bar') + 'baz' + > My.test.storage.delete('bar')('foo') + 'bar' + > Object.keys(My.test.storage()) + ['foo'] */ -My.localStorage = (function() { - if (!window.localStorage) { - window.localStorage = {}; - } - return function(ns) { - function storage(key, value) { - var args, ret; - if (arguments.length == 0) { - ret = {}; - Ox.forEach(localStorage, function(value, key) { - if (Ox.startsWith(key, ns + '.')) { - ret[key.slice(ns.length + 1)] = JSON.parse(value); - } - }); - } else if (arguments.length == 1 && !Ox.isObject(key)) { - value = localStorage[ns + '.' + key]; - ret = Ox.isUndefined(value) ? void 0 : JSON.parse(value); - } else { - Ox.forEach(Ox.makeObject(arguments), function(value, key) { - localStorage[ns + '.' + key] = JSON.stringify(value); - }); - ret = this; - } - return ret; - }; - storage.delete = function() { - var keys = arguments.length == 0 ? Object.keys(storage()) - : Ox.toArray(arguments) - keys.forEach(function(key) { - delete localStorage[ns + '.' + key]; +My.localStorage = function(ns) { + function storage(key, value) { + var ret; + if (arguments.length == 0) { + ret = {}; + Ox.forEach(localStorage, function(value, key) { + if (Ox.startsWith(key, ns + '.')) { + ret[key.slice(ns.length + 1)] = JSON.parse(value); + } }); - return storage; - }; + } else if (arguments.length == 1 && !Ox.isObject(key)) { + value = localStorage[ns + '.' + key]; + ret = Ox.isUndefined(value) ? void 0 : JSON.parse(value); + } else { + Ox.forEach(Ox.makeObject(arguments), function(value, key) { + localStorage[ns + '.' + key] = JSON.stringify(value); + }); + ret = storage; + } + return ret; + } + storage.delete = function() { + var keys = arguments.length == 0 ? Object.keys(storage()) + : Ox.toArray(arguments) + keys.forEach(function(key) { + delete localStorage[ns + '.' + key]; + }); return storage; }; -}()); + return storage; +}; /* -And one more section, named 'UI Elements'. +And another section, named 'UI Elements'. */ //@ UI Elements @@ -305,7 +336,9 @@ And one more section, named 'UI Elements'. When documenting a constructor function, the returned object may come with a lot more documentation than the function itself. In this case, one may want to document the contructor's arguments first, then the signature and return value, -follwed by the documentation of the returned object. +follwed by the documentation of the returned object. Further, if an event has +event data, i.e. passes an object to its handlers, the properties of that object +are documented as properties of the event. */ /*@ My.Box A very simple colored box @@ -315,6 +348,12 @@ My.Box A very simple colored box ([options[, self]]) -> Box object change Fires when the color of the box changes color Value between `0` and `255` + > My.Box({color: [0, 255, 0]}).getHSL() + [120, 1, 0.5] + > My.Box().setHSL(240, 1, 0.5).options('color') + [0, 0, 255] + > My.Box().toGrayscale().options('color') + [85, 85, 85] */ My.Box = function(options, self) { self = self || {}; @@ -342,7 +381,7 @@ My.Box = function(options, self) { () -> <[n]> HSL value */ that.getHSL = function() { - return Ox.hsl(self.options.value); + return Ox.hsl(self.options.color); }; /*@ .setHSL Sets the color of the box to a given HSL value @@ -358,7 +397,7 @@ My.Box = function(options, self) { */ that.toGrayscale = function() { return that.options({ - color: Ox.repeat([Ox.avg(self.options.color)], 3) + color: Ox.repeat([Math.round(Ox.avg(self.options.color))], 3) }); }; return that; @@ -368,7 +407,7 @@ My.Box = function(options, self) { If an object extends or inherits from another one, one can specify its "class" (i.e. the name of the constuctor of the object it inherits from). Here, `My.ExtendedBox` extends `My.Box`. All events and properties of the latter, -unless redefined will, be present on the former +unless redefined will, be present on the former. */ /*@ My.ExtendedBox An extended box with random color @@ -377,6 +416,12 @@ My.ExtendedBox An extended box with random color width Width in px self Shared private object ([options[, self]]) -> Extended Box object + > My.ExtendedBox().options({color: [0, 255, 0]}).getHSL() + [120, 1, 0.5] + > My.ExtendedBox().setHSL(240, 1, 0.5).options('color') + [0, 0, 255] + > [My.ExtendedBox().options('width'), My.ExtendedBox().options('height')] + [256, 256] */ My.ExtendedBox = function(options, self) { self = self || {}; @@ -414,7 +459,102 @@ My.ExtendedBox = function(options, self) { return that; }; +/* +The last item gets added to the 'Objects' section. +*/ +//@ Objects + +/* +Whenever code is hard to test with just a series of one-liners, a ` + > My.test.object.ping() == 0 + true + > Ox.methods(My.Event.bind(My.test.object, 'ping', My.test.handler)) + ['bind', 'trigger', 'unbind'] + > My.test.object.ping() == 1 + true + > Ox.methods(My.Event.unbind(My.test.object, 'ping', My.test.handler)) + ['bind', 'trigger', 'unbind'] + > My.test.object.ping() == 2 + true + > My.test.array + [1] + */ +My.Event = (function() { + var handlers = [], that = {}; + that.bind = function(object, event, callback) { + if (arguments.length == 2) { + callback = event; + event = null; + } + handlers.push({object: object, event: event, callback: callback}); + return that; + }; + that.trigger = function(object, event, data) { + handlers.forEach(function(handler) { + if (handler.object === object && handler.event === event) { + handler.callback(data || null); + } + }); + return that; + }; + that.unbind = function(object, event, callback) { + handlers.forEach(function(handler, i) { + if ( + handler.object === object + && (!event || !handler.event || handler.event === event) + && (!callback || handler.callback === callback) + ) { + handlers.splice(i, 1); + } + }); + return that; + }; + return that; +}()); //@ + /* And finally, this is how everything gets parsed and displayed, in less than 30 lines of code. Note that it would be more efficient to parse the source once @@ -437,8 +577,11 @@ and Ox.DocPanel({ expanded: true, items: doc, - getModule: function() { return 'My'; }, + getModule: function() { + return 'My'; + }, path: path, + showTests: true, stripComments: true }); ``` @@ -461,11 +604,12 @@ Ox.load('UI', function() { files: [file], getModule: function() { return 'My'; }, path: path, + showTests: true, stripComments: true }); }, tabs: [ - {id: 'source', title: 'Source Code', selected: true}, + {id: 'source', title: 'Source Code'}, {id: 'items', title: 'Parsed Documentation'}, {id: 'panel', title: 'Documentation Browser'} ]