some more documentation; reimplement Ox.range using Ox.loop

This commit is contained in:
rolux 2011-05-07 00:47:17 +02:00
parent ae80b6db54
commit 8c4bc3b415
5 changed files with 305 additions and 243 deletions

View file

@ -1,122 +1,18 @@
<!DOCTYPE HTML>
<html>
<head>
<style>
table {
//border: 1px solid black;
}
td {
//border: 1px solid red;
}
</style>
<script type="text/javascript" src="../../build/Ox.js"></script>
<script>
var element = document.createElement('script');
element.src = '../../build/Ox.UI/js/Map/Ox.Map.js';
element.type = 'text/javascript';
document.head.appendChild(element);
</script>
<script>
Ox.documentReady(function() {
Ox.print(Ox.Map)
})
</script>
</head>
<body>
<table>
<tr>
<td>Ox.foo</td>
<td>&lt;foo&gt;</td>
<td>foo</td>
</tr>
</table>
<table>
<tr>
<td width=16/>
<td><b>Usage</b></td>
</tr>
</table>
<table>
<tr>
<td width=32/>
<td>Ox.foo(foo)</td>
<td>returns</td>
<td>&lt;foo&gt;</td>
<td>foo</td>
</tr>
<tr>
<td width=32/>
<td>Ox.foo(foo, bar)</td>
<td>returns</td>
<td>&lt;foobar&gt;</td>
<td>foobar</td>
</tr>
</table>
<table>
<tr>
<td width=16/>
<td><b>Arguments</b></td>
</tr>
</table>
<table>
<tr>
<td width=32/>
<td>foo</td>
<td>&lt;foo&gt;</td>
<td>foo</td>
<td width=300></td>
</tr>
<tr>
<td colspan=5>
<table>
<tr>
<td width=48/>
<td><b>Properties</b></td>
</tr>
</table>
<table>
<tr>
<td width=64/>
<td>foo</td>
<td>&lt;foo&gt;</td>
<td>foo</td>
<td width=100></td>
</tr>
<tr>
<td colspan=5>
<table>
<tr>
<td width=80/>
<td><b>Properties</b></td>
</tr>
</table>
<table>
<tr>
<td width=96/>
<td>foo</td>
<td>&lt;foo&gt;</td>
<td>foo</td>
<td width=100></td>
</tr>
<tr>
<td width=96/>
<td>foobar</td>
<td>&lt;foobar&gt;</td>
<td>foobar</td>
<td width=100></td>
</tr>
</table>
</td>
</tr>
<tr>
<td width=64/>
<td>foobar</td>
<td>&lt;foobar&gt;</td>
<td>foobar</td>
<td width=100></td>
</tr>
</table>
</td>
</tr>
<tr>
<td width=32/>
<td>foobar</td>
<td>&lt;foobar&gt;</td>
<td>foobar</td>
<td width=300></td>
</tr>
</table>
</body>
<body></body>
<html>

View file

