better Ox.isEqual(), more tests, more documentation
This commit is contained in:
parent
a1ed6a44c5
commit
37219bfbe9
5 changed files with 466 additions and 252 deletions
|
@ -63,8 +63,8 @@ Ox.load('UI', {
|
||||||
.html(
|
.html(
|
||||||
Ox.repeat(' ', 4) +
|
Ox.repeat(' ', 4) +
|
||||||
'<b>> ' + Ox.encodeHTML(test.statement) + ' </b> ==> ' +
|
'<b>> ' + Ox.encodeHTML(test.statement) + ' </b> ==> ' +
|
||||||
Ox.encodeHTML(test.actual) +
|
(test.success ? '' : Ox.encodeHTML(test.actual) + ' !=> ') +
|
||||||
(test.success ? '' : ' !=> ' + Ox.encodeHTML(test.expected))
|
Ox.encodeHTML(test.expected)
|
||||||
)
|
)
|
||||||
.hide()
|
.hide()
|
||||||
.appendTo($foo);
|
.appendTo($foo);
|
||||||
|
@ -78,7 +78,10 @@ Ox.load('UI', {
|
||||||
height: '15px',
|
height: '15px',
|
||||||
padding: '4px 8px 4px 8px',
|
padding: '4px 8px 4px 8px',
|
||||||
fontFamily: 'Menlo, Monaco, Courier',
|
fontFamily: 'Menlo, Monaco, Courier',
|
||||||
fontSize: '12px'
|
fontSize: '12px',
|
||||||
|
whiteSpace: 'nowrap',
|
||||||
|
MozUserSelect: 'text',
|
||||||
|
WebkitUserSelect: 'text'
|
||||||
});
|
});
|
||||||
gradients.forEach(function(gradient) {
|
gradients.forEach(function(gradient) {
|
||||||
$div.css({
|
$div.css({
|
||||||
|
|
|
@ -254,6 +254,18 @@ Dialog
|
||||||
cursor: se-resize;
|
cursor: se-resize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
================================================================================
|
||||||
|
Documentation
|
||||||
|
================================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
.OxDocPage code {
|
||||||
|
//border: 1px solid rgb(232, 232, 232);
|
||||||
|
//background: rgb(248, 248, 248);
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
================================================================================
|
================================================================================
|
||||||
Drag & Drop
|
Drag & Drop
|
||||||
|
|
|
@ -6,7 +6,7 @@ Ox.DocPage = function(options, self) {
|
||||||
item: {}
|
item: {}
|
||||||
})
|
})
|
||||||
.options(options || {})
|
.options(options || {})
|
||||||
.addClass('OxText')
|
.addClass('OxDocPage OxText')
|
||||||
.css({
|
.css({
|
||||||
overflow: 'auto'
|
overflow: 'auto'
|
||||||
});
|
});
|
||||||
|
@ -42,8 +42,13 @@ Ox.DocPage = function(options, self) {
|
||||||
if (item[section]) {
|
if (item[section]) {
|
||||||
if (section == 'description') {
|
if (section == 'description') {
|
||||||
$elements.push($('<div>')
|
$elements.push($('<div>')
|
||||||
.css({paddingLeft: (level * 32) + 'px'})
|
.css({
|
||||||
.html(item.description)
|
paddingTop: (level ? 0 : 8) + 'px',
|
||||||
|
borderTop: level ? '': '1px solid rgb(192, 192, 192)',
|
||||||
|
marginTop: (level ? 0 : 8) + 'px',
|
||||||
|
marginLeft: (level * 32) + 'px',
|
||||||
|
})
|
||||||
|
.html(Ox.parseHTML(item.description))
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
$elements.push($('<div>')
|
$elements.push($('<div>')
|
||||||
|
@ -108,7 +113,7 @@ Ox.DocPage = function(options, self) {
|
||||||
.addClass(className)
|
.addClass(className)
|
||||||
.css({marginLeft: (level * 32 + 16) + 'px'})
|
.css({marginLeft: (level * 32 + 16) + 'px'})
|
||||||
.html(
|
.html(
|
||||||
'<code>' + Ox.parseHTML(example.result) + '</code>'
|
'<code>' + Ox.encodeHTML(example.result) + '</code>'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
|
@ -39,7 +39,7 @@ Ox.SyntaxHighlighter = function(options, self) {
|
||||||
!(self.options.stripComments && token.type == 'comment')
|
!(self.options.stripComments && token.type == 'comment')
|
||||||
) {
|
) {
|
||||||
classNames = 'Ox' + Ox.toTitleCase(token.type);
|
classNames = 'Ox' + Ox.toTitleCase(token.type);
|
||||||
if (token.type == 'whitespace') {
|
if (self.options.showWhitespace && token.type == 'whitespace') {
|
||||||
if (isAfterLinebreak() && hasIrregularSpaces()) {
|
if (isAfterLinebreak() && hasIrregularSpaces()) {
|
||||||
classNames += ' OxLeading'
|
classNames += ' OxLeading'
|
||||||
} else if (isBeforeLinebreak()) {
|
} else if (isBeforeLinebreak()) {
|
||||||
|
@ -65,27 +65,15 @@ Ox.SyntaxHighlighter = function(options, self) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
self.lines = self.source.split('<br/>');
|
self.lines = self.source.split('<br/>');
|
||||||
self.lineNumbersWidth = (self.lines.length + self.options.offset - 1).toString().length * 7;
|
self.lineNumbersWidth = (
|
||||||
self.sourceCodeWidth = 80 * 7 + (
|
self.lines.length + self.options.offset - 1
|
||||||
self.lines.length > 40 ? Ox.UI.SCROLLBAR_SIZE : 0
|
).toString().length * 7;
|
||||||
);
|
|
||||||
self.height = 40 * 14 + (
|
|
||||||
Math.max.apply(null, self.lines.map(function(line) {
|
|
||||||
return line.length;
|
|
||||||
})) > 80 ? Ox.UI.SCROLLBAR_SIZE : 0
|
|
||||||
);
|
|
||||||
|
|
||||||
that.css({
|
|
||||||
//width: self.lineNumbersWidth + self.sourceCodeWidth,
|
|
||||||
//height: self.height
|
|
||||||
});
|
|
||||||
|
|
||||||
self.$lineNumbers = new Ox.Element()
|
self.$lineNumbers = new Ox.Element()
|
||||||
.addClass('OxLineNumbers')
|
.addClass('OxLineNumbers')
|
||||||
.css({
|
.css({
|
||||||
display: 'table-cell',
|
display: 'table-cell',
|
||||||
width: self.lineNumbersWidth + 'px',
|
width: self.lineNumbersWidth + 'px',
|
||||||
//height: (self.lines.length * 14) + 8 + 'px',
|
|
||||||
padding: '4px',
|
padding: '4px',
|
||||||
})
|
})
|
||||||
.html(
|
.html(
|
||||||
|
@ -98,8 +86,6 @@ Ox.SyntaxHighlighter = function(options, self) {
|
||||||
.addClass('OxSourceCode')
|
.addClass('OxSourceCode')
|
||||||
.css({
|
.css({
|
||||||
display: 'table-cell',
|
display: 'table-cell',
|
||||||
//width: self.sourceCodeWidth + 'px',
|
|
||||||
//height: (self.lines.length * 14) + 'px',
|
|
||||||
padding: '4px'
|
padding: '4px'
|
||||||
})
|
})
|
||||||
.html(self.source)
|
.html(self.source)
|
||||||
|
|
660
source/Ox.js
660
source/Ox.js
|
@ -2,6 +2,34 @@
|
||||||
|
|
||||||
// OxJS (c) 2011 Ox2620, dual-licensed GPL/MIT, see http://oxjs.org for details
|
// OxJS (c) 2011 Ox2620, dual-licensed GPL/MIT, see http://oxjs.org for details
|
||||||
|
|
||||||
|
/*
|
||||||
|
Some conventions:
|
||||||
|
Functions
|
||||||
|
- only one var statement, in the first line of the function
|
||||||
|
- return only once, from the last line of the function body
|
||||||
|
Variable names
|
||||||
|
arg argument
|
||||||
|
args arguments
|
||||||
|
arr array
|
||||||
|
callback callback function
|
||||||
|
col collection (array, string or object)
|
||||||
|
date date
|
||||||
|
fn function
|
||||||
|
hasFoo boolean
|
||||||
|
i index (integer key)
|
||||||
|
isFoo boolean
|
||||||
|
k key (of a key/value pair)
|
||||||
|
key key (of a key/value pair)
|
||||||
|
max maximum value
|
||||||
|
min minumum value
|
||||||
|
num number
|
||||||
|
obj object
|
||||||
|
re regexp
|
||||||
|
ret return value
|
||||||
|
v value (of a key/value pair)
|
||||||
|
val value (of a key/value pair)
|
||||||
|
*/
|
||||||
|
|
||||||
// todo: check http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/
|
// todo: check http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/
|
||||||
// also see https://github.com/tlrobinson/narwhal/blob/master/lib/util.js
|
// also see https://github.com/tlrobinson/narwhal/blob/master/lib/util.js
|
||||||
|
|
||||||
|
@ -164,6 +192,41 @@ Ox.merge = function(arr) {
|
||||||
return arr;
|
return arr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*@
|
||||||
|
Ox.sort <f> Sorts an array, handling leading digits and ignoring capitalization
|
||||||
|
> Ox.sort(['10', '9', 'B', 'a'])
|
||||||
|
['9', '10', 'a', 'B']
|
||||||
|
@*/
|
||||||
|
Ox.sort = function(arr) {
|
||||||
|
var len, matches = {}, sort = {};
|
||||||
|
// find leading numbers
|
||||||
|
arr.forEach(function(val, i) {
|
||||||
|
var match = /^\d+/(val);
|
||||||
|
matches[val] = match ? match[0] : '';
|
||||||
|
});
|
||||||
|
// get length of longest leading number
|
||||||
|
len = Ox.max(Ox.map(matches, function(val) {
|
||||||
|
return val.length;
|
||||||
|
}));
|
||||||
|
// pad leading numbers, and make lower case
|
||||||
|
arr.forEach(function(val) {
|
||||||
|
sort[val] = (
|
||||||
|
matches[val] ?
|
||||||
|
Ox.pad(matches[val], len) + val.toString().substr(matches[val].length) :
|
||||||
|
val
|
||||||
|
).toLowerCase();
|
||||||
|
});
|
||||||
|
return arr.sort(function(a, b) {
|
||||||
|
var ret = 0;
|
||||||
|
if (sort[a] < sort[b]) {
|
||||||
|
ret = -1;
|
||||||
|
} else if (sort[a] > sort[b]) {
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/*@
|
/*@
|
||||||
Ox.unique <f> Returns an array without duplicate values
|
Ox.unique <f> Returns an array without duplicate values
|
||||||
> Ox.unique([1, 2, 3, 2, 1])
|
> Ox.unique([1, 2, 3, 2, 1])
|
||||||
|
@ -473,7 +536,7 @@ Ox.getset = function(obj, args, callback, context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*@
|
/*@
|
||||||
Ox.isEmpty <f> Returns true if an array, object or string is empty
|
Ox.isEmpty <f> Returns true if a collection is empty
|
||||||
> Ox.isEmpty([])
|
> Ox.isEmpty([])
|
||||||
true
|
true
|
||||||
> Ox.isEmpty({})
|
> Ox.isEmpty({})
|
||||||
|
@ -486,7 +549,7 @@ Ox.isEmpty = function(val) {
|
||||||
};
|
};
|
||||||
|
|
||||||
/*@
|
/*@
|
||||||
Ox.keys <f> Returns the keys of an array, object or string
|
Ox.keys <f> Returns the keys of a collection
|
||||||
Unlike <code>Object.keys()</code>, <code>Ox.keys()</code> works for arrays,
|
Unlike <code>Object.keys()</code>, <code>Ox.keys()</code> works for arrays,
|
||||||
objects and strings.
|
objects and strings.
|
||||||
> Ox.keys([1, 2, 3])
|
> Ox.keys([1, 2, 3])
|
||||||
|
@ -502,7 +565,6 @@ Ox.keys <f> Returns the keys of an array, object or string
|
||||||
@*/
|
@*/
|
||||||
|
|
||||||
// fixme: is this really needed? arrays... ok... but strings??
|
// fixme: is this really needed? arrays... ok... but strings??
|
||||||
|
|
||||||
Ox.keys = function(obj) {
|
Ox.keys = function(obj) {
|
||||||
var keys = [];
|
var keys = [];
|
||||||
Ox.forEach(obj, function(v, k) {
|
Ox.forEach(obj, function(v, k) {
|
||||||
|
@ -727,27 +789,20 @@ Ox.range = function() {
|
||||||
return arr;
|
return arr;
|
||||||
};
|
};
|
||||||
|
|
||||||
Ox.serialize = function(obj) {
|
/*@
|
||||||
/*
|
Ox.setPropertyOnce <f> Sets a property once
|
||||||
>>> Ox.serialize({a: 1, b: 2, c: 3})
|
Given a array of objects, each of which has a property with a boolean
|
||||||
'a=1&b=2&c=3'
|
value, this sets exactly one of these to true, and returns the index
|
||||||
*/
|
of the object whose property is true.
|
||||||
var arr = [];
|
> Ox.setPropertyOnce([{selected: false}, {selected: false}], 'selected')
|
||||||
Ox.forEach(obj, function(val, key) {
|
|
||||||
val !== '' && arr.push(key + '=' + val);
|
|
||||||
});
|
|
||||||
return arr.join('&');
|
|
||||||
};
|
|
||||||
|
|
||||||
Ox.setPropertyOnce = function(arr, str) {
|
|
||||||
/*
|
|
||||||
>>> Ox.setPropertyOnce([{selected: false}, {selected: false}], 'selected')
|
|
||||||
0
|
0
|
||||||
>>> Ox.setPropertyOnce([{selected: false}, {selected: true}], 'selected')
|
> Ox.setPropertyOnce([{selected: false}, {selected: true}], 'selected')
|
||||||
1
|
1
|
||||||
>>> Ox.setPropertyOnce([{selected: true}, {selected: true}], 'selected')
|
> Ox.setPropertyOnce([{selected: true}, {selected: true}], 'selected')
|
||||||
0
|
0
|
||||||
*/
|
@*/
|
||||||
|
// fixme: strange name, and shouldn't it return the full array?
|
||||||
|
Ox.setPropertyOnce = function(arr, str) {
|
||||||
var pos = -1;
|
var pos = -1;
|
||||||
Ox.forEach(arr, function(v, i) {
|
Ox.forEach(arr, function(v, i) {
|
||||||
if (pos == -1 && arr[i][str]) {
|
if (pos == -1 && arr[i][str]) {
|
||||||
|
@ -763,74 +818,72 @@ Ox.setPropertyOnce = function(arr, str) {
|
||||||
return pos;
|
return pos;
|
||||||
};
|
};
|
||||||
|
|
||||||
Ox.shuffle = function(arr) {
|
/*@
|
||||||
/*
|
Ox.shuffle <f> Randomizes the order of values within a collection
|
||||||
>>> Ox.shuffle([1, 2, 3]).length
|
> Ox.shuffle([1, 2, 3]).length
|
||||||
3
|
3
|
||||||
*/
|
> Ox.len(Ox.shuffle({a: 1, b: 2, c: 3}))
|
||||||
var shuffle = arr;
|
3
|
||||||
return shuffle.sort(function() {
|
> Ox.shuffle('123').length
|
||||||
|
3
|
||||||
|
@*/
|
||||||
|
|
||||||
|
Ox.shuffle = function(col) {
|
||||||
|
var keys, ret, type = Ox.typeOf(col), values;
|
||||||
|
function sort() {
|
||||||
return Math.random() - 0.5;
|
return Math.random() - 0.5;
|
||||||
});
|
}
|
||||||
|
if (type == 'array') {
|
||||||
|
ret = col.sort(sort);
|
||||||
|
} else if (type == 'object') {
|
||||||
|
keys = Object.keys(col);
|
||||||
|
values = Ox.values(col).sort(sort);
|
||||||
|
ret = {};
|
||||||
|
keys.forEach(function(key, i) {
|
||||||
|
ret[key] = values[i]
|
||||||
|
});
|
||||||
|
} else if (type == 'string') {
|
||||||
|
ret = col.split('').sort(sort).join('');
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*@
|
||||||
|
Ox.some <f> Tests if one or more elements of a collection satisfy a given condition
|
||||||
|
Unlike <code>[].some()</code>, <code>Ox.some()</code> works for arrays,
|
||||||
|
objects and strings.
|
||||||
|
> Ox.some([2, 1, 0], function(i, v) { return i == v; })
|
||||||
|
true
|
||||||
|
> Ox.some({a: 1, b: 2, c: 3}, function(v) { return v == 1; })
|
||||||
|
true
|
||||||
|
> Ox.some("foo", function(v) { return v == 'f'; })
|
||||||
|
true
|
||||||
|
@*/
|
||||||
Ox.some = function(obj, fn) {
|
Ox.some = function(obj, fn) {
|
||||||
/*
|
|
||||||
Ox.some() works for arrays, objects and strings, unlike [].some()
|
|
||||||
>>> Ox.some([2, 1, 0], function(i, v) { return i == v; })
|
|
||||||
true
|
|
||||||
>>> Ox.some({a: 1, b: 2, c: 3}, function(v) { return v == 1; })
|
|
||||||
true
|
|
||||||
>>> Ox.some("foo", function(v) { return v == 'f'; })
|
|
||||||
true
|
|
||||||
*/
|
|
||||||
return Ox.filter(Ox.values(obj), fn).length > 0;
|
return Ox.filter(Ox.values(obj), fn).length > 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
Ox.sort = function(arr) {
|
/*@
|
||||||
/*
|
Ox.sum <f> Returns the sum of the values of a collection
|
||||||
>>> Ox.sort(['10', '9', 'B', 'a'])
|
> Ox.sum(1, 2, 3)
|
||||||
['9', '10', 'a', 'B']
|
|
||||||
*/
|
|
||||||
var len, matches = {}, sort = {};
|
|
||||||
// find leading numbers
|
|
||||||
arr.forEach(function(val, i) {
|
|
||||||
var match = /^\d+/(val);
|
|
||||||
matches[val] = match ? match[0] : '';
|
|
||||||
});
|
|
||||||
// get length of longest leading number
|
|
||||||
len = Ox.max(Ox.map(matches, function(val) {
|
|
||||||
return val.length;
|
|
||||||
}));
|
|
||||||
// pad leading numbers, and make lower case
|
|
||||||
arr.forEach(function(val) {
|
|
||||||
sort[val] = (
|
|
||||||
matches[val] ?
|
|
||||||
Ox.pad(matches[val], len) + val.toString().substr(matches[val].length) :
|
|
||||||
val
|
|
||||||
).toLowerCase();
|
|
||||||
});
|
|
||||||
return arr.sort(function(a, b) {
|
|
||||||
var ret = 0;
|
|
||||||
if (sort[a] < sort[b]) {
|
|
||||||
ret = -1;
|
|
||||||
} else if (sort[a] > sort[b]) {
|
|
||||||
ret = 1;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
Ox.sum = function(obj) {
|
|
||||||
/*
|
|
||||||
>>> Ox.sum([-1, 0, 1])
|
|
||||||
0
|
|
||||||
>>> Ox.sum({a: 1, b: 2, c: 3})
|
|
||||||
6
|
6
|
||||||
*/
|
> Ox.sum([1, 2, 3])
|
||||||
|
6
|
||||||
|
> Ox.sum({a: 1, b: 2, c: 3})
|
||||||
|
6
|
||||||
|
> Ox.sum('123')
|
||||||
|
6
|
||||||
|
> Ox.sum('123foo')
|
||||||
|
6
|
||||||
|
> Ox.sum('08', -2, 'foo')
|
||||||
|
6
|
||||||
|
@*/
|
||||||
|
Ox.sum = function(col) {
|
||||||
var sum = 0;
|
var sum = 0;
|
||||||
Ox.forEach(obj, function(val) {
|
col = arguments.length > 1 ? Ox.makeArray(arguments) : col;
|
||||||
sum += val;
|
Ox.forEach(col, function(val) {
|
||||||
|
val = +val;
|
||||||
|
sum += Ox.isNumber(val) ? val : 0;
|
||||||
});
|
});
|
||||||
return sum;
|
return sum;
|
||||||
};
|
};
|
||||||
|
@ -854,43 +907,39 @@ Ox.toArray = function(obj) {
|
||||||
return arr;
|
return arr;
|
||||||
};
|
};
|
||||||
|
|
||||||
Ox.unserialize = function(str) {
|
/*@
|
||||||
/*
|
Ox.values <f> Returns the values of a collection
|
||||||
>>> Ox.unserialize('a=1&b=2&c=3').c
|
> Ox.values([1, 2, 3])
|
||||||
'3'
|
|
||||||
*/
|
|
||||||
var arr, obj = {};
|
|
||||||
Ox.forEach(str.split('&'), function(val) {
|
|
||||||
arr = val.split('=');
|
|
||||||
obj[arr[0]] = arr[1];
|
|
||||||
});
|
|
||||||
return obj;
|
|
||||||
};
|
|
||||||
|
|
||||||
Ox.values = function(obj) {
|
|
||||||
/*
|
|
||||||
>>> Ox.values([1, 2, 3])
|
|
||||||
[1, 2, 3]
|
[1, 2, 3]
|
||||||
>>> Ox.values({a: 1, b: 2, c: 3})
|
> Ox.values({a: 1, b: 2, c: 3})
|
||||||
[1, 2, 3]
|
[1, 2, 3]
|
||||||
>>> Ox.values('abc')
|
> Ox.values('abc')
|
||||||
['a', 'b', 'c']
|
['a', 'b', 'c']
|
||||||
>>> Ox.values([1,])
|
> Ox.values([1,,3])
|
||||||
[1]
|
[1, 3]
|
||||||
*/
|
@*/
|
||||||
// fixme: why doesn't this use map?
|
Ox.values = function(col) {
|
||||||
|
// this happens to works for arrays and strings, but still:
|
||||||
|
// Ox.values(arr) -> arr, Ox.values(str) -> str.split('')
|
||||||
var values = [];
|
var values = [];
|
||||||
Ox.forEach(obj, function(val) {
|
Ox.forEach(col, function(val) {
|
||||||
values.push(val);
|
values.push(val);
|
||||||
});
|
});
|
||||||
return values;
|
return values;
|
||||||
};
|
};
|
||||||
|
|
||||||
Ox.walk = function(obj, fn) {
|
/*@
|
||||||
/*
|
Ox.walk <f> Recursively walk a tree-like key/value store
|
||||||
>>> a = 0; Ox.walk({a: 1, b: {c: 2, d: 3}}, function(v, k) { a += Ox.isNumber(v) ? v : 0}); a
|
<script>
|
||||||
|
Ox.test.number = 0;
|
||||||
|
Ox.walk({a: 1, b: {c: 2, d: 3}}, function (v) {
|
||||||
|
Ox.test.number += Ox.isNumber(v) ? v : 0;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
> Ox.test.number
|
||||||
6
|
6
|
||||||
*/
|
@*/
|
||||||
|
Ox.walk = function(obj, fn) {
|
||||||
Ox.forEach(obj, function(val, key) {
|
Ox.forEach(obj, function(val, key) {
|
||||||
fn(val, key, obj);
|
fn(val, key, obj);
|
||||||
Ox.walk(obj[key], fn);
|
Ox.walk(obj[key], fn);
|
||||||
|
@ -2788,6 +2837,7 @@ Ox.doc <f> Generates documentation for annotated JavaScript
|
||||||
@*/
|
@*/
|
||||||
|
|
||||||
Ox.doc = (function() {
|
Ox.doc = (function() {
|
||||||
|
// fixme: dont require the trailing '@'
|
||||||
var re = {
|
var re = {
|
||||||
item: /^(.+?) <(.+?)> (.+)$/,
|
item: /^(.+?) <(.+?)> (.+)$/,
|
||||||
multiline: /^\/\*\@.*?\n([\w\W]+)\n.*?\@\*\/$/,
|
multiline: /^\/\*\@.*?\n([\w\W]+)\n.*?\@\*\/$/,
|
||||||
|
@ -2886,6 +2936,7 @@ Ox.doc = (function() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
function parseTokens(tokens, includeLeading) {
|
function parseTokens(tokens, includeLeading) {
|
||||||
|
// fixme: do not strip whitespace from the beginning of the first line of the items' source
|
||||||
var leading = [],
|
var leading = [],
|
||||||
tokens_ = [];
|
tokens_ = [];
|
||||||
tokens.forEach(function(token) {
|
tokens.forEach(function(token) {
|
||||||
|
@ -3079,7 +3130,7 @@ Ox.test = function(file, callback) {
|
||||||
var actual = eval(example.statement);
|
var actual = eval(example.statement);
|
||||||
if (example.result) {
|
if (example.result) {
|
||||||
tests.push({
|
tests.push({
|
||||||
actual: actual,
|
actual: JSON.stringify(actual),
|
||||||
expected: example.result,
|
expected: example.result,
|
||||||
name: item.name,
|
name: item.name,
|
||||||
section: item.section,
|
section: item.section,
|
||||||
|
@ -3174,18 +3225,19 @@ Ox.tokenize = (function() {
|
||||||
'shift', 'slice', 'some', 'sort', 'splice',
|
'shift', 'slice', 'some', 'sort', 'splice',
|
||||||
'unshift',
|
'unshift',
|
||||||
// Date
|
// Date
|
||||||
'getDate', 'getDay', 'getFullYear', 'getHours', 'getMilliseconds',
|
'getDate', 'getDay', 'getFullYear', 'getHours',
|
||||||
'getMinutes', 'getMonth', 'getSeconds', 'getTime', 'getTimezoneOffset',
|
'getMilliseconds', 'getMinutes', 'getMonth', 'getSeconds',
|
||||||
'getUTCDate', 'getUTCDay', 'getUTCFullYear', 'getUTCHours', 'getUTCMilliseconds',
|
'getTime', 'getTimezoneOffset',
|
||||||
'getUTCMinutes', 'getUTCMonth', 'getUTCSeconds',
|
'getUTCDate', 'getUTCDay', 'getUTCFullYear', 'getUTCHours',
|
||||||
|
'getUTCMilliseconds', 'getUTCMinutes', 'getUTCMonth', 'getUTCSeconds',
|
||||||
'now',
|
'now',
|
||||||
'parse',
|
'parse',
|
||||||
'setDate', 'setFullYear', 'setHours', 'setMilliseconds', 'setMinutes',
|
'setDate', 'setFullYear', 'setHours', 'setMilliseconds',
|
||||||
'setMonth', 'setSeconds', 'setTime',
|
'setMinutes', 'setMonth', 'setSeconds', 'setTime',
|
||||||
'setUTCDate', 'setUTCFullYear', 'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes',
|
'setUTCDate', 'setUTCFullYear', 'setUTCHours', 'setUTCMilliseconds',
|
||||||
'setUTCMonth', 'setUTCSeconds',
|
'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds',
|
||||||
'toDateString', 'toJSON', 'toLocaleDateString', 'toLocaleString', 'toLocaleTimeString',
|
'toDateString', 'toJSON', 'toLocaleDateString', 'toLocaleString',
|
||||||
'toTimeString', 'toUTCString',
|
'toLocaleTimeString', 'toTimeString', 'toUTCString',
|
||||||
'UTC',
|
'UTC',
|
||||||
// Function
|
// Function
|
||||||
'apply', 'bind', 'call', 'isGenerator',
|
'apply', 'bind', 'call', 'isGenerator',
|
||||||
|
@ -3226,7 +3278,22 @@ Ox.tokenize = (function() {
|
||||||
'match',
|
'match',
|
||||||
'replace',
|
'replace',
|
||||||
'search', 'slice', 'split', 'substr', 'substring',
|
'search', 'slice', 'split', 'substr', 'substring',
|
||||||
'toLocaleLowerCase', 'toLocaleUpperCase', 'toLowerCase', 'toUpperCase', 'trim'
|
'toLocaleLowerCase', 'toLocaleUpperCase', 'toLowerCase', 'toUpperCase', 'trim',
|
||||||
|
// Window
|
||||||
|
'addEventListener', 'alert', 'atob',
|
||||||
|
'blur', 'btoa',
|
||||||
|
'clearInterval', 'clearTimeout', 'close', 'confirm',
|
||||||
|
'dispatchEvent',
|
||||||
|
'escape',
|
||||||
|
'find', 'focus',
|
||||||
|
'getComputedStyle', 'getSelection',
|
||||||
|
'moveBy', 'moveTo',
|
||||||
|
'open',
|
||||||
|
'postMessage', 'print', 'prompt',
|
||||||
|
'removeEventListener', 'resizeBy', 'resizeTo',
|
||||||
|
'scroll', 'scrollBy', 'scrollTo',
|
||||||
|
'setCursor', 'setInterval', 'setTimeout', 'stop',
|
||||||
|
'unescape'
|
||||||
],
|
],
|
||||||
object: [
|
object: [
|
||||||
'Array',
|
'Array',
|
||||||
|
@ -3250,8 +3317,24 @@ Ox.tokenize = (function() {
|
||||||
// Function
|
// Function
|
||||||
'constructor', 'length', 'prototype',
|
'constructor', 'length', 'prototype',
|
||||||
// RegExp
|
// RegExp
|
||||||
'global', 'ignoreCase', 'lastIndex', 'multiline', 'source'
|
'global', 'ignoreCase', 'lastIndex', 'multiline', 'source',
|
||||||
|
// Window
|
||||||
|
'applicationCache',
|
||||||
|
'closed', 'content', 'crypto',
|
||||||
|
'defaultStatus', 'document',
|
||||||
|
'frameElement', 'frames',
|
||||||
|
'history',
|
||||||
|
'innerHeight', 'innerWidth',
|
||||||
|
'length', 'location', 'locationbar', 'localStorage',
|
||||||
|
'menubar',
|
||||||
|
'name', 'navigator',
|
||||||
|
'opener', 'outerHeight', 'outerWidth',
|
||||||
|
'pageXOffset', 'pageYOffset', 'parent', 'personalbar',
|
||||||
|
'screen', 'screenX', 'screenY', 'scrollbars', 'scrollX', 'scrollY',
|
||||||
|
'self', 'sessionStorage', 'status', 'statusbar',
|
||||||
|
'toolbar', 'top'
|
||||||
]
|
]
|
||||||
|
// Window stuff? 'atob', 'btoa', 'console', 'document' ...
|
||||||
};
|
};
|
||||||
|
|
||||||
return function(source) {
|
return function(source) {
|
||||||
|
@ -3272,7 +3355,7 @@ Ox.tokenize = (function() {
|
||||||
},
|
},
|
||||||
identifier: function() {
|
identifier: function() {
|
||||||
var str;
|
var str;
|
||||||
while (identifier.indexOf(source[++cursor]) > -1) {}
|
while ((identifier + number).indexOf(source[++cursor]) > -1) {}
|
||||||
str = source.substring(start, cursor);
|
str = source.substring(start, cursor);
|
||||||
Ox.forEach(word, function(value, key) {
|
Ox.forEach(word, function(value, key) {
|
||||||
if (value.indexOf(str) > -1) {
|
if (value.indexOf(str) > -1) {
|
||||||
|
@ -3419,6 +3502,7 @@ Ox.divideInt <f> Divides a number by another and returns an array of integers
|
||||||
[16, 16, 17, 17, 17, 17]
|
[16, 16, 17, 17, 17, 17]
|
||||||
@*/
|
@*/
|
||||||
Ox.divideInt = function(num, by) {
|
Ox.divideInt = function(num, by) {
|
||||||
|
// fixme: for loops are so C ;)
|
||||||
var arr = [],
|
var arr = [],
|
||||||
div = parseInt(num / by),
|
div = parseInt(num / by),
|
||||||
mod = num % by,
|
mod = num % by,
|
||||||
|
@ -3550,6 +3634,34 @@ Ox.extend = function() {
|
||||||
return obj;
|
return obj;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*@
|
||||||
|
Ox.serialize <f> Parses an object into query parameters
|
||||||
|
> Ox.serialize({a: 1, b: 2, c: 3})
|
||||||
|
'a=1&b=2&c=3'
|
||||||
|
@*/
|
||||||
|
Ox.serialize = function(obj) {
|
||||||
|
var arr = [];
|
||||||
|
Ox.forEach(obj, function(val, key) {
|
||||||
|
arr.push(key + '=' + val);
|
||||||
|
});
|
||||||
|
return arr.join('&');
|
||||||
|
};
|
||||||
|
|
||||||
|
/*@
|
||||||
|
Ox.unserialize <f> Parses query parameters into an object
|
||||||
|
> Ox.unserialize('a=1&b=2&c=3')
|
||||||
|
{a: 1, b: 2, c: 3}
|
||||||
|
@*/
|
||||||
|
Ox.unserialize = function(str) {
|
||||||
|
var obj = {};
|
||||||
|
Ox.forEach(str.split('&'), function(val) {
|
||||||
|
var arr = val.split('='),
|
||||||
|
num = +arr[1];
|
||||||
|
obj[arr[0]] = Ox.isNumber(num) ? num : arr[1];
|
||||||
|
});
|
||||||
|
return obj;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
================================================================================
|
================================================================================
|
||||||
RegExp functions
|
RegExp functions
|
||||||
|
@ -3684,7 +3796,7 @@ Ox.loadFile = (function() {
|
||||||
|
|
||||||
Ox.basename = function(str) {
|
Ox.basename = function(str) {
|
||||||
/*
|
/*
|
||||||
fixme: this should go into Path functions
|
fixme: deprecate
|
||||||
>>> Ox.basename("foo/bar/foo.bar")
|
>>> Ox.basename("foo/bar/foo.bar")
|
||||||
"foo.bar"
|
"foo.bar"
|
||||||
>>> Ox.basename("foo.bar")
|
>>> Ox.basename("foo.bar")
|
||||||
|
@ -3693,6 +3805,10 @@ Ox.basename = function(str) {
|
||||||
return str.replace(/^.*[\/\\]/g, '');
|
return str.replace(/^.*[\/\\]/g, '');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*@
|
||||||
|
Ox.char <f> Alias for String.fromCharCode
|
||||||
|
@*/
|
||||||
|
// fixme: add some mapping? like Ox.char(9, 13) or Ox.char([9, 13])?
|
||||||
Ox.char = String.fromCharCode;
|
Ox.char = String.fromCharCode;
|
||||||
|
|
||||||
Ox.clean = function(str) {
|
Ox.clean = function(str) {
|
||||||
|
@ -3723,11 +3839,15 @@ Ox.contains = function(str, chr) {
|
||||||
return str.indexOf(chr) > -1;
|
return str.indexOf(chr) > -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
Ox.endsWith = function(str, sub) {
|
/*@
|
||||||
/*
|
Ox.endsWith <f> Checks if a string ends with a given substring
|
||||||
>>> Ox.endsWith("foobar", "bar")
|
While <code>Ox.endsWith('foobar', 'bar')</code> is longer than
|
||||||
|
<code>/bar$/.test('foobar')</code>, <code>Ox.endsWith('foobar', bar)</code>
|
||||||
|
is shorter than <code>new RegExp(bar + '$').test('foobar')</code>.
|
||||||
|
> Ox.endsWith('foobar', 'bar')
|
||||||
true
|
true
|
||||||
*/
|
@*/
|
||||||
|
Ox.endsWith = function(str, sub) {
|
||||||
return new RegExp(sub + '$').test(str);
|
return new RegExp(sub + '$').test(str);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3739,34 +3859,40 @@ Ox.highlight = function(txt, str) {
|
||||||
) : txt;
|
) : txt;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*@
|
||||||
|
Ox.isValidEmail <f> Tests if a string is a valid e-mail address
|
||||||
|
(str) -> <b> True if the string is a valid e-mail address
|
||||||
|
str <s> Any string
|
||||||
|
> Ox.isValidEmail("foo@bar.com")
|
||||||
|
true
|
||||||
|
> Ox.isValidEmail("foo.bar@foobar.co.uk")
|
||||||
|
true
|
||||||
|
> Ox.isValidEmail("foo@bar")
|
||||||
|
false
|
||||||
|
> Ox.isValidEmail("foo@bar..com")
|
||||||
|
false
|
||||||
|
@*/
|
||||||
Ox.isValidEmail = function(str) {
|
Ox.isValidEmail = function(str) {
|
||||||
/*
|
|
||||||
>>> Ox.isValidEmail("foo@bar.com")
|
|
||||||
true
|
|
||||||
>>> Ox.isValidEmail("foo.bar@foobar.co.uk")
|
|
||||||
true
|
|
||||||
>>> Ox.isValidEmail("foo@bar")
|
|
||||||
false
|
|
||||||
>>> Ox.isValidEmail("foo@bar..com")
|
|
||||||
false
|
|
||||||
*/
|
|
||||||
return !!/^[0-9A-Z\.\+\-_]+@(?:[0-9A-Z\-]+\.)+[A-Z]{2,6}$/i(str);
|
return !!/^[0-9A-Z\.\+\-_]+@(?:[0-9A-Z\-]+\.)+[A-Z]{2,6}$/i(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*@
|
||||||
|
Ox.pad <f> Pad a string to a given length
|
||||||
|
> Ox.pad(1, 2)
|
||||||
|
"01"
|
||||||
|
> Ox.pad("abc", 6, ".", "right")
|
||||||
|
"abc..."
|
||||||
|
> Ox.pad("foobar", 3, ".", "right")
|
||||||
|
"foo"
|
||||||
|
> Ox.pad("abc", 6, "123456", "right")
|
||||||
|
"abc123"
|
||||||
|
> Ox.pad("abc", 6, "123456", "left")
|
||||||
|
"456abc"
|
||||||
|
@*/
|
||||||
Ox.pad = function(str, len, pad, pos) {
|
Ox.pad = function(str, len, pad, pos) {
|
||||||
// fixme: slighly obscure signature
|
// fixme: slighly obscure signature
|
||||||
// fixme: weird for negative numbers
|
// fixme: weird for negative numbers
|
||||||
/*
|
/*
|
||||||
>>> Ox.pad(1, 2)
|
|
||||||
"01"
|
|
||||||
>>> Ox.pad("abc", 6, ".", "right")
|
|
||||||
"abc..."
|
|
||||||
>>> Ox.pad("foobar", 3, ".", "right")
|
|
||||||
"foo"
|
|
||||||
>>> Ox.pad("abc", 6, "123456", "right")
|
|
||||||
"abc123"
|
|
||||||
>>> Ox.pad("abc", 6, "123456", "left")
|
|
||||||
"456abc"
|
|
||||||
*/
|
*/
|
||||||
str = str.toString().substr(0, len);
|
str = str.toString().substr(0, len);
|
||||||
pad = Ox.repeat(pad || '0', len - str.length);
|
pad = Ox.repeat(pad || '0', len - str.length);
|
||||||
|
@ -3778,6 +3904,30 @@ Ox.pad = function(str, len, pad, pos) {
|
||||||
return str;
|
return str;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*@
|
||||||
|
Ox.parsePath <f> Returns the components of a path
|
||||||
|
(str) -> <o> Path
|
||||||
|
extension <s> File extension
|
||||||
|
filename <s> Filename
|
||||||
|
pathname <s> Pathname
|
||||||
|
> Ox.parsePath('/foo/bar/foo.bar')
|
||||||
|
{extension: 'bar', filename: 'foo.bar', pathname: '/foo/bar/'}
|
||||||
|
> Ox.parsePath('foo/')
|
||||||
|
{extension: '', filename: '', pathname: 'foo/'}
|
||||||
|
> Ox.parsePath('foo')
|
||||||
|
{extension: '', filename: 'foo', pathname: ''}
|
||||||
|
> Ox.parsePath('.foo')
|
||||||
|
{extension: '', filename: '.foo', pathname: ''}
|
||||||
|
@*/
|
||||||
|
Ox.parsePath = function(str) {
|
||||||
|
var matches = /^(.+\/)?(.+?(\..+)?)?$/(str);
|
||||||
|
return {
|
||||||
|
pathname: matches[1] || '',
|
||||||
|
filename: matches[2] || '',
|
||||||
|
extension: matches[3] ? matches[3].substr(1) : ''
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
Ox.repeat = function(obj, num) {
|
Ox.repeat = function(obj, num) {
|
||||||
/*
|
/*
|
||||||
works for arrays, numbers and strings
|
works for arrays, numbers and strings
|
||||||
|
@ -3807,6 +3957,14 @@ Ox.reverse = function(str) {
|
||||||
return str.toString().split('').reverse().join('');
|
return str.toString().split('').reverse().join('');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*@
|
||||||
|
Ox.startsWith <f> Checks if a string starts with a given substring
|
||||||
|
While <code>Ox.startsWith('foobar', 'foo')</code> is longer than
|
||||||
|
<code>/^foo/.test('foobar')</code>, <code>Ox.startsWith('foobar', foo)</code>
|
||||||
|
is shorter than <code>new RegExp('^' + foo).test('foobar')</code>.
|
||||||
|
> Ox.endsWith('foobar', 'bar')
|
||||||
|
true
|
||||||
|
@*/
|
||||||
Ox.startsWith = function(str, sub) {
|
Ox.startsWith = function(str, sub) {
|
||||||
/*
|
/*
|
||||||
>>> Ox.startsWith("foobar", "foo")
|
>>> Ox.startsWith("foobar", "foo")
|
||||||
|
@ -3819,12 +3977,13 @@ Ox.startsWith = function(str, sub) {
|
||||||
return new RegExp('^' + sub).test(str);
|
return new RegExp('^' + sub).test(str);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*@
|
||||||
|
Ox.stripTags <f> Strips HTML tags from a string
|
||||||
|
> Ox.stripTags('f<span>o</span>o')
|
||||||
|
'foo'
|
||||||
|
@*/
|
||||||
Ox.stripTags = function(str) {
|
Ox.stripTags = function(str) {
|
||||||
/*
|
return str.replace(/(<.*?>)/g, '');
|
||||||
>>> Ox.stripTags("f<span>o</span>o")
|
|
||||||
"foo"
|
|
||||||
*/
|
|
||||||
return str.replace(/(<.*?>)/gi, '');
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ox.substr = function(str, start, stop) {
|
Ox.substr = function(str, start, stop) {
|
||||||
|
@ -3852,47 +4011,54 @@ Ox.substr = function(str, start, stop) {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*@
|
||||||
|
Ox.toCamelCase <f> Takes a string with '-', '/' or '_', returns a camelCase string
|
||||||
|
> Ox.toCamelCase('foo-bar-baz')
|
||||||
|
'fooBarBaz'
|
||||||
|
> Ox.toCamelCase('foo/bar/baz')
|
||||||
|
'fooBarBaz'
|
||||||
|
> Ox.toCamelCase('foo_bar_baz')
|
||||||
|
'fooBarBaz'
|
||||||
|
@*/
|
||||||
|
|
||||||
Ox.toCamelCase = function(str) {
|
Ox.toCamelCase = function(str) {
|
||||||
/*
|
|
||||||
>>> Ox.toCamelCase("foo-bar-baz")
|
|
||||||
"fooBarBaz"
|
|
||||||
>>> Ox.toCamelCase("foo/bar/baz")
|
|
||||||
"fooBarBaz"
|
|
||||||
>>> Ox.toCamelCase("foo_bar_baz")
|
|
||||||
"fooBarBaz"
|
|
||||||
*/
|
|
||||||
return str.replace(/[\-_\/][a-z]/g, function(str) {
|
return str.replace(/[\-_\/][a-z]/g, function(str) {
|
||||||
return str[1].toUpperCase();
|
return str[1].toUpperCase();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*@
|
||||||
|
Ox.toDashes <f> Takes a camelCase string, returns a string with dashes
|
||||||
|
> Ox.toDashes('fooBarBaz')
|
||||||
|
'foo-bar-baz'
|
||||||
|
@*/
|
||||||
Ox.toDashes = function(str) {
|
Ox.toDashes = function(str) {
|
||||||
/*
|
|
||||||
>>> Ox.toDashes("fooBarBaz")
|
|
||||||
"foo-bar-baz"
|
|
||||||
*/
|
|
||||||
return str.replace(/[A-Z]/g, function(str) {
|
return str.replace(/[A-Z]/g, function(str) {
|
||||||
return '-' + str.toLowerCase();
|
return '-' + str.toLowerCase();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*@
|
||||||
|
Ox.toSlashes <f> Takes a camelCase string, returns a string with slashes
|
||||||
|
> Ox.toSlashes('fooBarBaz')
|
||||||
|
'foo/bar/baz'
|
||||||
|
@*/
|
||||||
Ox.toSlashes = function(str) {
|
Ox.toSlashes = function(str) {
|
||||||
/*
|
/*
|
||||||
>>> Ox.toSlashes("fooBarBaz")
|
|
||||||
"foo/bar/baz"
|
|
||||||
*/
|
*/
|
||||||
return str.replace(/[A-Z]/g, function(str) {
|
return str.replace(/[A-Z]/g, function(str) {
|
||||||
return '/' + str.toLowerCase();
|
return '/' + str.toLowerCase();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*@
|
||||||
|
Ox.toTitleCase <f> Returns a string with capitalized words
|
||||||
|
> Ox.toTitleCase('foo')
|
||||||
|
'Foo'
|
||||||
|
> Ox.toTitleCase('Apple releases iPhone, IBM stock plummets')
|
||||||
|
'Apple Releases iPhone, IBM Stock Plummets'
|
||||||
|
@*/
|
||||||
Ox.toTitleCase = function(str) {
|
Ox.toTitleCase = function(str) {
|
||||||
/*
|
|
||||||
>>> Ox.toTitleCase("foo")
|
|
||||||
"Foo"
|
|
||||||
>>> Ox.toTitleCase("Apple releases iPhone, IBM stock plummets")
|
|
||||||
"Apple Releases iPhone, IBM Stock Plummets"
|
|
||||||
*/
|
|
||||||
return Ox.map(str.split(' '), function(v) {
|
return Ox.map(str.split(' '), function(v) {
|
||||||
var sub = v.substr(1),
|
var sub = v.substr(1),
|
||||||
low = sub.toLowerCase();
|
low = sub.toLowerCase();
|
||||||
|
@ -3903,11 +4069,12 @@ Ox.toTitleCase = function(str) {
|
||||||
}).join(" ");
|
}).join(" ");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*@
|
||||||
|
Ox.toUnderscores <f> Takes a camelCase string, returns string with underscores
|
||||||
|
> Ox.toUnderscores('fooBarBaz')
|
||||||
|
'foo_bar_baz'
|
||||||
|
@*/
|
||||||
Ox.toUnderscores = function(str) {
|
Ox.toUnderscores = function(str) {
|
||||||
/*
|
|
||||||
>>> Ox.toUnderscores("fooBarBaz")
|
|
||||||
"foo_bar_baz"
|
|
||||||
*/
|
|
||||||
return str.replace(/[A-Z]/g, function(str) {
|
return str.replace(/[A-Z]/g, function(str) {
|
||||||
return '_' + str.toLowerCase();
|
return '_' + str.toLowerCase();
|
||||||
});
|
});
|
||||||
|
@ -3921,10 +4088,23 @@ Ox.trim = function(str) { // is in jQuery, and in JavaScript itself
|
||||||
return str.replace(/^\s+|\s+$/g, "");
|
return str.replace(/^\s+|\s+$/g, "");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*@
|
||||||
|
Ox.truncate <f> Truncate a string to a given length
|
||||||
|
(string, length) <s> Truncated string
|
||||||
|
(string, length, position) -> <s> Truncated string
|
||||||
|
(string, length, placeholder) -> <s> Truncated string
|
||||||
|
(string, length, position, placeholder) -> <s> Truncated string
|
||||||
|
> Ox.truncate('anticonstitutionellement', 16)
|
||||||
|
'anticonstitut...'
|
||||||
|
> Ox.truncate('anticonstitutionellement', 16, -1)
|
||||||
|
'...utionellement'
|
||||||
|
> Ox.truncate('anticonstitutionellement', 16, '>')
|
||||||
|
'anticonstitutio>'
|
||||||
|
> Ox.truncate("anticonstitutionellement", 16, "...", "center")
|
||||||
|
'anticon...lement'
|
||||||
|
@*/
|
||||||
Ox.truncate = function(str, len, pad, pos) {
|
Ox.truncate = function(str, len, pad, pos) {
|
||||||
/*
|
/*
|
||||||
>>> Ox.truncate("anticonstitutionellement", 16, "...", "center")
|
|
||||||
"anticon...lement"
|
|
||||||
*/
|
*/
|
||||||
var pad = pad || {},
|
var pad = pad || {},
|
||||||
pos = pos || "right",
|
pos = pos || "right",
|
||||||
|
@ -3945,11 +4125,14 @@ Ox.truncate = function(str, len, pad, pos) {
|
||||||
return str;
|
return str;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*@
|
||||||
|
Ox.words <f> Splits a string into words, removing punctuation
|
||||||
|
(string) -> <[s]> Array of words
|
||||||
|
string <s> Any string
|
||||||
|
> Ox.words('Let\'s "walk" a tree-like key/value store--okay?')
|
||||||
|
["let's", "walk", "a", "tree-like", "key", "value", "store", "okay"]
|
||||||
|
@*/
|
||||||
Ox.words = function(str) {
|
Ox.words = function(str) {
|
||||||
/*
|
|
||||||
> Ox.words("The key/value pairs are read-only--aren't they?")
|
|
||||||
["the", "key", "value", "pairs", "are", "read-only", "aren't", "they"]
|
|
||||||
*/
|
|
||||||
var arr = str.toLowerCase().split(/\b/),
|
var arr = str.toLowerCase().split(/\b/),
|
||||||
chr = "-'",
|
chr = "-'",
|
||||||
len = arr.length,
|
len = arr.length,
|
||||||
|
@ -3978,23 +4161,21 @@ Ox.words = function(str) {
|
||||||
|
|
||||||
/*@
|
/*@
|
||||||
Ox.wordwrap <f> Wrap a string at word boundaries
|
Ox.wordwrap <f> Wrap a string at word boundaries
|
||||||
|
> Ox.wordwrap("Anticonstitutionellement, Paris s'eveille", 25, '<br/>')
|
||||||
|
"Anticonstitutionellement, <br/>Paris s'eveille"
|
||||||
|
> Ox.wordwrap("Anticonstitutionellement, Paris s'eveille", 16, '<br/>')
|
||||||
|
"Anticonstitution<br/>ellement, Paris <br/>s'eveille"
|
||||||
|
> Ox.wordwrap('These are short words', 16, '<br/>', true)
|
||||||
|
'These are <br/>short words'
|
||||||
@*/
|
@*/
|
||||||
Ox.wordwrap = function(str, len, sep, bal, spa) {
|
Ox.wordwrap = function(str, len, sep, bal, spa) {
|
||||||
// fixme: bad API, sep/bal/spa should be in options object
|
// fixme: bad API, sep/bal/spa should be in options object
|
||||||
/*
|
|
||||||
>>> Ox.wordwrap("Anticonstitutionellement, Paris s'eveille", 25, "<br/>")
|
|
||||||
"Anticonstitutionellement, <br/>Paris s'eveille"
|
|
||||||
>>> Ox.wordwrap("Anticonstitutionellement, Paris s'eveille", 16, "<br/>")
|
|
||||||
"Anticonstitution<br/>ellement, Paris <br/>s'eveille"
|
|
||||||
>>> Ox.wordwrap("These are short words", 16, "<br/>", true)
|
|
||||||
"These are <br/>short words"
|
|
||||||
*/
|
|
||||||
var str = str === null ? '' : str.toString(),
|
var str = str === null ? '' : str.toString(),
|
||||||
len = len || 80,
|
len = len || 80,
|
||||||
sep = sep || "<br/>",
|
sep = sep || '<br/>',
|
||||||
bal = bal || false,
|
bal = bal || false,
|
||||||
spa = Ox.isUndefined(spa) ? true : spa,
|
spa = Ox.isUndefined(spa) ? true : spa,
|
||||||
words = str.split(" "),
|
words = str.split(' '),
|
||||||
lines;
|
lines;
|
||||||
if (bal) {
|
if (bal) {
|
||||||
// balance lines: test if same number of lines
|
// balance lines: test if same number of lines
|
||||||
|
@ -4015,15 +4196,15 @@ Ox.wordwrap = function(str, len, sep, bal, spa) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lines = [""];
|
lines = [''];
|
||||||
Ox.forEach(words, function(word) {
|
Ox.forEach(words, function(word) {
|
||||||
if ((lines[lines.length - 1] + word + " ").length <= len + 1) {
|
if ((lines[lines.length - 1] + word + ' ').length <= len + 1) {
|
||||||
// word fits in current line
|
// word fits in current line
|
||||||
lines[lines.length - 1] += word + " ";
|
lines[lines.length - 1] += word + ' ';
|
||||||
} else {
|
} else {
|
||||||
if (word.length <= len) {
|
if (word.length <= len) {
|
||||||
// word fits in next line
|
// word fits in next line
|
||||||
lines.push(word + " ");
|
lines.push(word + ' ');
|
||||||
} else {
|
} else {
|
||||||
// word is longer than line
|
// word is longer than line
|
||||||
var chr = len - lines[lines.length - 1].length;
|
var chr = len - lines[lines.length - 1].length;
|
||||||
|
@ -4031,7 +4212,7 @@ Ox.wordwrap = function(str, len, sep, bal, spa) {
|
||||||
for (var pos = chr; pos < word.length; pos += len) {
|
for (var pos = chr; pos < word.length; pos += len) {
|
||||||
lines.push(word.substr(pos, len));
|
lines.push(word.substr(pos, len));
|
||||||
}
|
}
|
||||||
lines[lines.length - 1] += " ";
|
lines[lines.length - 1] += ' ';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -4106,48 +4287,75 @@ Ox.isElement = function(val) {
|
||||||
|
|
||||||
/*@
|
/*@
|
||||||
Ox.isEqual <function> Returns true if two values are equal
|
Ox.isEqual <function> Returns true if two values are equal
|
||||||
> Ox.isEqual(false, false)
|
> Ox.isEqual((function() { return arguments; }()), (function() { return arguments; }()))
|
||||||
true
|
|
||||||
> Ox.isEqual(0, 0)
|
|
||||||
true
|
|
||||||
> Ox.isEqual(NaN, NaN)
|
|
||||||
false
|
|
||||||
> Ox.isEqual('', '')
|
|
||||||
true
|
true
|
||||||
> Ox.isEqual([1, 2, 3], [1, 2, 3])
|
> Ox.isEqual([1, 2, 3], [1, 2, 3])
|
||||||
true
|
true
|
||||||
> Ox.isEqual({a: 1, b: [2, 3], c: {d: '4'}}, {a: 1, b: [2, 3], c: {d: '4'}})
|
> Ox.isEqual([1, 2, 3], [3, 2, 1])
|
||||||
|
false
|
||||||
|
> Ox.isEqual(false, false)
|
||||||
|
true
|
||||||
|
> Ox.isEqual(new Date(0), new Date(0))
|
||||||
|
true
|
||||||
|
> Ox.isEqual(new Date(0), new Date(1))
|
||||||
|
false
|
||||||
|
> Ox.isEqual(document.createElement('a'), document.createElement('a'))
|
||||||
|
true
|
||||||
|
> Ox.isEqual(document.createElement('a'), document.createElement('b'))
|
||||||
|
false
|
||||||
|
> Ox.isEqual(function(a) { return a; }, function(a) { return a; })
|
||||||
|
true
|
||||||
|
> Ox.isEqual(function(a) { return a; }, function(b) { return b; })
|
||||||
|
false
|
||||||
|
> Ox.isEqual(Infinity, Infinity)
|
||||||
|
true
|
||||||
|
> Ox.isEqual(-Infinity, Infinity)
|
||||||
|
false
|
||||||
|
> Ox.isEqual(NaN, NaN)
|
||||||
|
false
|
||||||
|
> Ox.isEqual(0, 0)
|
||||||
true
|
true
|
||||||
> Ox.isEqual({a: 1, b: 2, c: 3}, {c: 3, b: 2, a: 1})
|
> 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
|
true
|
||||||
> Ox.isEqual(function(foo) { return foo; }, function(bar) { return bar; })
|
> Ox.isEqual({a: 1, b: [2, 3], c: {d: '4'}}, {a: 1, b: [2, 3], c: {d: '4'}})
|
||||||
|
true
|
||||||
|
> Ox.isEqual(/ /, / /)
|
||||||
|
true
|
||||||
|
> Ox.isEqual(/ /g, / /i)
|
||||||
false
|
false
|
||||||
|
> Ox.isEqual('', '')
|
||||||
|
true
|
||||||
|
> Ox.isEqual(void 0, void 0)
|
||||||
|
true
|
||||||
@*/
|
@*/
|
||||||
Ox.isEqual = function(obj0, obj1) {
|
Ox.isEqual = function(a, b) {
|
||||||
var ret = false;
|
var isEqual = false, type = Ox.typeOf(a);
|
||||||
if (obj0 === obj1) {
|
if (a === b) {
|
||||||
ret = true;
|
isEqual = true;
|
||||||
} else if (typeof(obj0) == typeof(obj1)) {
|
} else if (type == Ox.typeOf(b)) {
|
||||||
if (obj0 == obj1) {
|
if (a == b) {
|
||||||
ret = true;
|
isEqual = true;
|
||||||
} else if (Ox.isArray(obj0) && obj0.length == obj1.length) {
|
} else if (type == 'date') {
|
||||||
ret = true;
|
isEqual = a.getTime() == b.getTime();
|
||||||
Ox.forEach(obj0, function(v, i) {
|
} else if (['element', 'function'].indexOf(type) > -1) {
|
||||||
ret = Ox.isEqual(v, obj1[i]);
|
isEqual = a.toString() == b.toString();
|
||||||
return ret;
|
} else if (type == 'regexp') {
|
||||||
|
isEqual = a.global == b.global &&
|
||||||
|
a.ignore == b.ignore &&
|
||||||
|
a.multiline == b.multiline &&
|
||||||
|
a.source == b.source;
|
||||||
|
} else if (
|
||||||
|
['arguments', 'array', 'object'].indexOf(type) > -1 &&
|
||||||
|
Ox.len(a) == Ox.len(b)
|
||||||
|
) {
|
||||||
|
isEqual = true;
|
||||||
|
Ox.forEach(a, function(v, k) {
|
||||||
|
isEqual = Ox.isEqual(v, b[k]);
|
||||||
|
return isEqual;
|
||||||
});
|
});
|
||||||
} else if (Ox.isDate(obj0)) {
|
|
||||||
ret = obj0.getTime() == obj1.getTime();
|
|
||||||
} else if (Ox.isObject(obj0)) {
|
|
||||||
ret = Ox.isEqual(Ox.keys(obj0), Ox.keys(obj1)) &&
|
|
||||||
Ox.isEqual(Ox.values(obj0), Ox.values(obj1));
|
|
||||||
} else if (Ox.isFunction(obj0)) {
|
|
||||||
ret = obj0.toString() == obj1.toString();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return isEqual;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*@
|
/*@
|
||||||
|
|
Loading…
Reference in a new issue