diff --git a/examples/documentation/oxdoc/js/example.js b/examples/documentation/oxdoc/js/example.js index 0240c9af..f60285a3 100644 --- a/examples/documentation/oxdoc/js/example.js +++ b/examples/documentation/oxdoc/js/example.js @@ -1,36 +1,53 @@ +'use strict'; /* -An Ox.doc comment looks like this `//@ foo` or +An OxDoc comment is an inline or multi-line comment that starts with `@`: ``` +//@ ... /*@ -foo -bar -baz -*\/ +... +*/ ``` The syntax is simple: almost every line has the form `name summary`. If it doesn't, its meaning depends on its context. */ - this.My = {}; /* If the first line of the comment doesn't match `name summary`, it is a -section definition. Here, we mark a section named 'Primitives'. +section definition. Here, it marks a section named 'Primitives'. */ //@ Primitives +/* +This inline comment documents an item by providing its name, type and one-line +summary. +*/ //@ My.REQUEST_TIMEOUT Request timeout, in milliseconds My.REQUEST_TIMEOUT = 60000; +/* +In a multiline comment, lines that follow the inital definition are indented, as +they refer to the item defined in the line above. Lines that don't match `name + summary` are parsed as a description. Like the summary, the description +can contain `markdown`. +*/ /*@ My.MAGIC_CONSTANT Magic constant, needed for HTTP requests - Please note that the value for `MAGIC_CONSTANT` is browser-dependent. + Please note that the value of `My.MAGIC_CONSTANT` (either `23` or `42`) is + browser-dependent. */ -My.MAGIC_CONSTANT = navigator.userAgent.length % 2 == 0 ? 23 : 42; +My.MAGIC_CONSTANT = navigator.userAgent.length % 2 ? 23 : 42; -Ox.load(function() { -//@ Objects /* +This defines a new section named 'Objects'. +*/ +//@ 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. */ /*@ My.favorites ... @@ -75,32 +92,43 @@ My.favorites = (function() { other: document }, keys = Object.keys(favorites); - return Ox.extend(favorites, {any: favorites[keys[Ox.random(keys.length)]]}); + favorites.any = favorites[keys[Math.floor(Math.random() * keys.length)]]; + return favorites; }()); +/* +Documentation can be nested. In other words, one can document the properties of +a property (of a property...). Also, if all elements of an array are of a known +type (in this case `string`), one can mark the type as `<[s]>` instead of just +``. +*/ /*@ -My.HTMLUtils ... - replace ... - 0 ... - 1 replace +My.HTMLUtils HTML Utilities + namedEntities <[s]> Named HTML entities + replace Entity decoding utilities + namedEntities Can be passed to `String.prototype.replace` + 0 Matches named entities + 1 Decodes named entities + numericEntities Can be passed to `String.prototype.replace` + 0 Matches numeric entities + 1 Decodes numeric entities */ My.HTMLUtils = (function() { - var entities = { - '"': '"', '&': '&', "'": ''', '<': '<', '>': '>' - }; + var chars = '"&\'<>', + entities = ['"', '&', ''', '<', '>']; return { - entities: entities, + namedEntities: entities, replace: { - namedEntity: [ - new RegExp('(' + Ox.values(entities).join('|') + ')', 'g'), + namedEntities: [ + new RegExp('(' + entities.join('|') + ')', 'g'), function(match) { - return Ox.keyOf(entities, match); + return chars[entities.indexOf(match)]; } ], - numericEntity: [ + numericEntities: [ /&#([0-9A-FX]+);/gi, function(match, code) { - return Ox.char( + return String.fromCharCode( /^X/i.test(code) ? parseInt(code.slice(1), 16) : parseInt(code, 10) @@ -111,83 +139,63 @@ My.HTMLUtils = (function() { }; }()); -/*@ -My.defaultPlace Default place object - geometry - bounds .. - northEast - lat - lng - southWest - lat - lng - types <[s]> - name Localized place names - short Short place name - de Short German name - en Short English name - fr Short French name - long Long place name - de Long German name - en Long English name - fr Long French name - points <[o]> Points of interest - lat Latitude - lng Longitude -@*/ -My.place = { - bounds: { - northEast: {lat: 0, lng: 0}, - southWest: {lat: 0, lng: 0} - }, - name: { - short: { - de: 'Brüssel', - en: 'Brussels', - fr: 'Bruxelles' - }, - long: { - de: 'Brüssel, Belgien', - en: 'Brussels, Belgium', - fr: 'Bruxelles, Belgique' - } - }, - points: [ - {lat: 0, lng: 0}, - {lat: 45, lng: 90} - ] -}; - +/* +The beginning of another section, named 'Functions'. +*/ //@ Functions +/* +In the case of a function, the indented lines don't document properties, but the +function's signature, return value and arguments. Signature and return value are +just a special case of `name summary`, where `name` has the form +`(arguments) ->`. If an item can be of more than one type (in this case `string` +or `function`), this is documented as ``. If it has a default value (in +this case the string `'GET'`), this is documented as ``. In the case of +a `function`-type argument (usually a callback function), there is no return +value to document, only the arguments it gets passed. +*/ /*@ +My.readURL Asynchronously reads a remote resource (url[, method], callback) -> undefined - url URL - method Request method ('GET', 'POST', 'PUT' or 'DELETE') - callback Callback function + Please note that the return value of `My.readURL` may change in the + future. + url Remote URL, or function that returns one + method Request method ('GET', 'POST', 'PUT' or 'DELETE') + callback Callback function + result Response text, or `null` in case of an error + error Error object, or `null` in case of success + code Error code + text Error text */ My.readURL = function(url, method, callback) { var request = new XMLHttpRequest(); + if (Ox.isFunction(url)) { + url = url(); + } if (arguments.length == 2) { callback = method; method = 'GET'; } request.open(method, url, true); - req.onreadystatechange = function() { + request.onreadystatechange = function() { if (request.readyState == 4) { if (request.status == 200) { - callback(request.responseText); + callback(request.responseText, null); } else { - throw new Error( - 'Cannot get URL "' + url - + '" (Status: ' + request.status + ')' - ); + callback(null, { + code: request.status, + text: request.statusText + }); } } }; request.send(); }; +/* +If a function's return value depends on the absence or presence of optional +arguments, there can be multiple `(arguments) -> summary` lines. +*/ /*@ My.isOdd Synchronously or asynchronously computes if a given number is odd (number) -> True if the number is odd @@ -207,10 +215,11 @@ My.isOdd = function(number, callback) { }; /* -Occasionally, you may write a function whose signature cannot be represented in -`(required[, optional])` notation. For a range function — `(stop)` or `(start, -stop)` or `(start, stop, step)` — the notation `([start, ]stop[, step])` would -be ambigious, since you cannot call it with `(stop, step)`. +Another case for multiple `(arguments) -> summary` lines are functions +whose signature cannot be represented in `(required[, optional])` notation. For +a range function — `(stop)` or `(start, stop)` or `(start, stop, step)` — the +notation `([start, ]stop[, step])` would be ambigious, since you cannot call it +with `(stop, step)`. */ /*@ My.range Returns a python-style range @@ -226,6 +235,10 @@ My.range = function() { return a; }; +/* +In case a function has a property or method one wants to document, it gets +prefixed with `.`, in order to differentiate it from an argument. +*/ /*@ My.localStorage Returns a localStorage handler for a given namespace (ns) -> storage localStorage handler @@ -278,13 +291,63 @@ My.localStorage = (function() { }; }()); -}); +/* +And one more section, named 'UI Elements'. +*/ +//@ UI Element + +/*@ +My.Box A very simple colored box + options Options + color <[n]> RGB value + self Shared private object + ([options[, self]]) -> Box object + grayscale Fires when changing the color of the box to grayscale + color Value between `0` and `255` +*/ +My.Box = function(options, self) { + self = self || {}; + var that = Ox.Element({}, self) + .defaults({color: [255, 0, 0]}) + .options(options || {}) + .update(setColor) + .css({width: '256px', height: '256px'}); + function setColor() { + that.css({background: 'rgb(' + self.options.color.join(', ') + ')'}); + } + /*@ + .toGrayscale Changes the color of the box to grayscale. + () -> The box object + */ + that.toGrayscale = function() { + return that.options({ + color: Ox.repeat([Ox.avg(self.options.color)], 3) + }).triggerEvent('grayscale', {color: self.options.color[0]}); + }; + return that; +}; + //@ Ox.load('UI', function() { - var path = Ox.PATH + '../examples/documentation/js/'; - Ox.print(path, '??') - Ox.DocPanel({ - files: 'example.js', - path: path - }).appendTo(Ox.$body); + var file = 'example.js', + path = Ox.PATH + '../examples/documentation/oxdoc/js/'; + Ox.get(path + file, function(source) { + var doc = Ox.doc(source); + Ox.TabPanel({ + content: { + source: Ox.SyntaxHighlighter({source: path + file}), + doc: Ox.TreeList({data: doc}), + docpanel: Ox.DocPanel({ + expanded: true, + files: 'example.js', + path: path + }) + }, + tabs: [ + {id: 'source', title: 'source'}, + {id: 'doc', title: 'doc = Ox.doc(source)'}, + {id: 'docpanel', title: 'Ox.DocPanel({items: doc})'} + ] + }).appendTo(Ox.$body); + }); });