@ -8,10 +8,12 @@ Ox.DocPage = function(options, self) {
.options(options || {})
.addClass('OxText')
.css({
width: '640px'
width: '640px',
height: '400px',
overflow: 'auto'
});
$('body').css('overflowY', 'auto')
$('body').css('overflowY', 'scroll')
that.append($('<h1>').append('<code>' + self.options.doc.name + '</code>'));
@ -85,12 +87,12 @@ Ox.DocPage = function(options, self) {
.addClass(className)
.css({marginLeft: ((level * 32 + 32) + 'px')})
.html(
'<code><b>&gt;</b>&nbsp;' +
'<code><b>&gt;&nbsp;' +
Ox.encodeHTML(example.statement)
//example.statement
.replace(/ /g, '&nbsp;')
.replace(/\n/g, '<br/>\n&nbsp;&nbsp;') +
'</code>'
'</b></code>'
)
);
example.result && $elements.push($('<div>')

View file

@ -35,6 +35,8 @@ Ox.SyntaxHighlighter = function(options, self) {
.replace(/\r\n/g, '\n')
.replace(/\r/g, '\n');
//self.options.source = Ox.minify(self.options.source);
self.cursor = 0;
self.source = '';
self.tokens = Ox.tokenize(self.options.source);

View file

@ -10,7 +10,7 @@
Ox <f> The <code>Ox</code> object
See <code>Ox.wrap</code> for details.
(value) -> <o> wrapped value
value <*> any value
value <*> Any value
@*/
Ox = function(val) {
@ -28,6 +28,7 @@ Ox.AMPM = ['AM', 'PM'];
//@ Ox.DURATIONS <[str]> ['year', 'month', 'day', 'minute', 'second']
Ox.DURATIONS = ['year', 'month', 'day', 'minute', 'second'];
//@ Ox.EARTH_RADIUS <number> Radius of the earth in meters
// see http://en.wikipedia.org/wiki/WGS-84
Ox.EARTH_RADIUS = 6378137;
//@ Ox.EARTH_CIRCUMFERENCE <num> Circumference of the earth in meters
Ox.EARTH_CIRCUMFERENCE = Ox.EARTH_RADIUS * 2 * Math.PI;
@ -36,8 +37,8 @@ Ox.HTML_ENTITIES = {
'"': '&quot;', '&': '&amp;', "'": '&apos;', '<': '&lt;', '>': '&gt;'
};
//@ Ox.KEYS <object> Names for key codes
// the dot notation ('0.numpad') allows for namespaced events ('key_0.numpad'),
// so that binding to 'key_0' will catch 'key0.numpad' too
// The dot notation ('0.numpad') allows for namespaced events ('key_0.numpad'),
// so that binding to 'key_0' will catch both 'key_0' and 'key_0.numpad'.
Ox.KEYS = {
0: 'section', 8: 'backspace', 9: 'tab', 12: 'clear', 13: 'enter',
16: 'shift', 17: 'control', 18: 'alt', 20: 'capslock', 27: 'escape',
@ -209,7 +210,9 @@ Ox.doc = (function() {
lastItem.properties = lastItem.properties || [];
lastItem.properties.push(item);
// include leading linebreaks and whitespace
lastItem.source = Ox.merge(lastItem.source, parseTokens(tokens[i], true));
lastItem.source = Ox.merge(
lastItem.source, parseTokens(tokens[i], true)
);
}
});
function decodeLinebreaks(match, submatch) {
@ -361,9 +364,9 @@ Ox.doc = (function() {
return Ox.startsWith(type, unwrapped);
})).length
) {
ret.types.push(wrap(type[0]))
ret.types.push(wrap(type[0]));
} else {
ret.default = str;
ret['default'] = str;
}
});
function unwrap(str) {
@ -371,7 +374,8 @@ Ox.doc = (function() {
str = str.substr(1, str.length - 2) : str;
}
function wrap(str) {
return isArray ? '[' + str + ']' : str;
return isArray ?
'array[' + str + (str != 'any' ? 's' : '') + ']' : str;
}
return ret;
}
@ -506,9 +510,12 @@ Ox.loadFile = (function() {
element.src = file;
} else {
if (!findFileInHead()) {
element = document.createElement(type == 'css' ? 'link' : 'script');
element = document.createElement(
type == 'css' ? 'link' : 'script'
);
element[type == 'css' ? 'href' : 'src'] = file;
element.type = type == 'css' ? 'text/css' : 'text/javascript';
element.type = type == 'css' ?
'text/css' : 'text/javascript';
if (type == 'css') {
element.rel = 'stylesheet';
waitForCSS();
@ -573,7 +580,8 @@ Ox.print = function() {
date = new Date();
args.unshift(
Ox.formatDate(date, '%H:%M:%S.') + (+date).toString().substr(-3),
arguments.callee.caller.name || '(anonymous)'
(arguments.callee.caller && arguments.callee.caller.name) ||
'(anonymous)'
);
window.console && window.console.log.apply(window.console, args);
return args.join(' ');
@ -599,7 +607,7 @@ Ox.wrap <f> Wraps a value so that one can directly call any Ox function on it
(value) -> <o> wrapped value
chain <f> wrap the return value to allow chaining
value <f> unwrap the value wrapped by chain()
value <*> any value
value <*> Any value
> Ox.wrap("foobar").repeat(2)
"foobarfoobar"
> Ox.wrap("foobar").chain().reverse().toTitleCase().value()
@ -728,7 +736,7 @@ Ox.every = function(obj, fn) {
Ox.extend = function() {
/*
>>> Ox.extend({a: 1, b: 1, c: 1}, {b: 2, c: 2}, {c: 3}).c
3
{"a":1,"b":2,"c":3}
*/
var obj = arguments[0];
Ox.forEach(Array.prototype.slice.call(arguments, 1), function(arg, i) {
@ -745,9 +753,9 @@ Ox.filter = function(obj, fn) {
>>> Ox.filter([2, 1, 0], function(v, i) { return v == i; })
[1]
>>> Ox.keys(Ox.filter({a: 'c', b: 'b', c: 'a'}, function(v, k) { return v == k; }))
['b']
>>> Ox.filter(' hello world ', function(v) { return v != ' '; })
'helloworld'
["b"]
>>> Ox.filter(' foo bar ', function(v) { return v != ' '; })
"foobar"
***/
var type = Ox.typeOf(obj),
ret = type == 'array' ? [] : type == 'object' ? {} : '';
@ -816,20 +824,14 @@ Ox.forEach <f> forEach loop
callback <f> Callback function
value <*> Value
key <n|s> Key
> var string = "";
> Ox.forEach(["f", "o", "o"], function(v, i) { string += i; })
> Ox.forEach({a: "f", b: "o", c: "o"}, function(v, k) { string += k; })
> Ox.forEach("foo", function(v) { string += v; })
> string
"012abcfoo"
@*/
Ox.forEach = function(obj, fn) {
/*
Ox.forEach() works for arrays, objects and strings,
like $.each(), unlike [].forEach()
The arguments of the iterator function are (value, key),
like [].forEach(), unlike $.each()
>>> Ox.forEach('foo', function(v, i) {})
'foo'
>>> Ox.forEach([0, 1, 2], function(v, i) {})
[0, 1, 2]
>>> Ox.forEach({a: 1, b: 2, c: 3}, function(v, k) {}).a
1
*/
var isObject = Ox.isObject(obj), key;
for (key in obj) {
key = isObject ? key : parseInt(key);
@ -888,8 +890,12 @@ Ox.isEqual = function(obj0, obj1) {
true
>>> Ox.isEqual({a: 1, b: [2, 3], c: {d: '4'}}, {a: 1, b: [2, 3], c: {d: '4'}})
true
>>> Ox.isEqual(function(arg) { return arg; }, function(arg) { return arg; });
>>> Ox.isEqual({a: 1, b: 2, c: 3}, {c: 3, b: 2, a: 1})
true // FIXME: is false
>>> Ox.isEqual(function(arg) { return arg; }, function(arg) { return arg; })
true
>>> Ox.isEqual(function(foo) { return foo; }, function(bar) { return bar; })
false
*/
var ret = false;
if (obj0 === obj1) {
@ -967,25 +973,59 @@ Ox.len = function(obj) {
return Ox.isObject(obj) ? Ox.values(obj).length : obj.length;
};
/*@
Ox.loop <f> For-loop, functional-style
Returning <code>false</code> from the iterater function acts like a
<code>break</code> statement. Unlike a <code>for</code> loop,
<code>Ox.loop</code> doesn't leak its counter variable to the outer scope,
but returns it.
(stop, callback) -> <n> Next value
equivalent to <code>for (var i = 0; i < stop; i++)</code>
(start, stop, callback) -> <n> Next value
equivalent to <code>for (var i = start; i < stop; i++)</code> or,
if <code>start</code> is larger than <code>stop</code>,
<code>for (var i = start; i > stop; i--)</code>
(start, stop, step) -> <n> Next value
equivalent to <code>for (var i = start; i < stop; i += step)</code>
start <n> Start value
stop <n> Stop value (exclusive)
step <n> Step value
callback <f> Iterator function
i <n> Counter value
> Ox.loop(0, 3, 2, function() {})
4
> Ox.loop(10, function(i) { return i != 4; })
4
@*/
Ox.loop = function() {
var length = arguments.length,
fn = arguments[length - 1],
step = length == 4 ? arguments[2] : 1,
stop = arguments[length > 2 ? 1 : 0],
start = length > 2 ? arguments[0] : 0,
stop = arguments[length > 2 ? 1 : 0],
step = length == 4 ? arguments[2] : (start <= stop ? 1 : -1),
callback = arguments[length - 1],
i;
for (i = start; i < stop; i += step) {
fn(i);
for (i = start; step > 0 ? i < stop : i > stop; i += step) {
if (callback(i) === false) {
break;
};
}
return i;
};
Ox.makeArray = function(obj) {
/*
>>> (function() { return Ox.makeArray(arguments); }('foo', 'bar'))
['foo', 'bar']
*/
return Array.prototype.slice.call(obj);
};
/*@
Ox.makeArray <f> Takes an array-like object and returns a true array
Alias for <code>Array.prototype.slice.call</code>
(value) -> <a> True array
value <*> Array-like object
> (function() { return Ox.makeArray(arguments); }("foo", "bar"))
["foo", "bar"]
> Ox.makeArray("foo")
["f", "o", "o"]
> Ox.makeArray({0: "f", 1: "o", 2: "0", length: 3})
["f", "o", "o"]
@*/
Ox.makeArray = Array.prototype.slice.call;
Ox.makeObject = function(obj) {
/*
@ -1066,22 +1106,38 @@ Ox.merge = function(arr) {
return arr;
};
Ox.range = function(start, stop, step) {
/*
>>> Ox.range(3)
/*@
Ox.range <f> Python-style range
(stop) -> <[n]> range
Returns an array of integers from <code>0</code> (inclusive) to
<code>stop</code> (exclusive).
(start, stop) -> <[n]> range
Returns an array of integers from <code>start</code> (inclusive) to
<code>stop</code> (exclusive).
(start, stop, step) -> <[n]> range
Returns an array of numbers from <code>start</code> (inclusive) to
<code>stop</code> (exclusive), incrementing by <code>step</step>.
start <n> Start value
stop <n> Stop value
step <n> Step value
> Ox.range(3)
[0, 1, 2]
>>> Ox.range(3, 0)
> Ox.range(1, 4)
[1, 2, 3]
> Ox.range(3, 0)
[3, 2, 1]
>>> Ox.range(1, 2, 0.5)
> Ox.range(1, 2, 0.5)
[1, 1.5]
*/
stop = arguments.length > 1 ? stop : arguments[0];
start = arguments.length > 1 ? start : 0;
step = step || (start <= stop ? 1 : -1);
var arr = [], i;
for (i = start; step > 0 ? i < stop : i > stop; i += step) {
> Ox.range(-1, -2, -0.5)
[-1, -1.5]
@*/
Ox.range = function() {
var args = Ox.makeArray(arguments),
arr = [];
args.push(function(i) {
arr.push(i);
}
});
Ox.loop.apply(null, args);
return arr;
};
@ -2084,13 +2140,18 @@ Encoding functions
}
}
/*@
Ox.encodeUTF8 <f> Encodes a string as UTF-8
see http://en.wikipedia.org/wiki/UTF-8
(string) -> <s> UTF-8 encoded string
string <s> Any string
> Ox.encodeUTF8("foo")
"foo"
> Ox.encodeUTF8("¥€$")
"\u00C2\u00A5\u00E2\u0082\u00AC\u0024"
@*/
Ox.encodeUTF8 = function(str) {
/*
see http://en.wikipedia.org/wiki/UTF-8
>>> Ox.encodeUTF8('foo')
'foo'
>>> Ox.encodeUTF8('¥€$')
'\u00C2\u00A5\u00E2\u0082\u00AC\u0024'
*/
return Ox.map(str, function(chr) {
var code = chr.charCodeAt(0),
@ -2109,12 +2170,18 @@ Encoding functions
}).join('');
}
/*@
Ox.decodeUTF8 <f> Decodes an UTF-8-encoded string
see http://en.wikipedia.org/wiki/UTF-8
(utf8) -> <s> string
utf8 <s> Any UTF-8-encoded string
> Ox.decodeUTF8('foo')
'foo'
> Ox.decodeUTF8('\u00C2\u00A5\u00E2\u0082\u00AC\u0024')
'¥€$'
@*/
Ox.decodeUTF8 = function(str) {
/*
>>> Ox.decodeUTF8('foo')
'foo'
>>> Ox.decodeUTF8('\u00C2\u00A5\u00E2\u0082\u00AC\u0024')
'¥€$'
*/
var bytes = Ox.map(str, function(v) {
return v.charCodeAt(0);
@ -3208,6 +3275,49 @@ Ox.toDashes = function(str) {
});
};
Ox.minify = function(source) {
var tokens = Ox.tokenize(source)
return Ox.map(tokens, function(token, i) {
var ret = source.substr(token.offset, token.type == 'whitespace' ? 1 : token.length);
if (token.type == 'comment') {
ret = null;
} else if (
token.type == 'linebreak' && (
i == 0 || i == tokens.length - 1 ||
tokens[i - 1].type == 'linebreak' ||
tokens[i + 1].type == 'linebreak'
)
) {
ret = null;
} else if (
token.type == 'whitespace' && (
i == 0 || i == tokens.length - 1 ||
tokens[i - 1].type != 'keyword' || (
tokens[i + 1].type == 'operator'
)
)
) {
ret = null;
}
return ret;
}).join('');
};
/*@
Ox.tokenize <f> Tokenizes JavaScript
(source) -> <[o]> Array of tokens
length <n> Length of the token
offset <n> Offset of the token
type <s> Type of the token
Type can be <code>"comment"</code>, <code>"constant"</code>,
<code>"identifier"</code>, <code>"keyword"</code>,
<code>"linebreak"</code>, <code>"method"</code>,
<code>"number"</code>, <code>"object"</code>,
<code>"operator"</code>, <code>"property"</code>,
<code>"regexp"</code>, <code>"string"</code>
or <code>"whitespace"</code>
source <s> JavaScript source code
@*/
Ox.tokenize = (function() {
// see https://github.com/mozilla/narcissus/blob/master/lib/jslex.js
@ -3657,113 +3767,161 @@ Type functions
================================================================================
*/
Ox.isArguments = function(val) {
/*
>>> Ox.isArguments((function() { return arguments; }()))
/*@
Ox.isArguments <f> Tests if a value is an arguments "array"
(value) -> <b> True if the value is an arguments "array"
value <*> Any value
> Ox.isArguments((function() { return arguments; }()))
true
*/
@*/
Ox.isArguments = function(val) {
return !!(val && val.toString() == '[object Arguments]');
}
Ox.isArray = function(val) { // is in jQuery
/*
>>> Ox.isArray([])
/*@
Ox.isArray <f> Tests if a value is an array
(value) -> <b> True if the value is a date
value <*> Any value
> Ox.isArray([])
true
*/
> Ox.isArray((function() { return arguments; }()))
false
> Ox.isArray({0: 0, length: 1})
false
@*/
Ox.isArray = function(val) {
return val instanceof Array;
}
Ox.isBoolean = function(val) {
/*
>>> Ox.isBoolean(false)
/*@
Ox.isBoolean <f> Tests if a value is boolean
(value) -> <b> True if the value is boolean
value <*> Any value
> Ox.isBoolean(false)
true
*/
@*/
Ox.isBoolean = function(val) {
return typeof val == 'boolean';
};
Ox.isDate = function(val) {
/*
>>> Ox.isDate(new Date())
/*@
Ox.isDate <f> Tests if a value is a date
(value) -> <b> True if the value is a date
value <*> Any value
> Ox.isDate(new Date())
true
*/
@*/
Ox.isDate = function(val) {
return val instanceof Date;
};
Ox.isElement = function(val) {
/*
>>> Ox.isElement(document.createElement())
/*@
Ox.isElement <f> Tests if a value is a DOM element
(value) -> <b> True if the value is a DOM element
value <*> Any value
> Ox.isElement(document.createElement())
true
*/
@*/
Ox.isElement = function(val) {
return !!(val && val.nodeType == 1);
};
Ox.isFunction = function(val) { // is in jQuery
/*
>>> Ox.isFunction(function() {})
/*@
Ox.isFunction <f> Tests if a value is a function
(value) -> <b> True if the value is a function
value <*> Any value
> Ox.isFunction(function() {})
true
>>> Ox.isFunction(/ /)
> Ox.isFunction(/ /)
false
*/
@*/
Ox.isFunction = function(val) { // is in jQuery
return typeof val == 'function' && !Ox.isRegExp(val);
};
Ox.isInfinity = function(val) {
/*
>>> Ox.isInfinity(Infinity)
/*@
Ox.isInfinity <f> Tests if a value is infinite
(value) -> <b> True if the value is infinite
value <*> Any value
> Ox.isInfinity(Infinity)
true
>>> Ox.isInfinity(-Infinity)
> Ox.isInfinity(-Infinity)
true
>>> Ox.isInfinity(NaN)
> Ox.isInfinity(NaN)
false
*/
@*/
Ox.isInfinity = function(val) {
return typeof val == 'number' && !isFinite(val) && !Ox.isNaN(val);
};
Ox.isNaN = function(val) {
/*
>>> Ox.isNaN(NaN)
/*@
Ox.isNaN <f> Tests if a value is "Not a Number"
(value) -> <b> True if the value is "Not a Number"
value <*> Any value
> Ox.isNaN(NaN)
true
*/
@*/
Ox.isNaN = function(val) {
return val !== val;
}
Ox.isNull = function(val) {
/*
>>> Ox.isNull(null)
/*@
Ox.isNull <f> Tests if a value is <code>null</code>
(value) -> <b> True if the value is <code>null</null>
value <*> Any value
> Ox.isNull(null)
true
*/
@*/
Ox.isNull = function(val) {
return val === null;
};
Ox.isNumber = function(val) {
/*
>>> Ox.isNumber(0)
/*@
Ox.isNumber <f> Tests if a value is a number
(value) -> <b> True if the value is a number
value <*> Any value
> Ox.isNumber(0)
true
>>> Ox.isNumber(Infinity)
> Ox.isNumber(Infinity)
false
>>> Ox.isNumber(-Infinity)
> Ox.isNumber(-Infinity)
false
>>> Ox.isNumber(NaN)
> Ox.isNumber(NaN)
false
*/
@*/
Ox.isNumber = function(val) {
return typeof val == 'number' && isFinite(val);
};
Ox.isObject = function(val) {
/*
>>> Ox.isObject({})
/*@
Ox.isObject <f> Tests if a value is a an object
(value) -> <b> True if the value is an object
value <*> Any value
> Ox.isObject({})
true
>>> Ox.isObject([])
> Ox.isObject([])
false
>>> Ox.isObject(new Date())
> Ox.isObject(new Date())
false
>>> Ox.isObject(null)
> Ox.isObject(null)
false
*/
@*/
Ox.isObject = function(val) {
return typeof val == 'object' && !Ox.isArguments(val) &&
!Ox.isArray(val) && !Ox.isDate(val) && !Ox.isNull(val);
};
/*@
Ox.isRegExp <f> Tests if a value is a regular expression
(value) -> <b> True if the value is a regular expression
value <*> Any value
> Ox.isRegExp(/ /)
true
@*/
Ox.isRegExp = function(val) {
/*
>>> Ox.isRegExp(/ /)
@ -3772,24 +3930,28 @@ Ox.isRegExp = function(val) {
return val instanceof RegExp;
};
Ox.isString = function(val) {
/*
>>> Ox.isString('')
/*@
Ox.isString <f> Tests if a value is a string
(value) -> <b> True if the value is a string
value <*> Any value
> Ox.isString('')
true
*/
@*/
Ox.isString = function(val) {
return typeof val == 'string';
};
/*@
Ox.isUndefined <f> Tests if a value is undefined
(value) -> <b> If true, the value is undefined
value <*> any value
(value) -> <b> True if the value is undefined
value <*> Any value
> Ox.isUndefined()
true
@*/
Ox.isUndefined = function(val) {
// fixme: void 0 is also nice
// fixme: val === void 0 is also nice
return typeof val == 'undefined';
};