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
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 <object> ...
My.favorite <object> ...
# Properties --------------------------------------------------------------
array <a> My favorite array
boolean <b> My favorite boolean value
@ -73,15 +74,23 @@ My.favorites <object> ...
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 <o> HTML Utilities
numericEntities <a> Can be passed to `String.prototype.replace`
0 <r> Matches numeric entities
1 <f> Decodes numeric entities
> ''.replace.apply('&amp;', My.HTMLUtils.replace.namedEntities)
'&'
> ''.replace.apply('&#x2620;', 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) -> <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
@ -209,6 +224,10 @@ My.isOdd <f> Synchronously or asynchronously computes if a given number is odd
callback <f> Callback function
isOdd <b> True if the number is odd
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) {
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)
(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 <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 <s> Any string
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() {
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 <f> A very simple colored box
@ -315,6 +348,12 @@ My.Box <f> A very simple colored box
([options[, self]]) -> <o> Box object
change <!> Fires when the color of the box changes
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) {
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 <f> 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 <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
self <o> Shared private 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) {
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 `<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
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'}
]