update documentation example

This commit is contained in:
rolux 2012-06-24 15:41:06 +02:00
parent 9f1b86ab87
commit e0b1c238b9

View file

@ -50,10 +50,11 @@ This defines a new section named 'Objects'.
Lines that start with `#` are inline comments. The follwing lines document Lines that start with `#` are inline comments. The follwing lines document
properties of the `My.favorites` object. This example shows all possible values 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 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 <object> ... My.favorite <object> ...
# Properties -------------------------------------------------------------- # Properties --------------------------------------------------------------
array <a> My favorite array array <a> My favorite array
boolean <b> My favorite boolean value boolean <b> My favorite boolean value
@ -73,15 +74,23 @@ My.favorites <object> ...
any <*> Favorite of the day any <*> Favorite of the day
# Events ------------------------------------------------------------------- # Events -------------------------------------------------------------------
event <!> Fires when My.favorite['function'] is called 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() { My.favorite = (function() {
var favorites = { var favorite = {
array: [], array: [],
boolean: false, boolean: false,
date: new Date(), date: new Date(),
error: new Error(), error: new Error(),
'function': function() { 'function': function() {
My.triggerEvent(this, 'event'); My.Event.trigger(favorite, 'event');
}, },
arguments: (function() { return arguments; }()), arguments: (function() { return arguments; }()),
htmlelement: document.createElement('a'), htmlelement: document.createElement('a'),
@ -94,11 +103,11 @@ My.favorites = (function() {
'window': window, 'window': window,
other: document other: document
}, },
keys = Object.keys(favorites); keys = Object.keys(favorite);
favorites.any = favorites[ favorite.any = favorite[
keys[Math.floor(+new Date / 86400) * keys.length] keys[Math.floor(+new Date / 86400) * keys.length]
]; ];
return favorites; return favorite;
}()); }());
/* /*
@ -117,6 +126,10 @@ My.HTMLUtils <o> HTML Utilities
numericEntities <a> Can be passed to `String.prototype.replace` numericEntities <a> Can be passed to `String.prototype.replace`
0 <r> Matches numeric entities 0 <r> Matches numeric entities
1 <f> Decodes numeric entities 1 <f> Decodes numeric entities
> ''.replace.apply('&amp;', My.HTMLUtils.replace.namedEntities)
'&'
> ''.replace.apply('&#x2620;', My.HTMLUtils.replace.numericEntities)
'☠'
*/ */
My.HTMLUtils = (function() { My.HTMLUtils = (function() {
var chars = '"&\'<>', 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 If a function's return value depends on the absence or presence of optional
arguments, there can be multiple `(arguments) -> <type> summary` lines. arguments, there can be multiple `(arguments) -> <type> summary` lines. And to
test asynchronous functions, call `Ox.test(actual, expected)` in the
callback.
*/ */
/*@ /*@
My.isOdd <f> Synchronously or asynchronously computes if a given number is odd My.isOdd <f> Synchronously or asynchronously computes if a given number is odd
@ -209,6 +224,10 @@ My.isOdd <f> Synchronously or asynchronously computes if a given number is odd
callback <f> Callback function callback <f> Callback function
isOdd <b> True if the number is odd isOdd <b> True if the number is odd
ms <n> Time it took to compute the result, in milliseconds ms <n> 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) { My.isOdd = function(number, callback) {
var time = +new Date, isOdd = !!(number % 2); var time = +new Date, isOdd = !!(number % 2);
@ -231,6 +250,12 @@ My.range <f> Returns a python-style range
(b) -> <[n]> Integers from 0 (inclusive) to b (exclusive) (b) -> <[n]> Integers from 0 (inclusive) to b (exclusive)
(a, b) -> <[n]> Integers from a (inclusice) 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 (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() { My.range = function() {
var a = []; var a = [];
@ -241,8 +266,9 @@ My.range = function() {
}; };
/* /*
In case a function has properties or methods that need documentation, they get As functions are objects in JavaScript, they may have their own properties or
prefixed with `.`, in order to differentiate them from arguments. methods that need documentation. These get prefixed with `.`, in order to
differentiate them from arguments.
*/ */
/*@ /*@
My.localStorage <f> Returns a localStorage handler for a given namespace My.localStorage <f> Returns a localStorage handler for a given namespace
@ -258,46 +284,51 @@ My.localStorage <f> Returns a localStorage handler for a given namespace
(key[, ...]) -> <f> Deletes one or more pairs, returns the handler (key[, ...]) -> <f> Deletes one or more pairs, returns the handler
key <s> Any string key <s> Any string
ns <s> Namespace ns <s> 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() { My.localStorage = function(ns) {
if (!window.localStorage) { function storage(key, value) {
window.localStorage = {}; var ret;
} if (arguments.length == 0) {
return function(ns) { ret = {};
function storage(key, value) { Ox.forEach(localStorage, function(value, key) {
var args, ret; if (Ox.startsWith(key, ns + '.')) {
if (arguments.length == 0) { ret[key.slice(ns.length + 1)] = JSON.parse(value);
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];
}); });
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;
}; };
}()); return storage;
};
/* /*
And one more section, named 'UI Elements'. And another section, named 'UI Elements'.
*/ */
//@ 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 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 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, 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 <f> A very simple colored box My.Box <f> A very simple colored box
@ -315,6 +348,12 @@ My.Box <f> A very simple colored box
([options[, self]]) -> <o> Box object ([options[, self]]) -> <o> Box object
change <!> Fires when the color of the box changes change <!> Fires when the color of the box changes
color <n> Value between `0` and `255` color <n> 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) { My.Box = function(options, self) {
self = self || {}; self = self || {};
@ -342,7 +381,7 @@ My.Box = function(options, self) {
() -> <[n]> HSL value () -> <[n]> HSL value
*/ */
that.getHSL = function() { that.getHSL = function() {
return Ox.hsl(self.options.value); return Ox.hsl(self.options.color);
}; };
/*@ /*@
.setHSL <f> Sets the color of the box to a given HSL value .setHSL <f> Sets the color of the box to a given HSL value
@ -358,7 +397,7 @@ My.Box = function(options, self) {
*/ */
that.toGrayscale = function() { that.toGrayscale = function() {
return that.options({ 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; 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" 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, (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, `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 <f> An extended box with random color My.ExtendedBox <f> An extended box with random color
@ -377,6 +416,12 @@ My.ExtendedBox <f> An extended box with random color
width <n> Width in px width <n> Width in px
self <o> Shared private object self <o> Shared private object
([options[, self]]) -> <o:My.Box> Extended Box object ([options[, self]]) -> <o:My.Box> 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) { My.ExtendedBox = function(options, self) {
self = self || {}; self = self || {};
@ -414,7 +459,102 @@ My.ExtendedBox = function(options, self) {
return that; 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 `<script>` tag
can be added before the tests. Note that the script will be evaluated in the
global context, so it's a good idea not to create or leave any clutter.
*/
/*@
My.Event <o> Provides basic event handling
bind <f> Adds an event handler
(object[, event], callback) -> <o> My.Event
object <o> Any object that triggers events
event <s> Event name (if missing, add handler for all events)
callback <f> Event handler
data <o|null> Event data (if any)
trigger <f> Triggers an event
(object, event[, data]) -> <o> My.Event
object <o> The object that triggers the event
event <s> Event name
data <o> Event data (optional)
unbind <f> Removes one or more event handlers
(object[, event[, callback]]) -> <o> My.Event
object <o> The object that triggers the event
event <s> Event name (if missing, remove handlers for all events)
callback <f> Event handler (if missing, remove all handlers)
<script>
My.test = {
array: [],
handler: function(data) {
My.test.array.push(data.id);
},
object: (function() {
var id = 0,
that = {
ping: function() {
My.Event.trigger(that, 'ping', {id: id});
return id++;
}
};
return that;
}())
};
setTimeout(function() {
delete My.test;
}, 1000);
</script>
> 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 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 lines of code. Note that it would be more efficient to parse the source once
@ -437,8 +577,11 @@ and
Ox.DocPanel({ Ox.DocPanel({
expanded: true, expanded: true,
items: doc, items: doc,
getModule: function() { return 'My'; }, getModule: function() {
return 'My';
},
path: path, path: path,
showTests: true,
stripComments: true stripComments: true
}); });
``` ```
@ -461,11 +604,12 @@ Ox.load('UI', function() {
files: [file], files: [file],
getModule: function() { return 'My'; }, getModule: function() { return 'My'; },
path: path, path: path,
showTests: true,
stripComments: true stripComments: true
}); });
}, },
tabs: [ tabs: [
{id: 'source', title: 'Source Code', selected: true}, {id: 'source', title: 'Source Code'},
{id: 'items', title: 'Parsed Documentation'}, {id: 'items', title: 'Parsed Documentation'},
{id: 'panel', title: 'Documentation Browser'} {id: 'panel', title: 'Documentation Browser'}
] ]