WIP: try to convert to ES modules

This commit is contained in:
j 2026-02-09 18:59:12 +01:00
commit 299a08b6a3
29 changed files with 3003 additions and 2014 deletions

View file

@ -4,7 +4,8 @@
<title>OxJS - A JavaScript Library for Web Applications</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<link rel="stylesheet" type="text/css" href="index.css"/>
<script type="text/javascript" src="dev/Ox.js"></script>
<script type="text/javascript" src="source/UI/jquery/jquery-1.7.1.min.js"></script>
<script type="text/javascript" src="source/Ox.compat.js"></script>
<script type="text/javascript" src="index.js"></script>
</head>
<body></body>

18
source/Ox.compat.js Normal file
View file

@ -0,0 +1,18 @@
const init = [], initLoad = [];
window.Ox = function(value) {
console.log("delay stuff until we are done")
init.push(value)
};
window.Ox.load = function() {
initLoad.push(arguments)
};
(async () => {
const module = await import('./Ox/index.js');
console.log("Ox was loaded", init);
init.forEach(value => Ox(value))
delete init
initLoad.forEach(arguments => Ox.load.apply(null, arguments))
delete initLoad
})();

102
source/Ox/index.js Normal file
View file

@ -0,0 +1,102 @@
'use strict';
/*@
Ox <f> The `Ox` object
See `Ox.wrap` for details.
(value) -> <o> wrapped value
value <*> Any value
@*/
import * as OxCore from './js/Core.js';
import * as OxFunction from './js/Function.js';
import * as OxPolyfill from './js/Polyfill.js';
import * as OxArray from './js/Array.js';
import * as OxString from './js/String.js';
import * as OxCollection from './js/Collection.js';
import * as OxMath from './js/Math.js';
import * as OxAsync from './js/Async.js';
import * as OxColor from './js/Color.js';
import * as OxConstants from './js/Constants.js';
import * as OxDate from './js/Date.js';
import * as OxDOM from './js/DOM.js';
import * as OxEncoding from './js/Encoding.js';
import * as OxFormat from './js/Format.js';
import * as OxGeo from './js/Geo.js';
import * as OxHash from './js/Hash.js';
import * as OxHTML from './js/HTML.js';
import * as OxJavaScript from './js/JavaScript.js';
import * as OxLocale from './js/Locale.js';
import * as OxObject from './js/Object.js';
import * as OxRegExp from './js/RegExp.js';
import * as OxRequest from './js/Request.js';
import * as OxType from './js/Type.js';
import * as OxVideo from './js/Video.js';
const Ox = function(value) {
return OxCore.wrap(value)
};
Object.assign(Ox,
OxCore,
OxFunction,
OxPolyfill,
OxArray,
OxString,
OxCollection,
OxMath,
OxAsync,
OxColor,
OxConstants,
OxDate,
OxDOM,
OxEncoding,
OxFormat,
OxGeo,
OxHash,
OxHTML,
OxJavaScript,
OxLocale,
OxObject,
OxRegExp,
OxRequest,
OxType,
OxVideo,
);
export default Ox;
export { Ox };
// For backward compatibility with global usage
if (typeof window !== 'undefined') {
window.Ox = Ox;
Ox.loadPolyfill(window, Ox)
/*@
Ox.documentReady <function> Calls a callback function once the DOM is ready
(callback) -> <b> If true, the document was ready
callback <f> Callback function
@*/
Ox.documentReady = (function() {
var callbacks = [];
document.onreadystatechange = window.onload = function() {
if (document.readyState == 'complete') {
callbacks.forEach(function(callback) {
callback();
});
document.onreadystatechange = window.onload = null;
}
};
return function(callback) {
if (document.readyState == 'complete') {
callback();
return true;
} else {
callbacks.push(callback);
return false;
}
};
}());
}

View file

@ -1,5 +1,19 @@
'use strict';
import * as OxCore from './Core.js';
import * as OxBase from './Base.js';
import * as OxFunction from './Function.js';
import * as OxType from './Type.js';
const Ox = {};
Object.assign(Ox,
OxCore,
OxBase,
OxFunction,
OxType,
);
/*@
Ox.api <f> Turns an array into a list API
`Ox.api` takes an array and returns a function that allows you to run
@ -163,7 +177,7 @@ Ox.api <f> Turns an array into a list API
> Ox.test.apiResults[9].data
{items: [{name: 'John Cale'}, {name: 'Brian Eno'}]}
@*/
Ox.api = function(items, options) {
export function api(items, options) {
options = options || {};
@ -442,7 +456,7 @@ Ox.compact <f> Removes `null` or `undefined` values from an array
> Ox.compact([null,,1,,2,,3])
[1, 2, 3]
@*/
Ox.compact = function(array) {
export function compact(array) {
return array.filter(function(value) {
return value != null;
});
@ -461,7 +475,7 @@ Ox.find <f> Returns array elements that match a string
> Ox.find(['Bar', 'Barfoo', 'Foo', 'Foobar'], 'foo', true)
['Foo', 'Foobar']
@*/
Ox.find = function(array, string, leading) {
export function find(array, string, leading) {
var matches = [[], []];
string = string.toLowerCase();
array.forEach(function(value) {
@ -480,7 +494,7 @@ Ox.flatten <f> Flattens an array
> Ox.flatten([1, [2, [3], 2], 1])
[1, 2, 3, 2, 1]
@*/
Ox.flatten = function(array) {
export function flatten(array) {
var ret = [];
array.forEach(function(value) {
if (Ox.isArray(value)) {
@ -493,7 +507,7 @@ Ox.flatten = function(array) {
};
// FIXME: add docs and tests
Ox.getIndex = function(array, key, value) {
export function getIndex(array, key, value) {
return Ox.indexOf(array, function(obj) {
return obj[key] === value;
});
@ -509,13 +523,13 @@ Ox.getIndexById <f> Returns the first array index of an object with a given id
> Ox.getIndexById([{id: 'foo', str: 'Foo'}, {id: 'bar', str: 'Bar'}], 'baz')
-1
@*/
Ox.getIndexById = function(array, id) {
return Ox.getIndex(array, 'id', id);
export function getIndexById(array, id) {
return getIndex(array, 'id', id);
};
// FIXME: add docs and tests
Ox.getObject = function(array, key, value) {
var index = Ox.getIndex(array, key, value);
export function getObject(array, key, value) {
var index = getIndex(array, key, value);
return index > -1 ? array[index] : null;
};
@ -529,12 +543,12 @@ Ox.getObjectById <f> Returns the first object in an array with a given id
> Ox.getObjectById([{id: 'foo', str: 'Foo'}, {id: 'bar', str: 'Bar'}], 'baz')
null
@*/
Ox.getObjectById = function(array, id) {
return Ox.getObject(array, 'id', id);
export function getObjectById(array, id) {
return getObject(array, 'id', id);
};
/*
Ox.indexOf = function(arr) {
export function indexOf(arr) {
// indexOf for primitives, test for function, deep equal for others
};
*/
@ -555,7 +569,7 @@ Ox.last <f> Gets or sets the last element of an array
> Ox.last('123')
'3'
@*/
Ox.last = function(array, value) {
export function last(array, value) {
var ret;
if (arguments.length == 1) {
ret = array[array.length - 1];
@ -576,7 +590,7 @@ Ox.makeArray <f> Wraps any non-array in an array.
['foo']
@*/
// FIXME: rename to toArray
Ox.makeArray = function(value) {
export function makeArray(value) {
var ret, type = Ox.typeOf(value);
if (type == 'arguments' || type == 'nodelist') {
ret = Ox.slice(value);
@ -599,7 +613,7 @@ Ox.nextValue <f> Next value, given an array of numbers, a number and a direction
> Ox.nextValue([], 1, 1)
void 0
@*/
Ox.nextValue = function(array, value, direction) {
export function nextValue(array, value, direction) {
var found = false, nextValue;
direction = direction || 1;
direction == -1 && array.reverse();
@ -641,7 +655,7 @@ Ox.range <f> Python-style range
> Ox.range(-1, -2, -0.5)
[-1, -1.5]
@*/
Ox.range = function() {
export function range() {
var array = [];
Ox.loop.apply(null, Ox.slice(arguments).concat(function(index) {
array.push(index);
@ -768,7 +782,7 @@ Ox.unique <f> Removes duplicate values from an array
> Ox.unique('foo')
'fo'
@*/
Ox.unique = function(array) {
export function unique(array) {
return Ox.filter(array, function(value, index) {
return array.indexOf(value) == index;
});
@ -781,7 +795,7 @@ Ox.zip <f> Zips an array of arrays
> Ox.zip([0, 1, 2], [3, 4, 5])
[[0, 3], [1, 4], [2, 5]]
@*/
Ox.zip = function() {
export function zip() {
var args = arguments.length == 1 ? arguments[0] : Ox.slice(arguments),
array = [];
args[0].forEach(function(value, index) {

View file

@ -1,8 +1,19 @@
'use strict';
(function() {
import * as OxObject from './Object.js';
import * as OxConstants from './Constants.js';
import * as OxMath from './Math.js';
function asyncMap(forEach, collection, iterator, that, callback) {
const Ox = {};
Object.assign(Ox,
OxObject,
OxConstants,
OxMath
);
function internalAsyncMap(forEach, collection, iterator, that, callback) {
var type = Ox.typeOf(collection),
results = type == 'object' ? {} : [];
callback = Ox.last(arguments);
@ -15,9 +26,9 @@
}, that, function() {
callback(type == 'string' ? results.join('') : results);
});
}
}
Ox.asyncMap = function(array, iterator, that, callback) {
export function asyncMap(array, iterator, that, callback) {
array = Ox.makeArray(array);
callback = Ox.last(arguments);
that = arguments.length == 4 ? that : null;
@ -28,10 +39,10 @@
} else {
Ox.parallelMap(array, iterator, callback);
}
};
};
/*@
Ox.nonblockingForEach <f> Non-blocking `forEach` with synchronous iterator
/*@
Ox.nonblockingForEach <f> Non-blocking `forEach` with synchronous iterator
(col, iterator[, that], callback[, ms]) -> <u> undefined
collection <a|o|s> Collection
iterator <f> Iterator function
@ -41,8 +52,8 @@
that <o> The iterator's `this` binding
callback <f> Callback function
ms <n> Number of milliseconds after which to insert a `setTimeout` call
@*/
Ox.nonblockingForEach = function(collection, iterator, that, callback, ms) {
@*/
export function nonblockingForEach(collection, iterator, that, callback, ms) {
var i = 0, keys, last = Ox.last(arguments),
n, time, type = Ox.typeOf(collection);
callback = Ox.isFunction(last) ? last : arguments[arguments.length - 2];
@ -81,10 +92,10 @@
callback();
}
}
};
};
/*@
Ox.nonblockingMap <f> Non-blocking `map` with synchronous iterator
/*@
Ox.nonblockingMap <f> Non-blocking `map` with synchronous iterator
(collection, iterator[, that], callback[, ms]) -> <u> undefined
collection <a|o|s> Collection
iterator <f> Iterator function
@ -106,8 +117,8 @@
</script>
> Ox.nonblockingMap(Ox.range(100000), Ox.identity, function(r) { Ox.test(r.length, 100000); })
undefined
@*/
Ox.nonblockingMap = function(collection, iterator, that, callback, ms) {
@*/
export function nonblockingMap(collection, iterator, that, callback, ms) {
var last = Ox.last(arguments),
type = Ox.typeOf(collection),
results = type == 'object' ? {} : [];
@ -120,10 +131,10 @@
}, function() {
callback(type == 'string' ? results.join('') : results);
}, ms);
};
};
/*@
Ox.parallelForEach <f> `forEach` with asynchronous iterator, running in parallel
/*@
Ox.parallelForEach <f> `forEach` with asynchronous iterator, running in parallel
(collection, iterator[, that], callback) -> <u> undefined
collection <a|o|s> Collection
iterator <f> Iterator function
@ -144,8 +155,8 @@
</script>
> Ox.parallelForEach(Ox.range(10), Ox.test.pfeIterator, function() { Ox.test(Ox.test.pfeNumber, 5); })
undefined
@*/
Ox.parallelForEach = function(collection, iterator, that, callback) {
@*/
export function parallelForEach(collection, iterator, that, callback) {
var i = 0, n, type = Ox.typeOf(collection);
callback = callback || (arguments.length == 3 ? arguments[2] : Ox.noop);
collection = type == 'array' || type == 'object'
@ -157,10 +168,10 @@
++i == n && callback();
});
});
};
};
/*@
Ox.parallelMap <f> Parallel `map` with asynchronous iterator
/*@
Ox.parallelMap <f> Parallel `map` with asynchronous iterator
(collection, iterator[, that], callback) -> <u> undefined
collection <a|o|s> Collection
iterator <f> Iterator function
@ -190,13 +201,13 @@
</script>
> Ox.parallelMap(Ox.range(10), Ox.test.pmIterator, function(r) { Ox.test(Ox.sum(r), 0); })
undefined
@*/
Ox.parallelMap = function() {
asyncMap.apply(null, [Ox.parallelForEach].concat(Ox.slice(arguments)));
};
@*/
export function parallelMap() {
internalAsyncMap.apply(null, [Ox.parallelForEach].concat(Ox.slice(arguments)));
};
/*@
Ox.serialForEach <f> `forEach` with asynchronous iterator, run serially
/*@
Ox.serialForEach <f> `forEach` with asynchronous iterator, run serially
(collection, iterator[, that], callback) -> <u> undefined
collection <a|o|s> Collection
iterator <f> Iterator function
@ -217,8 +228,8 @@
</script>
> Ox.serialForEach(Ox.range(10), Ox.test.sfeIterator, function() { Ox.test(Ox.test.sfeNumber, 5); })
undefined
@*/
Ox.serialForEach = function(collection, iterator, that, callback) {
@*/
export function serialForEach(collection, iterator, that, callback) {
var i = 0, keys, n, type = Ox.typeOf(collection);
callback = callback || (arguments.length == 3 ? arguments[2] : Ox.noop);
collection = type == 'array' || type == 'object'
@ -245,10 +256,10 @@
callback();
}
}
};
};
/*@
Ox.serialMap <f> Serial `map` with asynchronous iterator
/*@
Ox.serialMap <f> Serial `map` with asynchronous iterator
(collection, iterator[, that], callback) -> <u> undefined
collection <a|o|s> Collection
iterator <f> Iterator function
@ -278,10 +289,9 @@
</script>
> Ox.serialMap(Ox.range(10), Ox.test.smIterator, function(r) { Ox.test(Ox.sum(r), 0); })
undefined
@*/
Ox.serialMap = function(collection, iterator, that, callback) {
asyncMap.apply(null, [Ox.serialForEach].concat(Ox.slice(arguments)));
};
// FIXME: The above test with 10000 iterations blows the stack
@*/
export function serialMap(collection, iterator, that, callback) {
internalAsyncMap.apply(null, [Ox.serialForEach].concat(Ox.slice(arguments)));
};
// FIXME: The above test with 10000 iterations blows the stack
}());

49
source/Ox/js/Base.js Normal file
View file

@ -0,0 +1,49 @@
/*@
Ox.filter <f> Filters a collection by a given condition
Unlike `Array.prototype.filter`, `Ox.filter` works for arrays, objects and
strings.
> Ox.filter([2, 1, 0], function(v, i) { return v == i; })
[1]
> Ox.filter({a: 'c', b: 'b', c: 'a'}, function(v, k) { return v == k; })
{b: 'b'}
> Ox.filter(' foo bar ', function(v) { return v != ' '; })
'foobar'
@*/
export function filter(collection, iterator, that) {
var ret, type = Ox.typeOf(collection);
iterator = iterator || Ox.identity;
if (type == 'object' || type == 'storage') {
ret = {};
Ox.forEach(collection, function(value, key) {
if (iterator.call(that, value, key, collection)) {
ret[key] = value;
}
});
} else {
ret = Ox.slice(collection).filter(iterator, that);
if (type == 'string') {
ret = ret.join('');
}
}
return ret;
};
/*@
Ox.indexOf <f> Returns the first index of a collection element that passes a test
> Ox.indexOf([1, 2, 3], function(val) { return val % 2 == 0; })
1
> Ox.indexOf({a: 1, b: 2, c: 3}, function(val) { return val % 2 == 0; })
'b'
> Ox.indexOf('FooBar', function(val) { return val == val.toUpperCase(); })
0
> Ox.indexOf([1, 2, 3], function(val) { return val == 0; })
-1
@*/
export function indexOf(collection, test) {
var index = Ox.forEach(collection, function(value) {
return !test(value); // break if test succeeds
});
return Ox.isObject(collection) ? Object.keys(collection)[index] || null
: index == collection.length ? -1 : index;
};

View file

@ -1,5 +1,22 @@
'use strict';
import * as OxCore from './Core.js';
import * as OxFunction from './Function.js';
import * as OxConstants from './Constants.js';
import * as OxType from './Type.js';
import * as OxObject from './Object.js';
const Ox = {};
Object.assign(Ox,
OxCore,
OxConstants,
OxType,
OxObject,
OxFunction,
);
/*@
Ox.avg <f> Returns the average of an array's values, or an object's properties
(collection) -> <n> Average value
@ -11,8 +28,8 @@ Ox.avg <f> Returns the average of an array's values, or an object's properties
> Ox.avg('avg is 0.1')
0.1
@*/
Ox.avg = function(collection) {
return Ox.sum(collection) / Ox.len(collection);
export function avg(collection) {
return Ox.sum(collection) / len(collection);
};
/*@
@ -28,13 +45,13 @@ Ox.clone <f> Returns a (shallow or deep) copy of an array or object
> (function() { var a = [[0, 1]], b = Ox.clone(a, true); a[0][0] = null; return b[0]; }())
[0, 1]
@*/
Ox.clone = function(collection, deep) {
export function clone(collection, deep) {
var ret, type = Ox.typeOf(collection);
if (type != 'array' && type != 'object') {
ret = collection;
} else if (deep) {
ret = type == 'array' ? [] : {};
Ox.forEach(collection, function(value, key) {
forEach(collection, function(value, key) {
type = Ox.typeOf(value);
ret[key] = type == 'array' || type == 'object'
? Ox.clone(value, true) : value;
@ -59,7 +76,7 @@ Ox.contains <f> Tests if a collection contains a value
> Ox.contains('foobar', 'bar')
true
@*/
Ox.contains = function(collection, value) {
export function contains(collection, value) {
var type = Ox.typeOf(collection);
return (
type == 'nodelist' || type == 'object'
@ -84,9 +101,9 @@ Ox.count <f> Counts the occurences of values in a collection
> Ox.count('foo', 'x')
0
@*/
Ox.count = function(collection, value) {
export function count(collection, value) {
var count = {};
Ox.forEach(collection, function(value) {
forEach(collection, function(value) {
count[value] = (count[value] || 0) + 1;
});
return value ? count[value] || 0 : count;
@ -111,42 +128,13 @@ Ox.every <f> Tests if every element of a collection satisfies a given condition
> Ox.every([true, true, true])
true
@*/
Ox.every = function(collection, iterator, that) {
export function every(collection, iterator, that) {
iterator = iterator || Ox.identity;
return Ox.forEach(collection, function(value, key, collection) {
return forEach(collection, function(value, key, collection) {
return !!iterator.call(that, value, key, collection);
}) == Ox.len(collection);
}) == len(collection);
};
/*@
Ox.filter <f> Filters a collection by a given condition
Unlike `Array.prototype.filter`, `Ox.filter` works for arrays, objects and
strings.
> Ox.filter([2, 1, 0], function(v, i) { return v == i; })
[1]
> Ox.filter({a: 'c', b: 'b', c: 'a'}, function(v, k) { return v == k; })
{b: 'b'}
> Ox.filter(' foo bar ', function(v) { return v != ' '; })
'foobar'
@*/
Ox.filter = function(collection, iterator, that) {
var ret, type = Ox.typeOf(collection);
iterator = iterator || Ox.identity;
if (type == 'object' || type == 'storage') {
ret = {};
Ox.forEach(collection, function(value, key) {
if (iterator.call(that, value, key, collection)) {
ret[key] = value;
}
});
} else {
ret = Ox.slice(collection).filter(iterator, that);
if (type == 'string') {
ret = ret.join('');
}
}
return ret;
};
/*@
Ox.forEach <f> forEach loop
@ -171,7 +159,7 @@ Ox.forEach <f> forEach loop
> Ox.forEach({a: 'f', b: 'o', c: 'o'}, function(v, k) { return v != 'o' });
1
@*/
Ox.forEach = function(collection, iterator, that) {
export function forEach(collection, iterator, that) {
var i = 0, key, type = Ox.typeOf(collection);
if (type == 'object' || type == 'storage') {
for (key in collection) {
@ -197,25 +185,6 @@ Ox.forEach = function(collection, iterator, that) {
return i;
};
/*@
Ox.indexOf <f> Returns the first index of a collection element that passes a test
> Ox.indexOf([1, 2, 3], function(val) { return val % 2 == 0; })
1
> Ox.indexOf({a: 1, b: 2, c: 3}, function(val) { return val % 2 == 0; })
'b'
> Ox.indexOf('FooBar', function(val) { return val == val.toUpperCase(); })
0
> Ox.indexOf([1, 2, 3], function(val) { return val == 0; })
-1
@*/
Ox.indexOf = function(collection, test) {
var index = Ox.forEach(collection, function(value) {
return !test(value); // break if test succeeds
});
return Ox.isObject(collection) ? Object.keys(collection)[index] || null
: index == collection.length ? -1 : index;
};
/*@
Ox.indicesOf <f> Returns all indices of collection elements that pass a test
> Ox.indicesOf([1, 2, 3], function(val) { return val % 2 == 1; })
@ -227,9 +196,9 @@ Ox.indicesOf <f> Returns all indices of collection elements that pass a test
> Ox.indicesOf([1, 2, 3], function(val) { return val == 0; })
[]
@*/
Ox.indicesOf = function(collection, test) {
export function indicesOf(collection, test) {
var ret = [];
Ox.forEach(collection, function(value, index) {
forEach(collection, function(value, index) {
test(value) && ret.push(index);
});
return ret;
@ -256,7 +225,7 @@ Ox.len <f> Returns the length of an array, nodelist, object, storage or string
> Ox.len(function(a, b, c) {})
undefined
@*/
Ox.len = function(collection) {
export function len(collection) {
var ret, type = Ox.typeOf(collection);
if (
type == 'arguments' || type == 'array'
@ -282,11 +251,11 @@ Ox.map <f> Transforms the values of an array, object or string
> Ox.map([,], function(v, i) { return i; })
[,]
@*/
Ox.map = function(collection, iterator, that) {
export function map(collection, iterator, that) {
var ret, type = Ox.typeOf(collection);
if (type == 'object' || type == 'storage') {
ret = {};
Ox.forEach(collection, function(value, key) {
forEach(collection, function(value, key) {
ret[key] = iterator.call(that, value, key, collection);
});
} else {
@ -309,7 +278,7 @@ Ox.max <f> Returns the maximum value of a collection
> Ox.max([])
-Infinity
@*/
Ox.max = function(collection) {
export function max(collection) {
var ret, values = Ox.values(collection);
if (values.length < Ox.STACK_LENGTH) {
ret = Math.max.apply(null, values);
@ -332,7 +301,7 @@ Ox.min <f> Returns the minimum value of a collection
> Ox.min([])
Infinity
@*/
Ox.min = function(collection) {
export function min(collection) {
var ret, values = Ox.values(collection);
if (values.length < Ox.STACK_LENGTH) {
ret = Math.min.apply(null, values);
@ -359,8 +328,8 @@ Ox.numberOf <f> Returns the number of elements in a collection that pass a test
> Ox.numberOf('foo', function(v, k, c) { return v == c[k - 1]; })
1
@*/
Ox.numberOf = function(collection, test) {
return Ox.len(Ox.filter(collection, test));
export function numberOf(collection, test) {
return len(Ox.filter(collection, test));
};
/*@
@ -381,7 +350,7 @@ Ox.remove <f> Removes an element from an array or object and returns it
> Ox.test.collection
[['a', 'c'], {a: 0, c: 2}]
@*/
Ox.remove = function(collection, element) {
export function remove(collection, element) {
var ret, key;
if (Ox.isArray(collection)) {
key = collection.indexOf(element);
@ -405,7 +374,7 @@ Ox.reverse <f> Reverses an array or string
> Ox.reverse('foobar')
'raboof'
@*/
Ox.reverse = function(collection) {
export function reverse(collection) {
return Ox.isArray(collection)
? Ox.clone(collection).reverse()
: collection.toString().split('').reverse().join('');
@ -420,7 +389,7 @@ Ox.shuffle <f> Randomizes the order of values within a collection
> Ox.shuffle('123').split('').sort().join('')
'123'
@*/
Ox.shuffle = function(collection) {
export function shuffle(collection) {
var keys, ret, type = Ox.typeOf(collection), values;
if (type == 'object' || type == 'storage') {
keys = Object.keys(collection);
@ -443,57 +412,6 @@ Ox.shuffle = function(collection) {
return ret;
};
/*@
Ox.slice <f> Alias for `Array.prototype.slice.call`
(collection[, start[, stop]]) -> <a> Array
collection <a|o|s> Array-like
start <n> Start position
stop <n> Stop position
> (function() { return Ox.slice(arguments); }(1, 2, 3))
[1, 2, 3]
> Ox.slice('foo', 0, 1);
['f']
> Ox.slice({0: 'f', 1: 'o', 2: 'o', length: 3}, -2)
['o', 'o']
@*/
// FIXME: remove toArray alias
Ox.slice = Ox.toArray = function(collection, start, stop) {
return Array.prototype.slice.call(collection, start, stop);
};
// IE8 can't apply slice to NodeLists, returns an empty array if undefined is
// passed as stop and returns an array of null values if a string is passed as
// value. Firefox 3.6 returns an array of undefined values if a string is passed
// as value.
if (
Ox.slice([0]).length == 0
|| Ox.slice('0')[0] === null
|| Ox.slice('0')[0] === void 0
|| !(function() {
try {
return Ox.slice(document.getElementsByTagName('a'));
} catch (error) {}
}())
) {
// FIXME: remove toArray alias
Ox.slice = Ox.toArray = function(collection, start, stop) {
var args = stop === void 0 ? [start] : [start, stop],
array = [], index, length, ret;
if (Ox.typeOf(collection) == 'string') {
collection = collection.split('');
}
try {
ret = Array.prototype.slice.apply(collection, args);
} catch (error) {
length = collection.length;
for (index = 0; index < length; index++) {
array[index] = collection[index];
}
ret = Array.prototype.slice.apply(array, args);
}
return ret;
};
}
/*@
Ox.some <f> Tests if one or more elements of a collection meet a given condition
Unlike `Array.prototype.some`, `Ox.some` works for arrays, objects and
@ -507,11 +425,11 @@ Ox.some <f> Tests if one or more elements of a collection meet a given condition
> Ox.some([false, null, 0, '', void 0])
false
@*/
Ox.some = function(collection, iterator, that) {
export function some(collection, iterator, that) {
iterator = iterator || Ox.identity;
return Ox.forEach(collection, function(value, key, collection) {
return forEach(collection, function(value, key, collection) {
return !iterator.call(that, value, key, collection);
}) < Ox.len(collection);
}) < len(collection);
};
/*@
@ -529,10 +447,10 @@ Ox.sum <f> Returns the sum of the values of a collection
> Ox.sum('08', -2, 'foo')
6
@*/
Ox.sum = function(collection) {
export function sum(collection) {
var ret = 0;
collection = arguments.length > 1 ? Ox.slice(arguments) : collection;
Ox.forEach(collection, function(value) {
forEach(collection, function(value) {
value = +value;
ret += isFinite(value) ? value : 0;
});
@ -541,7 +459,7 @@ Ox.sum = function(collection) {
/* FIXME: do we need this kind of zip functionality?
Ox.arrayToObject = function(array, key) {
export function arrayToObject(array, key) {
var ret = {};
array.forEach(function(v) {
ret[v[key]] = v;
@ -549,9 +467,9 @@ Ox.arrayToObject = function(array, key) {
return ret;
};
Ox.objectToArray = function(object, key) {
export function objectToArray(object, key) {
var ret = [];
Ox.forEach(object, function(v, k) {
forEach(object, function(v, k) {
ret.push(Ox.extend(v, key, k));
});
return ret;
@ -574,13 +492,13 @@ Ox.values <f> Returns the values of a collection
> Ox.values([1,,3])
[1,,3]
@*/
Ox.values = function(collection) {
export function values(collection) {
var ret, type = Ox.typeOf(collection);
if (type == 'array' || type == 'nodelist') {
ret = Ox.slice(collection);
} else if (type == 'object' || type == 'storage') {
ret = [];
Ox.forEach(collection, function(value) {
forEach(collection, function(value) {
ret.push(value);
});
} else if (type == 'string') {
@ -613,9 +531,9 @@ Ox.walk <f> Iterates over a nested data structure
> Ox.test.array
[['a'], ['b', 'c'], ['b', 'd']]
@*/
Ox.walk = function(collection, iterator, that, keys) {
export function walk(collection, iterator, that, keys) {
keys = keys || [];
Ox.forEach(collection, function(value, key) {
forEach(collection, function(value, key) {
var keys_ = keys.concat(key);
iterator.call(that, value, keys_, collection);
Ox.walk(collection[key], iterator, that, keys_);

View file

@ -1,5 +1,17 @@
'use strict';
import * as OxObject from './Object.js';
import * as OxConstants from './Constants.js';
import * as OxMath from './Math.js';
const Ox = {};
Object.assign(Ox,
OxObject,
OxConstants,
OxMath
);
/*@
Ox.hsl <f> Takes RGB values and returns HSL values
(rgb) <[n]> HSL values
@ -15,7 +27,7 @@ Ox.hsl <f> Takes RGB values and returns HSL values
> Ox.hsl(0, 255, 0)
[120, 1, 0.5]
@*/
Ox.hsl = function(rgb) {
export function hsl(rgb) {
var hsl = [0, 0, 0], max, min;
if (arguments.length == 3) {
rgb = Ox.slice(arguments);
@ -62,7 +74,7 @@ Ox.rgb <f> Takes HSL values and returns RGB values
[0, 255, 0]
@*/
Ox.rgb = function(hsl) {
export function rgb(hsl) {
var rgb = [0, 0, 0], v1, v2, v3;
if (arguments.length == 3) {
hsl = Ox.slice(arguments);
@ -106,7 +118,7 @@ Ox.toHex <f> Format RGB array as hex value
> Ox.toHex([192, 128, 64])
'C08040'
@*/
Ox.toHex = function(rgb) {
export function toHex(rgb) {
return rgb.map(function(value) {
return Ox.pad(value.toString(16).toUpperCase(), 'left', 2, '0');
}).join('');
@ -117,7 +129,7 @@ Ox.toRGB <f> Format hex value as RGB array
> Ox.toRGB('C08040')
[192, 128, 64]
@*/
Ox.toRGB = function(hex) {
export function toRGB(hex) {
return Ox.range(3).map(function(index) {
return parseInt(hex.substr(index * 2, 2), 16);
});

View file

@ -1,30 +1,38 @@
'use strict';
import * as OxMath from './Math.js';
const Ox = {};
Object.assign(Ox,
OxMath
);
//@ Ox.AMPM <[s]> ['AM', 'PM']
Ox.AMPM = ['AM', 'PM'];
export const AMPM = ['AM', 'PM'];
//@ Ox.BASE_32_ALIASES <o> Base 32 aliases
Ox.BASE_32_ALIASES = {'I': '1', 'L': '1', 'O': '0', 'U': 'V'},
export const BASE_32_ALIASES = {'I': '1', 'L': '1', 'O': '0', 'U': 'V'};
//@ Ox.BASE_32_DIGITS <o> Base 32 digits
Ox.BASE_32_DIGITS = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';
export const BASE_32_DIGITS = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';
//@ Ox.BCAD <[s]> ['BC', 'AD']
Ox.BCAD = ['BC', 'AD'];
export const BCAD = ['BC', 'AD'];
/*@
Ox.EARTH_RADIUS <n> Radius of the earth in meters
See http://en.wikipedia.org/wiki/WGS-84
*/
Ox.EARTH_RADIUS = 6378137;
export const EARTH_RADIUS = 6378137;
//@ Ox.EARTH_CIRCUMFERENCE <n> Circumference of the earth in meters
Ox.EARTH_CIRCUMFERENCE = 2 * Math.PI * Ox.EARTH_RADIUS;
export const EARTH_CIRCUMFERENCE = 2 * Math.PI * EARTH_RADIUS;
//@ Ox.EARTH_SURFACE <n> Surface of the earth in square meters
Ox.EARTH_SURFACE = 4 * Math.PI * Math.pow(Ox.EARTH_RADIUS, 2);
export const EARTH_SURFACE = 4 * Math.PI * Math.pow(EARTH_RADIUS, 2);
//@ Ox.HTML_ENTITIES <o> HTML entities for ... (FIXME)
Ox.HTML_ENTITIES = {
export const HTML_ENTITIES = {
'"': '&quot;', '&': '&amp;', "'": '&apos;', '<': '&lt;', '>': '&gt;'
};
//@ Ox.KEYS <o> Names for key codes
// 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 = {
export const KEYS = {
0: 'section', 8: 'backspace', 9: 'tab', 12: 'clear', 13: 'enter',
16: 'shift', 17: 'control', 18: 'alt', 20: 'capslock', 27: 'escape',
32: 'space', 33: 'pageup', 34: 'pagedown', 35: 'end', 36: 'home',
@ -55,9 +63,9 @@ Ox.KEYS = {
// see dojo, for ex.
};
//@ Ox.LOCALE <s> Default locale
Ox.LOCALE = 'en';
export const LOCALE = 'en';
//@ Ox.LOCALE_NAMES <o> Locale names
Ox.LOCALE_NAMES = {
export const LOCALE_NAMES = {
'ar': 'العربية',
'de': 'Deutsch',
'el': 'Ελληνικά',
@ -67,51 +75,56 @@ Ox.LOCALE_NAMES = {
'tr': 'Türkçe'
};
//@ Ox.LOCALES <o> Locales per module
Ox.LOCALES = {};
export const LOCALES = {};
//@ Ox.MAX_LATITUDE <n> Maximum latitude of a Mercator projection
Ox.MAX_LATITUDE = Ox.deg(Math.atan(Ox.sinh(Math.PI)));
export const MAX_LATITUDE = Ox.deg(Math.atan(Ox.sinh(Math.PI)));
//@ Ox.MIN_LATITUDE <n> Minimum latitude of a Mercator projection
Ox.MIN_LATITUDE = -Ox.MAX_LATITUDE;
export const MIN_LATITUDE = -Ox.MAX_LATITUDE;
//@ Ox.MODIFIER_KEYS <o> Names for modifier keys
// meta comes last so that one can differentiate between
// alt_control_shift_meta.left and alt_control_shift_meta.right
Ox.MODIFIER_KEYS = {
export const MODIFIER_KEYS = {
altKey: 'alt', // Mac: option
ctrlKey: 'control',
shiftKey: 'shift',
metaKey: 'meta' // Mac: command
};
//@ Ox.MONTHS <[s]> Names of months
Ox.MONTHS = [
export const MONTHS = [
'January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November', 'December'
];
//@ Ox.SHORT_MONTHS <[s]> Short names of months
Ox.SHORT_MONTHS = Ox.MONTHS.map(function(val) {
export const SHORT_MONTHS = MONTHS.map(function(val) {
return val.slice(0, 3);
});
//@ Ox.PATH <s> Path of Ox.js
Ox.PATH = (function() {
export const PATH = (function() {
// IE8 can't apply slice to NodeLists, see Ox.slice
var index, regexp = /Ox\.js(\?.+|)$/,
scripts = document.getElementsByTagName('script'), src;
var index, regexp = /Ox\.js(\?.+|)$/, scripts, src;
try {
scripts = document.getElementsByTagName('script')
} catch(e) {
scripts = ''
}
for (index = scripts.length - 1; index >= 0; index--) {
src = scripts[index].src;
if (regexp.test(src)) {
return src.replace(regexp, '');
}
}
return ''
}());
//@ Ox.MODE <s> Mode ('dev' or 'min')
Ox.MODE = Ox.PATH.slice(0, -1).split('/').pop();
export const MODE = PATH.slice(0, -1).split('/').pop();
//@ Ox.PREFIXES <[str]> `['', 'K', 'M', 'G', 'T', 'P']`
Ox.PREFIXES = ['', 'K', 'M', 'G', 'T', 'P'];
export const PREFIXES = ['', 'K', 'M', 'G', 'T', 'P'];
//@ Ox.SEASONS <[s]> Names of the seasons of the year
Ox.SEASONS = ['Winter', 'Spring', 'Summer', 'Fall'];
export const SEASONS = ['Winter', 'Spring', 'Summer', 'Fall'];
//@ Ox.STACK_SIZE <n> Maximum number of arguments
Ox.STACK_SIZE = 65536;
export const STACK_SIZE = 65536;
//@ Ox.SYMBOLS <o> Unicode characters for symbols
Ox.SYMBOLS = {
export const SYMBOLS = {
dollar: '\u0024', cent: '\u00A2', pound: '\u00A3', currency: '\u00A4',
yen: '\u00A5', bullet: '\u2022', ellipsis: '\u2026', permille: '\u2030',
colon: '\u20A1', cruzeiro: '\u20A2', franc: '\u20A3', lira: '\u20A4',
@ -138,12 +151,12 @@ Ox.SYMBOLS = {
click: '\uF803', apple: '\uF8FF'
};
//@ Ox.VERSION <s> OxJS version number
Ox.VERSION = '0.1';
export const VERSION = '0.1';
//@ Ox.WEEKDAYS <[s]> Names of weekdays
Ox.WEEKDAYS = [
export const WEEKDAYS = [
'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'
];
//@ Ox.SHORT_WEEKDAYS <[s]> Short names of weekdays
Ox.SHORT_WEEKDAYS = Ox.WEEKDAYS.map(function(val) {
export const SHORT_WEEKDAYS = WEEKDAYS.map(function(val) {
return val.slice(0, 3);
});

View file

@ -2,15 +2,23 @@
'use strict';
/*@
Ox <f> The `Ox` object
See `Ox.wrap` for details.
(value) -> <o> wrapped value
value <*> Any value
@*/
this.Ox = function(value) {
return Ox.wrap(value);
};
import * as OxType from './Type.js';
import * as OxCollection from './Collection.js';
import * as OxObject from './Object.js';
import * as OxDOM from './DOM.js';
import * as OxString from './String.js';
import * as OxRequest from './Request.js';
const Ox = {};
Object.assign(Ox,
OxType,
OxCollection,
OxObject,
OxDOM,
OxString,
OxRequest,
);
/*@
Ox.load <f> Loads OxJS and, optionally, one or more modules
@ -52,7 +60,7 @@ Ox.load <f> Loads OxJS and, optionally, one or more modules
callback <f> Callback function
success <b> If true, all modules have been loaded successfully
@*/
Ox.load = function() {
export function load() {
var callback = arguments[arguments.length - 1],
length, loaded = 0, localeFiles = [], modules = {}, succeeded = 0,
type = Ox.typeOf(arguments[0]);
@ -76,10 +84,10 @@ Ox.load = function() {
if (!length) {
callback(true);
} else {
Ox.forEach(modules, function(options, module) {
Ox.getFile(
Ox.PATH + module + '/' + module + '.js?' + Ox.VERSION,
function() {
Ox.forEach(modules, async function(options, module) {
console.log("load module!", module, options)
// Ox.PATH + module + '/index.js?' + Ox.VERSION,
const obj = await import('../../' + module + '/index.js?' + Ox.VERSION);
Ox.load[module](options, function(success) {
succeeded += success;
if (++loaded == length) {
@ -88,8 +96,6 @@ Ox.load = function() {
});
}
});
}
);
});
}
});
@ -110,7 +116,7 @@ Ox.localStorage <f> localStorage wrapper
> Ox.test.localStorage.delete('foo')()
{}
@*/
Ox.localStorage = function(namespace) {
export function localStorage(namespace) {
var localStorage;
try {
// this will fail if third party cookies/storage is not allowed
@ -163,7 +169,7 @@ Ox.localStorage = function(namespace) {
Ox.Log <f> Logging module
@*/
Ox.Log = (function() {
var storage = Ox.localStorage('Ox'),
var storage = localStorage('Ox'),
log = storage('log') || {filter: [], filterEnabled: true},
that = function() {
var ret;
@ -239,7 +245,7 @@ Ox.loop <f> For-loop, functional-style
> Ox.loop(0, 3, 2, function() {})
4
@*/
Ox.loop = function() {
export function loop() {
var length = arguments.length,
start = length > 2 ? arguments[0] : 0,
stop = arguments[length > 2 ? 1 : 0],
@ -263,7 +269,7 @@ Ox.print <f> Prints its arguments to the console
> Ox.print('foo', 'bar').split(' ').slice(1).join(' ')
'foo bar'
@*/
Ox.print = function() {
export function print() {
var args = Ox.slice(arguments), date = new Date();
args.unshift(
date.toString().split(' ')[4] + '.' + (+date).toString().slice(-3)
@ -276,7 +282,7 @@ Ox.print = function() {
Ox.trace <f> Prints its arguments to the console, followed by a stack trace
(arg, ...) -> <s> String
@*/
Ox.trace = function() {
export function trace() {
var args = Ox.slice(arguments);
try {
throw new Error();
@ -296,12 +302,10 @@ Ox.uid <f> Returns a unique id
> Ox.uid() != Ox.uid()
true
@*/
Ox.uid = (function() {
var uid = 0;
return function() {
return ++uid;
};
}());
var _uid = 0;
export function uid() {
return ++_uid;
}
/*@
Ox.wrap <f> Wraps a value so that one can directly call any Ox function on it
@ -317,7 +321,7 @@ Ox.wrap <f> Wraps a value so that one can directly call any Ox function on it
> Ox.wrap('foobar').value()
'foobar'
@*/
Ox.wrap = function(value, chained) {
export function wrap(value, chained) {
// somewhat inspired by underscore.js
var wrapper = {
chain: function() {
@ -341,3 +345,55 @@ Ox.wrap = function(value, chained) {
});
return wrapper;
};
/*@
Ox.slice <f> Alias for `Array.prototype.slice.call`
(collection[, start[, stop]]) -> <a> Array
collection <a|o|s> Array-like
start <n> Start position
stop <n> Stop position
> (function() { return Ox.slice(arguments); }(1, 2, 3))
[1, 2, 3]
> Ox.slice('foo', 0, 1);
['f']
> Ox.slice({0: 'f', 1: 'o', 2: 'o', length: 3}, -2)
['o', 'o']
@*/
// FIXME: remove toArray alias
export function slice(collection, start, stop) {
return Array.prototype.slice.call(collection, start, stop);
};
// IE8 can't apply slice to NodeLists, returns an empty array if undefined is
// passed as stop and returns an array of null values if a string is passed as
// value. Firefox 3.6 returns an array of undefined values if a string is passed
// as value.
if (
slice([0]).length == 0
|| slice('0')[0] === null
|| slice('0')[0] === void 0
|| !(function() {
try {
return Ox.slice(document.getElementsByTagName('a'));
} catch (error) {}
}())
) {
// FIXME: remove toArray alias
slice = function(collection, start, stop) {
var args = stop === void 0 ? [start] : [start, stop],
array = [], index, length, ret;
if (Ox.typeOf(collection) == 'string') {
collection = collection.split('');
}
try {
ret = Array.prototype.slice.apply(collection, args);
} catch (error) {
length = collection.length;
for (index = 0; index < length; index++) {
array[index] = collection[index];
}
ret = Array.prototype.slice.apply(array, args);
}
return ret;
};
}

View file

@ -1,5 +1,27 @@
'use strict';
import * as OxCore from './Core.js';
import * as OxObject from './Object.js';
import * as OxConstants from './Constants.js';
import * as OxMath from './Math.js';
import * as OxType from './Type.js';
import * as OxArray from './Array.js';
import * as OxCollection from './Collection.js';
import * as OxString from './String.js';
const Ox = {};
Object.assign(Ox,
OxCore,
OxObject,
OxConstants,
OxMath,
OxType,
OxArray,
OxCollection,
OxString,
);
/*@
Ox.$ <f> Generic HTML element, mimics jQuery
value <s|h|w|?> tagname, selector, html element, `window`, or `document`
@ -31,7 +53,7 @@ Ox.$ <f> Generic HTML element, mimics jQuery
> Ox.$('<input>').val('red').val()
'red'
@*/
Ox.$ = Ox.element = function $(value) {
export function element(value) {
var elements = Ox.isArray(value) ? value // array of elements
: Ox.isNodeList(value) ? Ox.slice(value) // nodelist
@ -796,6 +818,8 @@ Ox.$ = Ox.element = function $(value) {
};
export const $ = element;
/*@
Ox.canvas <function> Generic canvas object
Returns an object with the properties: `canvas`, `context`, `data` and
@ -806,7 +830,7 @@ Ox.canvas <function> Generic canvas object
height <n> Height in px
image <e> Image object
@*/
Ox.canvas = function() {
export function canvas() {
var c = {}, isImage = arguments.length == 1,
image = isImage ? arguments[0] : {
width: arguments[0], height: arguments[1]
@ -821,13 +845,24 @@ Ox.canvas = function() {
return c;
};
var callbacks = [];
/*@
Ox.documentReady <function> Calls a callback function once the DOM is ready
(callback) -> <b> If true, the document was ready
callback <f> Callback function
@*/
Ox.documentReady = (function() {
var callbacks = [];
export function documentReady(callback) {
if (document.readyState == 'complete') {
callback();
return true;
} else {
callbacks.push(callback);
return false;
}
}
if (typeof document !== 'undefined') {
document.onreadystatechange = window.onload = function() {
if (document.readyState == 'complete') {
callbacks.forEach(function(callback) {
@ -836,13 +871,4 @@ Ox.documentReady = (function() {
document.onreadystatechange = window.onload = null;
}
};
return function(callback) {
if (document.readyState == 'complete') {
callback();
return true;
} else {
callbacks.push(callback);
return false;
}
};
}());
}

View file

@ -1,5 +1,17 @@
'use strict';
import * as OxObject from './Object.js';
import * as OxConstants from './Constants.js';
import * as OxMath from './Math.js';
const Ox = {};
Object.assign(Ox,
OxObject,
OxConstants,
OxMath
);
//@ Ox.getDate <f> Get the day of a date, optionally UTC
// see Ox.setSeconds for source code
@ -21,7 +33,7 @@ Ox.getDateInWeek <f> Get the date that falls on a given weekday in the same week
"Monday, December 27, 1999"
@*/
// fixme: why is this Monday first? shouldn't it then be "getDateInISOWeek"??
Ox.getDateInWeek = function(date, weekday, utc) {
export function getDateInWeek(date, weekday, utc) {
date = Ox.makeDate(date);
var sourceWeekday = Ox.getISODay(date, utc),
targetWeekday = Ox.isNumber(weekday) ? weekday
@ -50,7 +62,7 @@ Ox.getDayOfTheYear <f> Get the day of the year for a given date
> Ox.getDayOfTheYear(new Date("12/31/2004"))
366
@*/
Ox.getDayOfTheYear = function(date, utc) {
export function getDayOfTheYear(date, utc) {
date = Ox.makeDate(date);
var month = Ox.getMonth(date, utc),
year = Ox.getFullYear(date, utc);
@ -68,7 +80,7 @@ Ox.getDaysInMonth <f> Get the number of days in a given month
> Ox.getDaysInMonth(new Date('01/01/2004'), "February")
29
@*/
Ox.getDaysInMonth = function(year, month) {
export function getDaysInMonth(year, month) {
year = Ox.makeYear(year);
month = Ox.isNumber(month) ? month
: Ox.indexOf(Ox.MONTHS, function(v) {
@ -87,7 +99,7 @@ Ox.getDaysInYear <f> Get the number of days in a given year
> Ox.getDaysInYear(new Date('01/01/2004'))
366
@*/
Ox.getDaysInYear = function(year, utc) {
export function getDaysInYear(year, utc) {
return 365 + Ox.isLeapYear(Ox.makeYear(year, utc));
};
@ -97,7 +109,7 @@ Ox.getFirstDayOfTheYear <f> Get the weekday of the first day of a given year
> Ox.getFirstDayOfTheYear(new Date('01/01/2000'))
6
@*/
Ox.getFirstDayOfTheYear = function(date, utc) {
export function getFirstDayOfTheYear(date, utc) {
date = Ox.makeDate(date);
date = Ox.setMonth(date, 0, utc);
date = Ox.setDate(date, 1, utc);
@ -114,7 +126,7 @@ Ox.getISODate <f> Get the ISO date string for a given date
> Ox.getISODate(new Date('01/01/2000'))
'2000-01-01T00:00:00Z'
@*/
Ox.getISODate = function(date, utc) {
export function getISODate(date, utc) {
return Ox.formatDate(Ox.makeDate(date), '%FT%TZ', utc);
};
@ -128,7 +140,7 @@ Ox.getISODay <f> Get the ISO weekday of a given date
> Ox.getISODay(new Date('01/03/2000'))
1
@*/
Ox.getISODay = function(date, utc) {
export function getISODay(date, utc) {
return Ox.getDay(Ox.makeDate(date), utc) || 7;
};
@ -143,7 +155,7 @@ Ox.getISOWeek <f> Get the ISO week of a given date
1
@*/
Ox.getISOWeek = function(date, utc) {
export function getISOWeek(date, utc) {
date = Ox.makeDate(date);
// set date to Thursday of the same week
return Math.floor((Ox.getDayOfTheYear(Ox.setDate(
@ -162,7 +174,7 @@ Ox.getISOYear <f> Get the ISO year of a given date
2000
@*/
Ox.getISOYear = function(date, utc) {
export function getISOYear(date, utc) {
date = Ox.makeDate(date);
// set date to Thursday of the same week
return Ox.getFullYear(Ox.setDate(
@ -180,7 +192,7 @@ Ox.getISOYear = function(date, utc) {
// see Ox.setSeconds for source code
//@ Ox.getTime <f> Alias for `+new Date()`
Ox.getTime = function(utc) {
export function getTime(utc) {
return +new Date() - (utc ? Ox.getTimezoneOffset() : 0);
};
@ -189,7 +201,7 @@ Ox.getTimezoneOffset <f> Get the local time zone offset in milliseconds
([date]) -> <n> Offset in milliseconds
date <d|u> Return offset at this date (if undefined, return current offset)
@*/
Ox.getTimezoneOffset = function(date) {
export function getTimezoneOffset(date) {
return Ox.makeDate(date).getTimezoneOffset() * 60000;
};
@ -201,7 +213,7 @@ Ox.getTimezoneOffsetString <f> Get the local time zone offset as a string
> Ox.getTimezoneOffsetString(new Date('01/01/2000')).length
5
@*/
Ox.getTimezoneOffsetString = function(date) {
export function getTimezoneOffsetString(date) {
var offset = Ox.makeDate(date).getTimezoneOffset();
return (offset <= 0 ? '+' : '-')
+ Ox.pad(Math.floor(Math.abs(offset) / 60), 2)
@ -218,7 +230,7 @@ Ox.getWeek <f> Get the week of a given day
> Ox.getWeek(new Date('01/03/2000'))
1
@*/
Ox.getWeek = function(date, utc) {
export function getWeek(date, utc) {
date = Ox.makeDate(date);
return Math.floor((Ox.getDayOfTheYear(date, utc)
+ Ox.getFirstDayOfTheYear(date, utc) - 1) / 7);
@ -233,7 +245,7 @@ Ox.isLeapYear <f> Returns true if a given year is a leap year
> Ox.isLeapYear(new Date('01/01/2004'))
true
@*/
Ox.isLeapYear = function(year, utc) {
export function isLeapYear(year, utc) {
year = Ox.makeYear(year, utc);
return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
};
@ -255,7 +267,7 @@ Ox.makeDate <f> Takes a date, number or string, returns a date
> Ox.formatDate(Ox.makeDate(Ox.parseDate('-50')), '%Y')
'-50'
@*/
Ox.makeDate = function(date) {
export function makeDate(date) {
// Safari 4/5 (<= 534.59.10) doesn't parse YYYY, YYYY-MM or YYYY-MM-DD
if (Ox.isString(date) && Ox.isInvalidDate(new Date(date))) {
if (/^\d{4}$/.test(date)) {
@ -280,7 +292,7 @@ Ox.makeYear <f> Takes a date, number or string, returns a year
> Ox.makeYear('1970')
1970
@*/
Ox.makeYear = function(date, utc) {
export function makeYear(date, utc) {
return Ox.isDate(date) ? Ox.getFullYear(date, utc) : parseInt(date, 10);
};
@ -295,7 +307,7 @@ Ox.parseDate <f> Takes a string ('YYYY-MM-DD HH:MM:SS.MMM') and returns a date
> Ox.parseDate('50', true).getUTCFullYear()
50
@*/
Ox.parseDate = function(string, utc) {
export function parseDate(string, utc) {
var date,
defaults = [, 1, 1, 0, 0, 0, 0],
values = /(-?\d+)-?(\d+)?-?(\d+)? ?(\d+)?:?(\d+)?:?(\d+)?\.?(\d+)?/
@ -320,7 +332,7 @@ Ox.parseDate = function(string, utc) {
};
/*
Ox.parseDateRange = function(start, end, utc) {
export function parseDateRange(start, end, utc) {
var dates = [
Ox.parseDate(start, utc),
Ox.parseDate(end, utc)

View file

@ -1,5 +1,17 @@
'use strict';
import * as OxObject from './Object.js';
import * as OxConstants from './Constants.js';
import * as OxMath from './Math.js';
const Ox = {};
Object.assign(Ox,
OxObject,
OxConstants,
OxMath
);
/*@
Ox.encodeBase26 <b> Encode a number as bijective base26
See <a href="http://en.wikipedia.org/wiki/Bijective_numeration">
@ -15,7 +27,7 @@ Ox.encodeBase26 <b> Encode a number as bijective base26
> Ox.encodeBase26(4461)
'FOO'
@*/
Ox.encodeBase26 = function(number) {
export function encodeBase26(number) {
var string = '';
while (number) {
string = String.fromCharCode(65 + (number - 1) % 26) + string;
@ -31,7 +43,7 @@ Ox.decodeBase26 <f> Decodes a bijective base26-encoded number
> Ox.decodeBase26('foo')
4461
@*/
Ox.decodeBase26 = function(string) {
export function decodeBase26(string) {
return string.toUpperCase().split('').reverse().reduce(function(p, c, i) {
return p + (c.charCodeAt(0) - 64) * Math.pow(26, i);
}, 0);
@ -45,7 +57,7 @@ Ox.encodeBase32 <b> Encode a number as base32
> Ox.encodeBase32(33819)
'110V'
@*/
Ox.encodeBase32 = function(number) {
export function encodeBase32(number) {
return Ox.map(number.toString(32), function(char) {
return Ox.BASE_32_DIGITS[parseInt(char, 32)];
});
@ -61,7 +73,7 @@ Ox.decodeBase32 <f> Decodes a base32-encoded number
> Ox.decodeBase32('?').toString()
'NaN'
@*/
Ox.decodeBase32 = function(string) {
export function decodeBase32(string) {
return parseInt(Ox.map(string.toUpperCase(), function(char) {
var index = Ox.BASE_32_DIGITS.indexOf(
Ox.BASE_32_ALIASES[char] || char
@ -75,7 +87,7 @@ Ox.encodeBase64 <f> Encode a number as base64
> Ox.encodeBase64(32394)
'foo'
@*/
Ox.encodeBase64 = function(number) {
export function encodeBase64(number) {
return btoa(Ox.encodeBase256(number)).replace(/=/g, '');
};
@ -84,7 +96,7 @@ Ox.decodeBase64 <f> Decodes a base64-encoded number
> Ox.decodeBase64('foo')
32394
@*/
Ox.decodeBase64 = function(string) {
export function decodeBase64(string) {
return Ox.decodeBase256(atob(string));
};
@ -93,7 +105,7 @@ Ox.encodeBase128 <f> Encode a number as base128
> Ox.encodeBase128(1685487)
'foo'
@*/
Ox.encodeBase128 = function(number) {
export function encodeBase128(number) {
var string = '';
while (number) {
string = Ox.char(number & 127) + string;
@ -107,7 +119,7 @@ Ox.decodeBase128 <f> Decode a base128-encoded number
> Ox.decodeBase128('foo')
1685487
@*/
Ox.decodeBase128 = function(string) {
export function decodeBase128(string) {
return string.split('').reverse().reduce(function(p, c, i) {
return p + (c.charCodeAt(0) << i * 7);
}, 0);
@ -118,7 +130,7 @@ Ox.encodeBase256 <f> Encode a number as base256
> Ox.encodeBase256(6713199)
'foo'
@*/
Ox.encodeBase256 = function(number) {
export function encodeBase256(number) {
var string = '';
while (number) {
string = Ox.char(number & 255) + string;
@ -132,7 +144,7 @@ Ox.decodeBase256 <f> Decode a base256-encoded number
> Ox.decodeBase256('foo')
6713199
@*/
Ox.decodeBase256 = function(string) {
export function decodeBase256(string) {
return string.split('').reverse().reduce(function(p, c, i) {
return p + (c.charCodeAt(0) << i * 8);
}, 0);
@ -149,7 +161,7 @@ Ox.encodeDeflate <f> Encodes a string, using deflate
> Ox.decodeDeflate(Ox.encodeDeflate('foo'), function(str) { Ox.test(str, 'foo'); })
undefined
@*/
Ox.encodeDeflate = function(string, callback) {
export function encodeDeflate(string, callback) {
// Make sure we can encode the full unicode range of characters.
string = Ox.encodeUTF8(string);
// We can only safely write to RGB, so we need 1 pixel for 3 bytes.
@ -198,7 +210,7 @@ Ox.decodeDeflate <f> Decodes an deflate-encoded string
str <s> The decoded string
@*/
Ox.decodeDeflate = function(string, callback) {
export function decodeDeflate(string, callback) {
var image = new Image(),
// PNG file signature and IHDR chunk
data = '\u0089PNG\r\n\u001A\n\u0000\u0000\u0000\u000DIHDR'
@ -292,7 +304,7 @@ Ox.encodeUTF8 <f> Encodes a string as UTF-8
> Ox.encodeUTF8("¥€$")
"\u00C2\u00A5\u00E2\u0082\u00AC\u0024"
@*/
Ox.encodeUTF8 = function(string) {
export function encodeUTF8(string) {
return Ox.map(string, function(char) {
var code = char.charCodeAt(0),
string = '';
@ -320,7 +332,7 @@ Ox.decodeUTF8 <f> Decodes an UTF-8-encoded string
> Ox.decodeUTF8('\u00C2\u00A5\u00E2\u0082\u00AC\u0024')
'¥€$'
@*/
Ox.decodeUTF8 = function(string) {
export function decodeUTF8(string) {
var code, i = 0, length = string.length, ret = '';
function error(byte, position) {
throw new RangeError(

View file

@ -1,5 +1,17 @@
'use strict';
import * as OxObject from './Object.js';
import * as OxConstants from './Constants.js';
import * as OxMath from './Math.js';
const Ox = {};
Object.assign(Ox,
OxObject,
OxConstants,
OxMath
);
/*@
Ox.formatArea <f> Formats a number of meters as square meters or kilometers
> Ox.formatArea(1000)
@ -8,7 +20,7 @@ Ox.formatArea <f> Formats a number of meters as square meters or kilometers
'1 km\u00B2'
@*/
Ox.formatArea = function(number, decimals) {
export function formatArea(number, decimals) {
var k = number >= 1000000 ? 'k' : '';
decimals = Ox.isUndefined(decimals) ? 8 : decimals;
return Ox.formatNumber(
@ -25,7 +37,7 @@ Ox.formatCount <f> Returns a string like "2 items", "1 item" or "no items".
> Ox.formatCount(1000, 'city', 'cities')
'1,000 cities'
@*/
Ox.formatCount = function(number, singular, plural) {
export function formatCount(number, singular, plural) {
plural = (plural || singular + 's') + (number === 2 ? '{2}' : '');
return (number === 0 ? Ox._('no') : Ox.formatNumber(number))
+ ' ' + Ox._(number === 1 ? singular : plural);
@ -36,7 +48,7 @@ Ox.formatCurrency <f> Formats a number with a currency symbol
> Ox.formatCurrency(1000, '$', 2)
'$1,000.00'
@*/
Ox.formatCurrency = function(number, string, decimals) {
export function formatCurrency(number, string, decimals) {
return string + Ox.formatNumber(number, decimals);
};
@ -397,7 +409,7 @@ Ox.formatDateRange <f> Formats a date range as a string
> Ox.formatDateRange('-50-01-01 00:00:00', '-50-01-01 23:59:59')
'Sun, Jan 1, 50 BC, 00:00:00 - 23:59:59'
@*/
Ox.formatDateRange = function(start, end, utc) {
export function formatDateRange(start, end, utc) {
end = end || Ox.formatDate(new Date(), '%Y-%m-%d');
var isOneUnit = false,
range = [start, end],
@ -487,7 +499,7 @@ Ox.formatDateRangeDuration <f> Formats the duration of a date range as a string
> Ox.formatDateRangeDuration('2000-02', '2000-03', true)
'1 month'
@*/
Ox.formatDateRangeDuration = function(start, end, utc) {
export function formatDateRangeDuration(start, end, utc) {
end = end || Ox.formatDate(new Date(), '%Y-%m-%d');
var date = Ox.parseDate(start, utc),
dates = [start, end].map(function(string) {
@ -535,7 +547,7 @@ Ox.formatDegrees <f> Formats degrees as D°MM'SS"
> Ox.formatDegrees(-111.11, 'lng')
"111°06'36\"W"
@*/
Ox.formatDegrees = function(degrees, mode) {
export function formatDegrees(degrees, mode) {
var days = 0,
seconds = Math.round(Math.abs(degrees) * 3600),
sign = degrees < 0 ? '-' : '',
@ -558,11 +570,13 @@ Ox.formatDimensions <f> Formats valus as dimension
> Ox.formatDimensions([1920, 1080], 'px')
"1,920 × 1,080 px"
@*/
Ox.formatDimensions = Ox.formatResolution = function(array, string) {
export function formatDimensions(array, string) {
return array.map(function(value) {
return Ox.formatNumber(value);
}).join(' × ') + (string ? ' ' + string : '');
};
export const formatResolution = formatDimensions;
/*@
Ox.formatDuration <f> Formats a duration as a string
@ -595,7 +609,7 @@ Ox.formatDuration <f> Formats a duration as a string
> Ox.formatDuration(0, 'long')
''
@*/
Ox.formatDuration = function(seconds/*, decimals, format*/) {
export function formatDuration(seconds/*, decimals, format*/) {
var last = Ox.last(arguments),
format = last == 'short' || last == 'long' ? last : 'none',
decimals = Ox.isNumber(arguments[1]) ? arguments[1] : 0,
@ -649,7 +663,7 @@ Ox.formatISBN <f> Formats a string as an ISBN of a given length (10 or 13)
> Ox.formatISBN('978-0-306-40615-7', 10)
'0306406152'
@*/
Ox.formatISBN = function(isbn, length, dashes) {
export function formatISBN(isbn, length, dashes) {
var ret = '';
function getCheckDigit(isbn) {
var mod = isbn.length == 10 ? 11 : 10
@ -697,7 +711,7 @@ Ox.formatNumber <f> Formats a number with thousands separators
> Ox.formatNumber(666666.666)
"666,667"
@*/
Ox.formatNumber = function(number, decimals) {
export function formatNumber(number, decimals) {
var array = [],
abs = Math.abs(number),
split = abs.toFixed(decimals).split('.');
@ -726,7 +740,7 @@ Ox.formatOrdinal <f> Formats a number as an ordinal
> Ox.formatOrdinal(13)
"13th"
@*/
Ox.formatOrdinal = function(number) {
export function formatOrdinal(number) {
var string = Ox.formatNumber(number),
length = string.length,
last = string[length - 1],
@ -751,7 +765,7 @@ Ox.formatPercent <f> Formats the relation of two numbers as a percentage
> Ox.formatPercent(1, 1000, 2)
"0.10%"
@*/
Ox.formatPercent = function(number, total, decimals) {
export function formatPercent(number, total, decimals) {
return Ox.formatNumber(number / total * 100, decimals) + Ox._('%');
};
@ -772,7 +786,7 @@ Ox.formatRoman <f> Formats a number as a roman numeral
> Ox.formatRoman(10000)
'MMMMMMMMMM'
@*/
Ox.formatRoman = function(number) {
export function formatRoman(number) {
var string = '';
Ox.forEach({
M: 1000, CM: 900, D: 500, CD: 400, C: 100, XC: 90,
@ -789,7 +803,7 @@ Ox.formatRoman = function(number) {
/*@
Ox.formatSRT <f> Formats subtitles as SRT
@*/
Ox.formatSRT = function(subtitles) {
export function formatSRT(subtitles) {
return '\ufeff' + Ox.sortBy(subtitles, ['in', 'out']).map(function(subtitle, index) {
return [
index + 1,
@ -816,7 +830,7 @@ Ox.formatString <f> Basic string formatting
> Ox.formatString('{b}', {a: 'foobar'}, true)
'{b}'
@*/
Ox.formatString = function(string, collection, keepUnmatched) {
export function formatString(string, collection, keepUnmatched) {
return string.replace(/\{([^}]+)\}/g, function(string, match) {
// make sure to not split at escaped dots ('\.')
var key,
@ -844,7 +858,7 @@ Ox.formatUnit <f> Formats a number with a unit
> Ox.formatUnit(100/3, '%')
'33%'
@*/
Ox.formatUnit = function(number, string, decimals) {
export function formatUnit(number, string, decimals) {
return Ox.formatNumber(number, decimals)
+ (/^[:%]/.test(string) ? '' : ' ') + string;
};
@ -859,7 +873,7 @@ Ox.formatValue <f> Formats a numerical value
"1.15 GiB"
@*/
// fixme: is this the best name?
Ox.formatValue = function(number, string, bin) {
export function formatValue(number, string, bin) {
var base = bin ? 1024 : 1000,
length = Ox.PREFIXES.length,
ret;

View file

@ -1,5 +1,17 @@
'use strict';
import * as OxObject from './Object.js';
import * as OxConstants from './Constants.js';
import * as OxMath from './Math.js';
const Ox = {};
Object.assign(Ox,
OxObject,
OxConstants,
OxMath
);
/*@
Ox.cache <f> Memoize a function
fn <f> function
@ -15,7 +27,7 @@ Ox.cache <f> Memoize a function
false
@*/
// TODO: add async test
Ox.cache = function(fn, options) {
export function cache(fn, options) {
var cache = {}, ret;
options = options || {};
options.async = options.async || false;
@ -65,7 +77,7 @@ Ox.debounce <f> Runs a function once it stops being called for a given interval
ms <n|250> Interval in milliseconds
immediate <b|false> If true, function is called once immediately
@*/
Ox.debounce = function(fn/*, ms, immediate*/) {
export function debounce(fn/*, ms, immediate*/) {
var args,
immediate = Ox.last(arguments) === true,
ms = Ox.isNumber(arguments[1]) ? arguments[1] : 250,
@ -95,7 +107,7 @@ Ox.identity <f> Returns its first argument
> Ox.identity(Infinity)
Infinity
@*/
Ox.identity = function(value) {
export function identity(value) {
return value;
};
@ -108,7 +120,7 @@ Ox.noop <f> Returns undefined and calls optional callback without arguments
> Ox.noop(1, 2, 3, function() { Ox.test(arguments.length, 0); })
undefined
@*/
Ox.noop = function() {
export function noop() {
var callback = Ox.last(arguments);
Ox.isFunction(callback) && callback();
};
@ -118,7 +130,7 @@ Ox.once <f> Runs a function once, and then never again
(fn) -> <f> Function that will run only once
fn <f> Function to run once
@*/
Ox.once = function(fn) {
export function once(fn) {
var once = false;
return function() {
if (!once) {
@ -139,11 +151,11 @@ Ox.queue <f> Queue of asynchronous function calls with cached results
fn <f> Queued function
maxThreads <n|10> Number of parallel function calls
@*/
Ox.queue = function(fn, maxThreads) {
export function queue(fn, maxThreads) {
maxThreads = maxThreads || 10;
var processing = [],
queued = [],
ret = Ox.cache(function() {
ret = cache(function() {
var args = Ox.slice(arguments);
queued.push({args: args, key: getKey(args)});
process();
@ -199,7 +211,7 @@ Ox.throttle <f> Runs a function at most once per given interval
fn <f> Function to throttle
ms <n|250> Interval in milliseconds
@*/
Ox.throttle = function(fn, ms) {
export function throttle(fn, ms) {
var args,
timeout;
ms = arguments.length == 1 ? 250 : ms;
@ -222,7 +234,7 @@ Ox.throttle = function(fn, ms) {
Ox.time <f> Returns the time it takes to execute a given function
(fn) -> <n> Time in milliseconds
@*/
Ox.time = function(fn) {
export function time(fn) {
var time = new Date();
fn();
return new Date() - time;

View file

@ -1,46 +1,56 @@
'use strict';
(function() {
import * as OxObject from './Object.js';
import * as OxConstants from './Constants.js';
import * as OxMath from './Math.js';
// fixme: make all this work with different types of "points"
// i.e. {lat, lng}, [lat, lng]
const Ox = {};
function deg(point) {
Object.assign(Ox,
OxObject,
OxConstants,
OxMath
);
// fixme: make all this work with different types of "points"
// i.e. {lat, lng}, [lat, lng]
function deg(point) {
return Ox.map(point, function(val) {
return Ox.mod(Ox.deg(val) + 180, 360) - 180;
});
}
}
function rad(point) {
function rad(point) {
return Ox.map(point, function(val) {
return Ox.rad(val);
});
}
}
function splitArea(area) {
function splitArea(area) {
return Ox.crossesDateline(area.sw, area.ne) ? [
{sw: area.sw, ne: {lat: area.ne.lat, lng: 180}},
{sw: {lat: area.sw.lat, lng: -180}, ne: area.ne}
] : [area];
}
}
/*@
Ox.crossesDateline <f> Returns true if a given line crosses the dateline
/*@
Ox.crossesDateline <f> Returns true if a given line crosses the dateline
> Ox.crossesDateline({lat: 0, lng: -90}, {lat: 0, lng: 90})
false
> Ox.crossesDateline({lat: 0, lng: 90}, {lat: 0, lng: -90})
true
@*/
// FIXME: argument should be {w: ..., e: ...}
Ox.crossesDateline = function(pointA, pointB) {
@*/
// FIXME: argument should be {w: ..., e: ...}
export function crossesDateline(pointA, pointB) {
return pointA.lng > pointB.lng;
};
};
/*@
Ox.getArea <f> Returns the area in square meters of a given rectancle
@*/
// FIXME: argument should be {sw: ..., ne: ...}
Ox.getArea = function(pointA, pointB) {
/*@
Ox.getArea <f> Returns the area in square meters of a given rectancle
@*/
// FIXME: argument should be {sw: ..., ne: ...}
export function getArea(pointA, pointB) {
/*
area of a ring between two latitudes:
2 * PI * r^2 * abs(sin(latA) - sin(latB))
@ -60,31 +70,31 @@
return Math.pow(Ox.EARTH_RADIUS, 2)
* Math.abs(Math.sin(pointA.lat) - Math.sin(pointB.lat))
* Math.abs(pointA.lng - pointB.lng);
};
};
/*@
Ox.getAverageBearing <f> Returns the average of two bearings
/*@
Ox.getAverageBearing <f> Returns the average of two bearings
> Ox.getAverageBearing(0, 90)
45
> Ox.getAverageBearing(10, 350)
0
@*/
// FIXME: find the proper name of this operation
// FIMXE: use in manhattan grid example
Ox.getAverageBearing = function(bearingA, bearingB) {
@*/
// FIXME: find the proper name of this operation
// FIMXE: use in manhattan grid example
export function getAverageBearing(bearingA, bearingB) {
return Ox.mod((bearingA + bearingB) / 2 + (
Math.abs(bearingA - bearingB) > 180 ? 180 : 0
), 360);
};
};
/*@
Ox.getBearing <f> Returns the bearing from one point to another
/*@
Ox.getBearing <f> Returns the bearing from one point to another
> Ox.getBearing({lat: -45, lng: 0}, {lat: 45, lng: 0})
0
> Ox.getBearing({lat: 0, lng: -90}, {lat: 0, lng: 90})
90
@*/
Ox.getBearing = function(pointA, pointB) {
@*/
export function getBearing(pointA, pointB) {
pointA = rad(pointA);
pointB = rad(pointB);
var x = Math.cos(pointA.lat) * Math.sin(pointB.lat)
@ -93,20 +103,20 @@
y = Math.sin(pointB.lng - pointA.lng)
* Math.cos(pointB.lat);
return (Ox.deg(Math.atan2(y, x)) + 360) % 360;
};
};
// FIXME: name, docs
Ox.getBearingDifference = function(bearingA, bearingB) {
// FIXME: name, docs
export function getBearingDifference(bearingA, bearingB) {
var difference = Math.abs(bearingA - bearingB);
return difference > 180 ? 360 - difference : difference;
};
};
/*@
Ox.getCenter <f> Returns the center of a recangle on a spehre
/*@
Ox.getCenter <f> Returns the center of a recangle on a spehre
> Ox.getCenter({lat: -45, lng: -90}, {lat: 45, lng: 90})
{lat: 0, lng: 0}
@*/
Ox.getCenter = function(pointA, pointB) {
@*/
export function getCenter(pointA, pointB) {
pointA = rad(pointA);
pointB = rad(pointB);
var x = Math.cos(pointB.lat)
@ -119,46 +129,46 @@
lat = Math.atan2(Math.sin(pointA.lat) + Math.sin(pointB.lat), d),
lng = pointA.lng + Math.atan2(y, Math.cos(pointA.lat) + x);
return deg({lat: lat, lng: lng});
};
};
/*@
Ox.getCircle <f> Returns points on a circle around a given point
/*@
Ox.getCircle <f> Returns points on a circle around a given point
(center, radius, precision) -> <a> Points
center <o> Center point ({lat, lng})
radius <n> Radius in meters
precision <n> Precision (the circle will have 2^precision segments)
@*/
Ox.getCircle = function(center, radius, precision) {
@*/
export function getCircle(center, radius, precision) {
return Ox.range(
0, 360, 360 / Math.pow(2, precision)
).map(function(bearing) {
return Ox.getPoint(center, radius, bearing);
});
};
};
// FIXME: name, docs
Ox.getClosestBearing = function(bearing, bearings) {
// FIXME: name, docs
export function getClosestBearing(bearing, bearings) {
var differences = bearings.map(function(bearing_) {
return getBearingDifference(bearing, bearing_);
});
return bearings[differences.indexOf(Ox.min(differences))];
};
};
/*@
Ox.getDegreesPerMeter <f> Returns degrees per meter at a given latitude
/*@
Ox.getDegreesPerMeter <f> Returns degrees per meter at a given latitude
> 360 / Ox.getDegreesPerMeter(0)
Ox.EARTH_CIRCUMFERENCE
@*/
Ox.getDegreesPerMeter = function(lat) {
@*/
export function getDegreesPerMeter(lat) {
return 360 / Ox.EARTH_CIRCUMFERENCE / Math.cos(lat * Math.PI / 180);
};
};
/*@
Ox.getDistance <f> Returns the distance in meters between two points
/*@
Ox.getDistance <f> Returns the distance in meters between two points
> Ox.getDistance({lat: -45, lng: -90}, {lat: 45, lng: 90}) * 2
Ox.EARTH_CIRCUMFERENCE
@*/
Ox.getDistance = function(pointA, pointB) {
@*/
export function getDistance(pointA, pointB) {
pointA = rad(pointA);
pointB = rad(pointB);
return Math.acos(
@ -166,14 +176,14 @@
+ Math.cos(pointA.lat) * Math.cos(pointB.lat)
* Math.cos(pointB.lng - pointA.lng)
) * Ox.EARTH_RADIUS;
};
};
/*@
Ox.getLatLngByXY <f> Returns lat/lng for a given x/y on a 1x1 mercator projection
/*@
Ox.getLatLngByXY <f> Returns lat/lng for a given x/y on a 1x1 mercator projection
> Ox.getLatLngByXY({x: 0.5, y: 0.5})
{lat: -0, lng: 0}
@*/
Ox.getLatLngByXY = function(xy) {
@*/
export function getLatLngByXY(xy) {
function getValue(value) {
return (value - 0.5) * 2 * Math.PI;
}
@ -181,16 +191,16 @@
lat: -Ox.deg(Math.atan(Ox.sinh(getValue(xy.y)))),
lng: Ox.deg(getValue(xy.x))
};
};
};
/*@
Ox.getLine <f> Returns points on a line between two points
/*@
Ox.getLine <f> Returns points on a line between two points
(pointA, pointB, precision) -> <a> Points
pointA <o> Start point ({lat, lng})
pointB <o> End point ({lat, lng})
precision <n> Precision (the line will have 2^precision segments)
@*/
Ox.getLine = function(pointA, pointB, precision) {
@*/
export function getLine(pointA, pointB, precision) {
var line = [pointA, pointB], points;
while (precision > 0) {
points = [line[0]];
@ -204,23 +214,23 @@
precision--;
}
return line;
};
};
/*@
Ox.getMetersPerDegree <f> Returns meters per degree at a given latitude
/*@
Ox.getMetersPerDegree <f> Returns meters per degree at a given latitude
> Ox.getMetersPerDegree(0) * 360
Ox.EARTH_CIRCUMFERENCE
@*/
Ox.getMetersPerDegree = function(lat) {
@*/
export function getMetersPerDegree(lat) {
return Math.cos(lat * Math.PI / 180) * Ox.EARTH_CIRCUMFERENCE / 360;
};
};
/*@
Ox.getPoint <f> Returns a point at a given distance/bearing from a given point
/*@
Ox.getPoint <f> Returns a point at a given distance/bearing from a given point
> Ox.getPoint({lat: -45, lng: 0}, Ox.EARTH_CIRCUMFERENCE / 4, 0)
{lat: 45, lng: 0}
@*/
Ox.getPoint = function(point, distance, bearing) {
@*/
export function getPoint(point, distance, bearing) {
var pointB = {};
point = rad(point);
distance /= Ox.EARTH_RADIUS;
@ -234,14 +244,14 @@
Math.cos(distance) - Math.sin(point.lat) * Math.sin(pointB.lat)
);
return deg(pointB);
};
};
/*@
Ox.getXYByLatLng <f> Returns x/y on a 1x1 mercator projection for a given lat/lng
/*@
Ox.getXYByLatLng <f> Returns x/y on a 1x1 mercator projection for a given lat/lng
> Ox.getXYByLatLng({lat: 0, lng: 0})
{x: 0.5, y: 0.5}
@*/
Ox.getXYByLatLng = function(latlng) {
@*/
export function getXYByLatLng(latlng) {
function getValue(value) {
return value / (2 * Math.PI) + 0.5;
}
@ -249,19 +259,19 @@
x: getValue(Ox.rad(latlng.lng)),
y: getValue(Ox.asinh(Math.tan(Ox.rad(-latlng.lat))))
};
};
};
/*@
Ox.isPolar <f> Returns true if a given point is outside the bounds of a mercator projection
/*@
Ox.isPolar <f> Returns true if a given point is outside the bounds of a mercator projection
> Ox.isPolar({lat: 90, lng: 0})
true
@*/
Ox.isPolar = function(point) {
@*/
export function isPolar(point) {
return point.lat < Ox.MIN_LATITUDE || point.lat > Ox.MAX_LATITUDE;
};
};
/*@
Ox.containsArea <f> Returns true if an area contains another area
/*@
Ox.containsArea <f> Returns true if an area contains another area
<script>
Ox.test.areas = [
{sw: {lat: -30, lng: -30}, ne: {lat: 30, lng: 30}},
@ -274,10 +284,10 @@
false
> Ox.containsArea(Ox.test.areas[2], Ox.test.areas[3])
true
@*/
// FIXME: Shouldn't this be rewritten as a test
// if the intersection is equal to the inner area?
Ox.containsArea = function(areaA, areaB) {
@*/
// FIXME: Shouldn't this be rewritten as a test
// if the intersection is equal to the inner area?
export function containsArea(areaA, areaB) {
// If an area crosses the dateline,
// we split it into two parts,
// west and east of the dateline
@ -300,10 +310,10 @@
return ret;
});
return ret;
};
};
/*@
Ox.intersectAreas <f> Returns the intersection of two areas, or null
/*@
Ox.intersectAreas <f> Returns the intersection of two areas, or null
<script>
Ox.test.areas = [
{sw: {lat: -10, lng: -10}, ne: {lat: 0, lng: 0}},
@ -316,10 +326,10 @@
{sw: {lat: 0, lng: 0}, ne: {lat: 0, lng: 0}}
> Ox.intersectAreas([Ox.test.areas[2], Ox.test.areas[3]])
{sw: {lat: 25, lng: -155}, ne: {lat: 30, lng: -150}}
@*/
// FIXME: handle the a corner case where
// two areas have two intersections
Ox.intersectAreas = function(areas) {
@*/
// FIXME: handle the a corner case where
// two areas have two intersections
export function intersectAreas(areas) {
var intersections, ret;
// If an area crosses the dateline,
// we split it into two parts,
@ -361,10 +371,10 @@
}
});
return ret ? Ox.joinAreas(ret) : null;
};
};
/*@
Ox.joinAreas <f> Joins an array of areas
/*@
Ox.joinAreas <f> Joins an array of areas
<script>
Ox.test.areas = [
{sw: {lat: -30, lng: 150}, ne: {lat: -20, lng: 160}},
@ -374,8 +384,8 @@
</script>
> Ox.joinAreas(Ox.test.areas)
{sw: {lat: -30, lng: 150}, ne: {lat: 30, lng: -150}}
@*/
Ox.joinAreas = function(areas) {
@*/
export function joinAreas(areas) {
// While the combined latitude is trivial (min to max), the combined longitude
// spans from the eastern to the western edge of the largest gap between areas
var ret = areas[0],
@ -474,7 +484,5 @@
ret.ne.lng = gaps[0].sw.lng;
}
return ret;
};
}());
};

View file

@ -1,8 +1,23 @@
'use strict';
(function() {
import * as OxArray from './Array.js';
import * as OxObject from './Object.js';
import * as OxConstants from './Constants.js';
import * as OxMath from './Math.js';
import * as OxString from './String.js';
var defaultTags = [
const Ox = {};
Object.assign(Ox,
OxArray,
OxObject,
OxConstants,
OxMath,
OxString,
);
var defaultTags = [
// inline formatting
{'name': 'b'},
{'name': 'bdi'},
@ -101,7 +116,7 @@
}).join('');
});
function addLinks(string, obfuscate) {
function _addLinks(string, obfuscate) {
return string
.replace(
/\b((https?:\/\/|www\.).+?)([.,:;!?)\]]*?(\s|$))/gi,
@ -119,9 +134,9 @@
return Ox.encodeEmailAddress(mail);
} : '<a href="mailto:$1">$1</a>'
);
}
}
function decodeHTMLEntities(string) {
function _decodeHTMLEntities(string) {
return string
.replace(
new RegExp('(' + Ox.values(htmlEntities).join('|') + ')', 'g'),
@ -139,11 +154,11 @@
);
}
);
}
}
// Splits a string into text (even indices) and tags (odd indices), ignoring
// tags with starting positions that are included in the ignore array
function splitHTMLTags(string, ignore) {
// Splits a string into text (even indices) and tags (odd indices), ignoring
// tags with starting positions that are included in the ignore array
function splitHTMLTags(string, ignore) {
var isTag = false, ret = [''];
ignore = ignore || [];
Ox.forEach(string, function(char, i) {
@ -158,10 +173,10 @@
}
});
return ret;
}
}
/*@
Ox.addLinks <f> Takes a string and adds links for e-mail addresses and URLs
/*@
Ox.addLinks <f> Takes a string and adds links for e-mail addresses and URLs
(string[, isHTML]) -> <s> Formatted string
string <s> String
isHTML <b|false> If true, ignore matches in tags or enclosed by links
@ -171,8 +186,8 @@
'<a href="http://www.foo.com/bar#baz">www.foo.com/bar#baz</a>, etc.'
> Ox.addLinks('<a href="http://www.foo.com">www.foo.com</a>', true)
'<a href="http://www.foo.com">www.foo.com</a>'
@*/
Ox.addLinks = function(string, isHTML) {
@*/
export function addLinks(string, isHTML) {
var isLink = false;
return isHTML
? splitHTMLTags(string).map(function(string, i) {
@ -184,17 +199,17 @@
isLink = false;
}
}
return isTag || isLink ? string : addLinks(string);
return isTag || isLink ? string : _addLinks(string);
}).join('')
: Ox.normalizeHTML(addLinks(string));
};
: normalizeHTML(_addLinks(string));
};
/*@
Ox.encodeEmailAddress <f> Returns obfuscated mailto: link
/*@
Ox.encodeEmailAddress <f> Returns obfuscated mailto: link
> Ox.encodeEmailAddress('mailto:foo@bar.com').indexOf(':') > -1
true
@*/
Ox.encodeEmailAddress = function(address, text) {
@*/
export function encodeEmailAddress(address, text) {
var parts = ['mailto:' + address, text || address].map(function(part) {
return Ox.map(part, function(char) {
var code = char.charCodeAt(0);
@ -205,10 +220,10 @@
});
});
return '<a href="' + parts[0] + '">' + parts[1] + '</a>';
};
};
/*@
Ox.encodeHTMLEntities <f> Encodes HTML entities
/*@
Ox.encodeHTMLEntities <f> Encodes HTML entities
(string[, encodeAll]) -> <s> String
string <s> String
encodeAll <b|false> If true, encode characters > 127 as numeric entities
@ -216,8 +231,8 @@
'&lt;&apos;&amp;&quot;&gt; äbçdê'
> Ox.encodeHTMLEntities('<\'&"> äbçdê', true)
'&lt;&apos;&amp;&quot;&gt; &#x00E4;b&#x00E7;d&#x00EA;'
@*/
Ox.encodeHTMLEntities = function(string, encodeAll) {
@*/
export function encodeHTMLEntities(string, encodeAll) {
return Ox.map(String(string), function(char) {
var code = char.charCodeAt(0);
if (code < 128) {
@ -229,10 +244,10 @@
}
return char;
});
};
};
/*@
Ox.decodeHTMLEntities <f> Decodes HTML entities
/*@
Ox.decodeHTMLEntities <f> Decodes HTML entities
(string[, decodeAll]) -> <s> String
string <s> String
decodeAll <b|false> If true, decode named entities for characters > 127
@ -254,15 +269,15 @@
'<b>β</b>'
> Ox.decodeHTMLEntities('&lt;b&gt;')
'<b>'
@*/
Ox.decodeHTMLEntities = function(string, decodeAll) {
@*/
export function decodeHTMLEntities(string, decodeAll) {
return decodeAll
? Ox.decodeHTMLEntities(Ox.normalizeHTML(string))
: decodeHTMLEntities(string);
};
? decodeHTMLEntities(normalizeHTML(string))
: _decodeHTMLEntities(string);
};
/*@
Ox.highlight <f> Highlight matches in string
/*@
Ox.highlight <f> Highlight matches in string
(string, query, classname[, isHTML]) -> Output string
string <s> Input string
query <r|s> Case-insentitive query string, or regular expression
@ -292,8 +307,8 @@
'foo<p>bar</p>baz'
> Ox.highlight('foo <br/>bar baz', 'foo bar', 'c', true)
'<span class="c">foo <br>bar</span> baz'
@*/
Ox.highlight = function(string, query, classname, isHTML) {
@*/
export function highlight(string, query, classname, isHTML) {
if (!query) {
return string;
}
@ -372,7 +387,7 @@
});
// we may have enclosed single opening or closing tags in a span
if (matches.length && tags.length) {
string = Ox.normalizeHTML(string);
string = normalizeHTML(string);
}
} else {
string = Ox.encodeHTMLEntities(
@ -386,23 +401,23 @@
});
}
return string;
};
};
/*@
Ox.normalizeHTML <f> Normalize HTML (using the DOM)
/*@
Ox.normalizeHTML <f> Normalize HTML (using the DOM)
> Ox.normalizeHTML('<b>foo')
'<b>foo</b>'
> Ox.normalizeHTML('<b>foo</b></b>')
'<b>foo</b>'
> Ox.normalizeHTML('&lt;&apos;&amp;&quot;&gt; &#x00E4;b&#x00E7;d&#x00EA;')
'&lt;\'&amp;"&gt; äbçdê'
@*/
Ox.normalizeHTML = function(html) {
@*/
export function normalizeHTML(html) {
return regexp.html.test(html) ? Ox.$('<div>').html(html).html() : html;
};
};
/*@
Ox.parseMarkdown <f> Parses (a tiny subset of) Markdown.
/*@
Ox.parseMarkdown <f> Parses (a tiny subset of) Markdown.
Supports `*emphasis*`, `_emphasis_`, `**strong**`, `__strong__`,
`` `code` ``, ``` ``code with backtick (`)`` ```,
```` ```classname\ngithub-style\ncode blocks\n``` ````,
@ -430,8 +445,8 @@
1
> Ox(Ox.parseMarkdown('<mail@example.com>')).decodeHTMLEntities()
'<a href="mailto:mail@example.com">mail@example.com</a>'
*/
Ox.parseMarkdown = function(string) {
*/
export function parseMarkdown(string) {
// see https://github.com/coreyti/showdown/blob/master/src/showdown.js
var array = [];
return string.replace(/\r\n/g, '\n').replace(/\r/g, '\n')
@ -489,10 +504,10 @@
return array[parseInt(index)];
}
);
};
};
/*@
Ox.sanitizeHTML <f> Takes untrusted HTML and returns something trustworthy
/*@
Ox.sanitizeHTML <f> Takes untrusted HTML and returns something trustworthy
> Ox.sanitizeHTML('http://foo.com, ...')
'<a href="http://foo.com">http://foo.com</a>, ...'
> Ox.sanitizeHTML('http://foo.com/foo?bar&baz, ...')
@ -537,8 +552,8 @@
'&lt;<a href="http://foo.com">http://foo.com</a>&gt;'
> Ox.sanitizeHTML('<foo value="http://foo.com"></foo>')
'"&lt;foo value="http://foo.com"&gt;&lt;/foo&gt;"'
@*/
Ox.sanitizeHTML = function(html, tags, globalAttributes) {
@*/
export function sanitizeHTML(html, tags, globalAttributes) {
tags = tags || defaultTags;
globalAttributes = globalAttributes || [];
@ -648,21 +663,20 @@
}).join('');
//FIXME: dont add links to urls inside of escaped tags
html = Ox.addLinks(html, true);
html = addLinks(html, true);
html = html.replace(/\n\n/g, '<br/><br/>');
// Close extra opening and remove extra closing tags.
// Note: this converts '&apos;' to "'" and '&quot;' to '"'
return Ox.normalizeHTML(html);
return normalizeHTML(html);
};
};
/*@
Ox.stripTags <f> Strips HTML tags from a string
/*@
Ox.stripTags <f> Strips HTML tags from a string
> Ox.stripTags('f<span>o</span>o')
'foo'
@*/
Ox.stripTags = function(string) {
@*/
export function stripTags(string) {
return string.replace(/<.*?>/g, '');
};
};
}());

View file

@ -1,9 +1,21 @@
'use strict';
import * as OxObject from './Object.js';
import * as OxConstants from './Constants.js';
import * as OxMath from './Math.js';
const Ox = {};
Object.assign(Ox,
OxObject,
OxConstants,
OxMath
);
/*@
Ox.oshash <f> Calculates oshash for a given file or blob object. Async.
@*/
Ox.oshash = function(file, callback) {
export function oshash(file, callback) {
// Needs to go via string to work for files > 2GB
var hash = fromString(file.size.toString());
@ -100,7 +112,7 @@ Ox.oshash = function(file, callback) {
/*@
Ox.SHA1 <f> Calculates SHA1 hash of the given string
@*/
Ox.SHA1 = function(msg) {
export function SHA1(msg) {
function rotate_left(n,s) {
var t4 = ( n<<s ) | (n>>>(32-s));

View file

@ -1,5 +1,21 @@
'use strict';
import * as OxArray from './Array.js';
import * as OxObject from './Object.js';
import * as OxConstants from './Constants.js';
import * as OxMath from './Math.js';
import * as OxString from './String.js';
const Ox = {};
Object.assign(Ox,
OxArray,
OxObject,
OxConstants,
OxMath,
OxString,
);
/*@
Ox.doc <f> Generates documentation for annotated JavaScript
(source) -> <[o]> Array of doc objects

View file

@ -1,26 +1,40 @@
'use strict';
import * as OxArray from './Array.js';
import * as OxObject from './Object.js';
import * as OxConstants from './Constants.js';
import * as OxMath from './Math.js';
import * as OxString from './String.js';
(function() {
const Ox = {};
var log, translations = {};
Object.assign(Ox,
OxArray,
OxObject,
OxConstants,
OxMath,
OxString,
);
/*@
Ox.getLocale <f> Returns locale
var log, translations = {};
/*@
Ox.getLocale <f> Returns locale
() -> <s> Locale (like 'de' or 'fr')
@*/
Ox.getLocale = function() {
@*/
export function getLocale() {
return Ox.LOCALE;
};
};
/*@
Ox.setLocale <f> Sets locale
/*@
Ox.setLocale <f> Sets locale
(locale[, url], callback)
locale <s> Locale (like 'de' or 'fr')
url <s|[s]> one or more URLs of JSON file with additional translations
callback <f> Callback function
success <b> If true, locale has been set
@*/
Ox.setLocale = function(locale, url, callback) {
@*/
export function setLocale(locale, url, callback) {
var isValidLocale = Ox.contains(Object.keys(Ox.LOCALE_NAMES), locale),
urls = [];
if (arguments.length == 2) {
@ -61,30 +75,29 @@
} else {
callback(false);
}
};
};
/*@
Ox._ <f> Localizes a string
/*@
Ox._ <f> Localizes a string
(string[, options]) -> <s> Localized string
string <s> English string
options <o> Options passed to Ox.formatString
@*/
Ox._ = function(value, options) {
@*/
export function _(value, options) {
var translation = translations[value];
log && log(value, translation);
translation = translation || value || '';
return Ox.formatString(translation, options);
};
};
/*@
Ox._.log <f> Registers a logging function
/*@
Ox._.log <f> Registers a logging function
(callback) -> <u> undefined
callback <f> Callback function
english <s> English string
translation <s> Translated string
@*/
Ox._.log = function(callback) {
@*/
_.log = function(callback) {
log = callback;
};
};
})();

View file

@ -1,12 +1,20 @@
'use strict';
import * as OxArray from './Array.js';
const Ox = {};
Object.assign(Ox,
OxArray,
);
/*@
Ox.acosh <f> Inverse hyperbolic cosine
Missing from `Math`.
> Ox.acosh(1)
0
@*/
Ox.acosh = function(x) {
export function acosh(x) {
return Math.log(x + Math.sqrt(x * x - 1));
};
@ -16,7 +24,7 @@ Ox.asinh <f> Inverse hyperbolic sine
> Ox.asinh(0)
0
@*/
Ox.asinh = function(x) {
export function asinh(x) {
return Math.log(x + Math.sqrt(x * x + 1));
};
@ -26,7 +34,7 @@ Ox.atanh <f> Inverse hyperbolic tangent
> Ox.atanh(0)
0
@*/
Ox.atanh = function(x) {
export function atanh(x) {
return 0.5 * Math.log((1 + x) / (1 - x));
};
@ -36,7 +44,7 @@ Ox.cosh <f> Hyperbolic cosine
> Ox.cosh(0)
1
@*/
Ox.cosh = function(x) {
export function cosh(x) {
return (Math.exp(x) + Math.exp(-x)) / 2;
};
@ -46,7 +54,7 @@ Ox.deg <f> Takes radians, returns degrees
> Ox.deg(2 * Math.PI)
360
@*/
Ox.deg = function(rad) {
export function deg(rad) {
return rad * 180 / Math.PI;
};
@ -58,7 +66,7 @@ Ox.hypot <f> Returns the square root of the sum of the squares of its arguments
> Ox.hypot(1, 1, 1)
Math.sqrt(3)
@*/
Ox.hypot = function() {
export function hypot() {
return Math.sqrt(Ox.slice(arguments).reduce(function(sum, number) {
return sum + number * number;
}, 0));
@ -83,7 +91,7 @@ Ox.limit <f> Limits a number by a given mininum and maximum
> Ox.limit(-1, -2)
-2
@*/
Ox.limit = function(/*number[[, min], max]*/) {
export function limit(/*number[[, min], max]*/) {
var number = arguments[0],
min = arguments.length == 3 ? arguments[1] : -Infinity,
max = arguments[arguments.length - 1];
@ -98,7 +106,7 @@ Ox.log <f> Returns the logarithm of a given number to a given base
> Ox.log(Math.E)
1
@*/
Ox.log = function(number, base) {
export function log(number, base) {
return Math.log(number) / Math.log(base || Math.E);
};
@ -110,7 +118,7 @@ Ox.mod <f> Modulo function
> Ox.mod(-11, 10)
9
@*/
Ox.mod = function(number, by) {
export function mod(number, by) {
return (number % by + by) % by;
};
@ -120,7 +128,7 @@ Ox.rad <f> Takes degrees, returns radians
> Ox.rad(360)
2 * Math.PI
@*/
Ox.rad = function(deg) {
export function rad(deg) {
return deg * Math.PI / 180;
};
@ -136,7 +144,7 @@ Ox.random <f> Returns a random integer within a given range
> Ox.random(1, 2) == 1
true
@*/
Ox.random = function() {
export function random() {
var min = arguments.length == 2 ? arguments[0] : 0,
max = arguments.length ? Ox.last(arguments) : 2;
return min + Math.floor(Math.random() * (max - min));
@ -151,7 +159,7 @@ Ox.round <f> Rounds a number with a given number of decimals
> Ox.round(1 / 2)
1
@*/
Ox.round = function(number, decimals) {
export function round(number, decimals) {
var pow = Math.pow(10, decimals || 0);
return Math.round(number * pow) / pow;
};
@ -169,7 +177,7 @@ Ox.sign <f> Returns the sign of a number (-1, 0 or 1)
> Ox.sign(Infinity)
1
@*/
Ox.sign = function(x) {
export function sign(x) {
x = +x;
return x !== x || x === 0 ? x : x < 0 ? -1 : 1;
};
@ -180,7 +188,7 @@ Ox.sinh <f> Hyperbolic sine
> Ox.sinh(0)
0
@*/
Ox.sinh = function(x) {
export function sinh(x) {
return (Math.exp(x) - Math.exp(-x)) / 2;
};
@ -194,7 +202,7 @@ Ox.splitInt <f> Splits an integer into an array of integers
> Ox.splitInt(100, 6)
[16, 16, 17, 17, 17, 17]
@*/
Ox.splitInt = function(number, by) {
export function splitInt(number, by) {
var div = Math.floor(number / by),
mod = number % by;
return Ox.range(by).map(function(i) {
@ -208,7 +216,7 @@ Ox.tanh <f> Hyperbolic tangent
> Ox.tanh(0)
0
@*/
Ox.tanh = function(x) {
export function tanh(x) {
return (Math.exp(x) - Math.exp(-x)) / (Math.exp(x) + Math.exp(-x));
};
@ -217,6 +225,6 @@ Ox.trunc <f> Truncates a number
> Ox.trunc(-1.5)
-1
@*/
Ox.trunc = function(x) {
export function trunc(x) {
return ~~x;
};

View file

@ -1,5 +1,25 @@
'use strict';
import * as OxCore from './Core.js';
import * as OxFunction from './Function.js';
import * as OxConstants from './Constants.js';
import * as OxCollection from './Collection.js';
import * as OxMath from './Math.js';
import * as OxType from './Type.js';
import * as OxArray from './Array.js';
const Ox = {};
Object.assign(Ox,
OxCore,
OxFunction,
OxConstants,
OxCollection,
OxMath,
OxType,
OxArray,
);
/*@
Ox.extend <function> Extends an object with one or more other objects
> Ox.extend({a: 1, b: 1, c: 1}, {b: 2, c: 2}, {c: 3})
@ -9,10 +29,10 @@ Ox.extend <function> Extends an object with one or more other objects
> Ox.extend({a: 1}, 'b')
{a: 1, b: void 0}
@*/
Ox.extend = function(object) {
export function extend(object) {
var args = Ox.slice(arguments, 1);
if (!Ox.isObject(args[0])) {
args = [Ox.makeObject(args)];
args = [makeObject(args)];
}
Ox.forEach(args, function(arg) {
Ox.forEach(arg, function(value, key) {
@ -62,7 +82,7 @@ Ox.getset <f> Generic getter and setter function
> Ox.test.object.options({foo: "foo", bar: "bar"}).options()
{"key": "val", "foo": "foo", "bar": "bar"}
@*/
Ox.getset = function(object, args, callback, that) {
export function getset(object, args, callback, that) {
var object_ = Ox.clone(object), ret;
if (args.length == 0) {
// []
@ -72,7 +92,7 @@ Ox.getset = function(object, args, callback, that) {
ret = Ox.clone(object[args[0]]);
} else {
// [key, val] or [{key: val, ...}]
args = Ox.makeObject(args);
args = makeObject(args);
object = Ox.extend(object, args);
Ox.forEach(args, function(value, key) {
if (!object_ || !Ox.isEqual(object_[key], value)) {
@ -84,7 +104,7 @@ Ox.getset = function(object, args, callback, that) {
return ret;
};
Ox.hasOwn = function(object, value) {
export function hasOwn(object, value) {
return Object.prototype.hasOwnProperty.call(object, value);
};
@ -93,7 +113,7 @@ Ox.keyOf <f> Equivalent of [].indexOf for objects
> Ox.keyOf({a: 1, b: 2, c: 3}, 1)
'a'
@*/
Ox.keyOf = function(object, value) {
export function keyOf(object, value) {
var key;
Ox.forEach(object, function(v, k) {
if (v === value) {
@ -117,7 +137,7 @@ Ox.makeObject <f> Takes an array and returns an object
> (function() { return Ox.makeObject(arguments); }())
{}
@*/
Ox.makeObject = function(array) {
export function makeObject(array) {
var ret = {};
if (Ox.isObject(array[0])) {
// [{foo: 'bar'}]
@ -134,7 +154,7 @@ Ox.methods <f> Returns a sorted list of all method names of an object
> Ox.methods({a: [], b: false, f: function() {}, n: 0, o: {}, s: ''})
['f']
@*/
Ox.methods = function(object, includePrototype) {
export function methods(object, includePrototype) {
var key, keys;
if (includePrototype) {
keys = [];
@ -158,7 +178,7 @@ Ox.serialize <f> Parses an object into query parameters
> Ox.serialize({a: [1, 2], b: true, n: 1, o: {k: 'v'}, s: 'foo'}, true)
'a=[1,2]&b=true&n=1&o={"k":"v"}&s="foo"'
@*/
Ox.serialize = function(object, isJSON) {
export function serialize(object, isJSON) {
var ret = [];
Ox.forEach(object, function(value, key) {
var value;
@ -184,7 +204,7 @@ Ox.unserialize <f> Parses query parameters into an object
{a: [1, 2], b: true, n: 1.2, o: {k: 'v'}, s1: 'foo', s2: 'bar'}
@*/
Ox.unserialize = function(string, isJSON) {
export function unserialize(string, isJSON) {
var ret = {};
Ox.filter(string.split('&')).forEach(function(value) {
var array = value.split('=');
@ -208,7 +228,7 @@ Ox.zipObject <f> Takes a keys and a values array, returns a new object
> Ox.zipObject(['a', 'b'], [1, 2])
{a: 1, b: 2}
@*/
Ox.zipObject = function(keys, values) {
export function zipObject(keys, values) {
var object = {};
keys = Ox.makeArray(keys);
values = Ox.makeArray(values);

View file

@ -1,6 +1,6 @@
'use strict';
(function(window) {
export function loadPolyfill(window, Ox) {
var canDefineProperty = !!Object.defineProperty && (function() {
try {
@ -426,5 +426,4 @@
);
}
}
}(this));
}

View file

@ -1,3 +1,5 @@
'use strict';
/*@
Ox.escapeRegExp <f> Escapes a string for use in a regular expression
(str) -> <r> Escaped string
@ -8,6 +10,6 @@ Ox.escapeRegExp <f> Escapes a string for use in a regular expression
true
@*/
// see https://developer.mozilla.org/en/JavaScript/Guide/Regular_Expressions
Ox.escapeRegExp = function(string) {
export function escapeRegExp(string) {
return (string + '').replace(/([\/\\^$*+?.\-|(){}[\]])/g, '\\$1');
};

View file

@ -1,5 +1,25 @@
'use strict';
import * as OxArray from './Array.js';
import * as OxObject from './Object.js';
import * as OxConstants from './Constants.js';
import * as OxMath from './Math.js';
import * as OxString from './String.js';
import * as OxType from './Type.js';
import * as OxCollection from './Collection.js';
const Ox = {};
Object.assign(Ox,
OxArray,
OxObject,
OxConstants,
OxMath,
OxString,
OxType,
OxCollection,
);
/*@
Ox.get <f> Get a remote resource
(url, callback) -> <u> undefined
@ -10,7 +30,7 @@ Ox.get <f> Get a remote resource
code <n> Status code
text <s> Status text
@*/
Ox.get = function(url, callback) {
export function get(url, callback) {
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.onreadystatechange = function() {
@ -49,7 +69,7 @@ Ox.getAsync <f> Runs an asynchonous loader for an array of URLs
code <n> Error code (like `404`)
text <s> Error text (like `'Not Found'`)
@*/
Ox.getAsync = function(urls, get, callback) {
export function getAsync(urls, get, callback) {
urls = Ox.makeArray(urls);
var errors = {}, i = 0, n = urls.length, results = {};
function done() {
@ -76,7 +96,7 @@ Ox.getAsync = function(urls, get, callback) {
}
function getSerial() {
var url = urls.shift();
Ox.getAsync(url, get, function(result, error) {
getAsync(url, get, function(result, error) {
extend(results, result, url);
extend(errors, error, url);
urls.length ? getSerial() : done();
@ -85,14 +105,13 @@ Ox.getAsync = function(urls, get, callback) {
urls.some(Ox.isArray) ? getSerial() : getParallel();
};
(function() {
var cache = {},
var cache = {},
head = document.head
|| document.getElementsByTagName('head')[0]
|| document.documentElement;
function getFile(type, url, callback) {
function _getFile(type, url, callback) {
var element, tagValue, typeValue, urlKey;
if (!cache[url]) {
if (!type) {
@ -162,65 +181,63 @@ Ox.getAsync = function(urls, get, callback) {
}
!error && onLoad();
}
}
}
function getFiles(type, urls, callback) {
Ox.getAsync(urls, function(url, callback) {
getFile(type, url, callback);
function getFiles(type, urls, callback) {
getAsync(urls, function(url, callback) {
_getFile(type, url, callback);
}, callback);
}
}
/*@
Ox.getFile <f> Loads a file (image, script or stylesheet)
/*@
Ox.getFile <f> Loads a file (image, script or stylesheet)
(file, callback) -> <u> undefined
file <s|[s]> Local path or remote URL, or array of those, or array of such arrays
Multiple files in the same array will be processed simultaneously,
but multiple arrays of files will be processed in that order.
callback <f> Callback function
image <h> DOM element (if the file is an image)
@*/
Ox.getFile = function(url, callback) {
@*/
export function getFile(url, callback) {
getFiles(null, url, callback);
};
};
/*@
Ox.getImage <f> Loads an image
/*@
Ox.getImage <f> Loads an image
(file, callback) -> <u> undefined
file <s|[s]> Local path or remote URL, or array of those, or array of such arrays
Multiple files in the same array will be processed simultaneously,
but multiple arrays of files will be processed in that order.
callback <f> Callback function
image <h> DOM element
@*/
Ox.getImage = function(url, callback) {
@*/
export function getImage(url, callback) {
getFiles('image', url, callback);
};
};
/*@
Ox.getScript <f> Loads a script
/*@
Ox.getScript <f> Loads a script
(file, callback) -> <u> undefined
file <s|[s]> Local path or remote URL, or array of those, or array of such arrays
Multiple files in the same array will be processed simultaneously,
but multiple arrays of files will be processed in that order.
callback <f> Callback function
@*/
Ox.getScript = function(url, callback) {
@*/
export function getScript(url, callback) {
getFiles('script', url, callback);
};
};
/*@
Ox.getStylesheet <f> Loads a stylesheet
/*@
Ox.getStylesheet <f> Loads a stylesheet
(file, callback) -> <u> undefined
file <s|[s]> Local path or remote URL, or array of those, or array of such arrays
Multiple files in the same array will be processed simultaneously,
but multiple arrays of files will be processed in that order.
callback <f> Callback function
@*/
Ox.getStylesheet = function(url, callback) {
@*/
export function getStylesheet(url, callback) {
getFiles('stylesheet', url, callback);
};
}());
};
/*@
Ox.getJSON <f> Get and parse one or more remote JSON files
@ -234,10 +251,10 @@ Ox.getJSON <f> Get and parse one or more remote JSON files
code <n> Error code (like `404`)
text <s> Error text (like `'Not Found'`)
@*/
Ox.getJSON = function(url, callback, isJSONC) {
export function getJSON(url, callback, isJSONC) {
var urls = Ox.makeArray(url);
Ox.getAsync(urls, function(url, callback) {
Ox.get(url, function(data, error) {
getAsync(urls, function(url, callback) {
get(url, function(data, error) {
callback(JSON.parse(
isJSONC ? Ox.minify(data || '') : data
), error);
@ -258,7 +275,7 @@ Ox.getJSONC <f> Get and parse a remote JSONC file
code <n> Error code (like `404`)
text <s> Error text (like `'Not Found'`)
@*/
Ox.getJSONC = function(url, callback) {
export function getJSONC(url, callback) {
Ox.getJSON(url, callback, true);
};
@ -275,9 +292,9 @@ Ox.getJSONP <f> Get and parse one or more remote JSONP files
code <n> Error code (like `404`)
text <s> Error text (like `'Not Found'`)
@*/
Ox.getJSONP = function(url, callback) {
export function getJSONP(url, callback) {
var urls = Ox.makeArray(url);
Ox.getAsync(urls, function(url, callback) {
getAsync(urls, function(url, callback) {
var id = 'callback' + Ox.uid();
Ox.getJSONP[id] = function(data) {
delete Ox.getJSONP[id];
@ -301,7 +318,7 @@ Ox.post <f> post to a remote resource
code <n> Status code
text <s> Status text
@*/
Ox.post = function(url, data, callback) {
export function post(url, data, callback) {
var request = new XMLHttpRequest();
request.open('post', url, true);
request.onreadystatechange = function() {

View file

@ -1,9 +1,21 @@
'use strict';
import * as OxCore from './Core.js';
import * as OxBase from './Base.js';
import * as OxCollection from './Collection.js';
const Ox = {};
Object.assign(Ox,
OxCore,
OxBase,
OxCollection,
);
/*@
Ox.char <f> Alias for String.fromCharCode
@*/
Ox.char = String.fromCharCode;
export const char = String.fromCharCode;
/*@
Ox.clean <f> Remove leading, trailing and double whitespace from a string
@ -18,7 +30,7 @@ Ox.clean <f> Remove leading, trailing and double whitespace from a string
> Ox.clean(' foo\tbar ')
'foo bar'
@*/
Ox.clean = function(string) {
export function clean(string) {
return Ox.filter(Ox.map(string.split('\n'), function(string) {
return string.replace(/\s+/g, ' ').trim() || '';
})).join('\n');
@ -30,7 +42,7 @@ Ox.codePointAt <f> Returns the code point at a given index
> Ox.codePointAt('\uD83D\uDCA9', 0)
0x1F4A9
@*/
Ox.codePointAt = function(string, index) {
export function codePointAt(string, index) {
var first, length = string.length, ret, second;
if (index >= 0 && index < length) {
first = string.charCodeAt(index);
@ -55,7 +67,7 @@ Ox.endsWith <f> Tests if a string ends with a given substring
> Ox.endsWith('foobar', 'foo')
false
@*/
Ox.endsWith = function(string, substring) {
export function endsWith(string, substring) {
string = string.toString();
substring = substring.toString();
return string.slice(string.length - substring.length) == substring;
@ -69,7 +81,7 @@ Ox.fromCodePoint <f> Returns a string for one or more given code points
> Ox.fromCodePoint(0x1F4A9)
'\uD83D\uDCA9'
@*/
Ox.fromCodePoint = function() {
export function fromCodePoint() {
var ret = '';
Ox.forEach(arguments, function(number) {
if (number < 0 || number > 0x10FFFF || !Ox.isInt(number)) {
@ -99,7 +111,7 @@ Ox.isValidEmail <f> Tests if a string is a valid e-mail address
> Ox.isValidEmail('foo@bar..com')
false
@*/
Ox.isValidEmail = function(string) {
export function isValidEmail(string) {
return !!/^[0-9A-Z\.\+\-_]+@(?:[0-9A-Z\-]+\.)+[A-Z]{2,64}$/i.test(string);
};
@ -140,7 +152,7 @@ Ox.pad <f> Pad a string to a given length
> Ox.pad('foo', -1)
''
@*/
Ox.pad = function(string, position, length, padding) {
export function pad(string, position, length, padding) {
var hasPosition = Ox.isString(arguments[1]),
isNumber = Ox.isNumber(arguments[0]),
last = Ox.last(arguments);
@ -166,7 +178,7 @@ Ox.parseDuration <f> Takes a formatted duration, returns seconds
> Ox.parseDuration('1::')
3600
@*/
Ox.parseDuration = function(string) {
export function parseDuration(string) {
return string.split(':').reverse().slice(0, 4).reduce(function(p, c, i) {
return p + (parseFloat(c) || 0) * (i == 3 ? 86400 : Math.pow(60, i));
}, 0);
@ -187,7 +199,7 @@ Ox.parsePath <f> Returns the components of a path
> Ox.parsePath('.foo')
{extension: '', filename: '.foo', pathname: ''}
@*/
Ox.parsePath = function(string) {
export function parsePath(string) {
var matches = /^(.+\/)?(.+?(\..+)?)?$/.exec(string);
return {
pathname: matches[1] || '',
@ -206,7 +218,7 @@ Ox.parseSRT <f> Parses an srt subtitle file
> Ox.parseSRT('1\n01:02:00,000 --> 01:02:03,400\nHello World')
[{'in': 3720, out: 3723.4, text: 'Hello World'}]
@*/
Ox.parseSRT = function(string, fps) {
export function parseSRT(string, fps) {
return string.replace(/\r\n/g, '\n').trim().split('\n\n')
.map(function(block) {
var lines = block.split('\n'), points;
@ -264,10 +276,22 @@ Ox.parseURL <f> Takes a URL, returns its components
> Ox.parseURL('http://www.foo.com:8080/bar/index.html?a=0&b=1#c').search
'?a=0&b=1'
@*/
Ox.parseURL = (function() {
var a = document.createElement('a'),
keys = ['hash', 'host', 'hostname', 'origin',
'pathname', 'port', 'protocol', 'search'];
export const parseURL = (function() {
const keys = [
'hash', 'host', 'hostname', 'origin',
'pathname', 'port', 'protocol', 'search'
];
if (typeof document == 'undefined') {
return function(string) {
const a = new URL(string);
var ret = {};
keys.forEach(function(key) {
ret[key] = a[key];
});
return ret;
}
} else {
var a = document.createElement('a');
return function(string) {
var ret = {};
a.href = string;
@ -276,10 +300,11 @@ Ox.parseURL = (function() {
});
return ret;
};
}
}());
// FIXME: can we get rid of this?
Ox.parseUserAgent = function(userAgent) {
export function parseUserAgent(userAgent) {
var aliases = {
browser: {
'Firefox': /(Fennec|Firebird|Iceweasel|Minefield|Namoroka|Phoenix|SeaMonkey|Shiretoko)/
@ -440,7 +465,7 @@ Ox.repeat <f> Repeat a value multiple times
@*/
// FIXME: see https://github.com/paulmillr/es6-shim/blob/master/es6-shim.js
// for a faster version
Ox.repeat = function(value, times) {
export function repeat(value, times) {
var ret;
if (Ox.isArray(value)) {
ret = [];
@ -458,7 +483,7 @@ Ox.splice <f> `[].splice` for strings, returns a new string
> Ox.splice('12xxxxx89', 2, 5, 3, 4, 5, 6, 7)
'123456789'
@*/
Ox.splice = function(string, index, remove) {
export function splice(string, index, remove) {
var array = string.split('');
Array.prototype.splice.apply(array, Ox.slice(arguments, 1));
return array.join('');
@ -474,7 +499,7 @@ Ox.startsWith <f> Tests if a string ends with a given substring
> Ox.startsWith('foobar', 'bar')
false
@*/
Ox.startsWith = function(string, substring) {
export function startsWith(string, substring) {
string = string.toString();
substring = substring.toString();
return string.slice(0, substring.length) == substring;
@ -489,7 +514,7 @@ Ox.toCamelCase <f> Takes a string with '-', '/' or '_', returns a camelCase stri
> Ox.toCamelCase('foo_bar_baz')
'fooBarBaz'
@*/
Ox.toCamelCase = function(string) {
export function toCamelCase(string) {
return string.replace(/[\-\/_][a-z]/g, function(string) {
return string[1].toUpperCase();
});
@ -500,7 +525,7 @@ Ox.toDashes <f> Takes a camelCase string, returns a string with dashes
> Ox.toDashes('fooBarBaz')
'foo-bar-baz'
@*/
Ox.toDashes = function(string) {
export function toDashes(string) {
return string.replace(/[A-Z]/g, function(string) {
return '-' + string.toLowerCase();
});
@ -511,7 +536,7 @@ Ox.toSlashes <f> Takes a camelCase string, returns a string with slashes
> Ox.toSlashes('fooBarBaz')
'foo/bar/baz'
@*/
Ox.toSlashes = function(string) {
export function toSlashes(string) {
return string.replace(/[A-Z]/g, function(string) {
return '/' + string.toLowerCase();
});
@ -524,7 +549,7 @@ Ox.toTitleCase <f> Returns a string with capitalized words
> Ox.toTitleCase('Apple releases iPhone, IBM stock plummets')
'Apple Releases iPhone, IBM Stock Plummets'
@*/
Ox.toTitleCase = function(string) {
export function toTitleCase(string) {
return string.split(' ').map(function(value) {
var substring = value.slice(1),
lowercase = substring.toLowerCase();
@ -540,7 +565,7 @@ Ox.toUnderscores <f> Takes a camelCase string, returns string with underscores
> Ox.toUnderscores('fooBarBaz')
'foo_bar_baz'
@*/
Ox.toUnderscores = function(string) {
export function toUnderscores(string) {
return string.replace(/[A-Z]/g, function(string) {
return '_' + string.toLowerCase();
});
@ -562,7 +587,7 @@ Ox.truncate <f> Truncate a string to a given length
> Ox.truncate('anticonstitutionellement', 'center', 16, '...')
'anticon...lement'
@*/
Ox.truncate = function(string, position, length, padding) {
export function truncate(string, position, length, padding) {
var hasPosition = Ox.isString(arguments[1]), last = Ox.last(arguments);
position = hasPosition ? arguments[1] : 'right';
length = hasPosition ? arguments[2] : arguments[1];
@ -589,7 +614,7 @@ Ox.words <f> Splits a string into words, removing punctuation
> Ox.words('Let\'s "split" array-likes into key/value pairs--okay?')
['let\'s', 'split', 'array-likes', 'into', 'key', 'value', 'pairs', 'okay']
@*/
Ox.words = function(string) {
export function words(string) {
var array = string.toLowerCase().split(/\b/),
length = array.length,
startsWithWord = /\w/.test(array[0]);
@ -635,7 +660,7 @@ Ox.wordwrap <f> Wrap a string at word boundaries
> Ox.wordwrap('These are short words', 16, true)
'These are \nshort words'
@*/
Ox.wordwrap = function(string, length) {
export function wordwrap(string, length) {
var balanced, lines, max, newline, words;
string = String(string);
length = length || 80;

View file

@ -1,13 +1,27 @@
'use strict';
import * as OxObject from './Object.js';
import * as OxFunction from './Function.js';
import * as OxConstants from './Constants.js';
import * as OxMath from './Math.js';
const Ox = {};
Object.assign(Ox,
OxObject,
OxFunction,
OxConstants,
OxMath
);
/*@
Ox.checkType <f> Throws a TypeError if a value is not of a given type
(val, type) -> <u> undefined
val <*> Any value
type <s|[s]> Type, or array of types
@*/
Ox.checkType = function(value, type) {
if (!Ox.contains(Ox.makeArray(type), Ox.typeOf(value))) {
export function checkType(value, type) {
if (!Ox.contains(Ox.makeArray(type), typeOf(value))) {
throw new TypeError();
}
};
@ -19,8 +33,8 @@ Ox.isArguments <f> Tests if a value is an arguments "array"
> Ox.isArguments((function() { return arguments; }()))
true
@*/
Ox.isArguments = function(value) {
return Ox.typeOf(value) == 'arguments';
export function isArguments(value) {
return typeOf(value) == 'arguments';
};
/*@
@ -36,8 +50,8 @@ Ox.isArray <f> Tests if a value is an array
> Ox.isArray({0: 0, length: 1})
false
@*/
Ox.isArray = function(value) {
return Ox.typeOf(value) == 'array';
export function isArray(value) {
return typeOf(value) == 'array';
};
/*@
@ -47,8 +61,8 @@ Ox.isBoolean <f> Tests if a value is boolean
> Ox.isBoolean(false)
true
@*/
Ox.isBoolean = function(value) {
return Ox.typeOf(value) == 'boolean';
export function isBoolean(value) {
return typeOf(value) == 'boolean';
};
/*@
@ -58,8 +72,8 @@ Ox.isDate <f> Tests if a value is a date
> Ox.isDate(new Date())
true
@*/
Ox.isDate = function(value) {
return Ox.typeOf(value) == 'date';
export function isDate(value) {
return typeOf(value) == 'date';
};
/*@
@ -69,7 +83,7 @@ Ox.isElement <f> Tests if a value is a DOM element
> Ox.isElement(document.createElement('a'))
true
@*/
Ox.isElement = function(value) {
export function isElement(value) {
return Ox.endsWith(Ox.typeOf(value), 'element');
};
@ -96,7 +110,7 @@ Ox.isEmpty <f> Tests if a value is an empty array, object or string
> Ox.isEmpty()
false
@*/
Ox.isEmpty = function(value) {
export function isEmpty(value) {
return Ox.len(value) === 0;
};
@ -157,12 +171,12 @@ Ox.isEqual <function> Tests if two values are equal
> Ox.isEqual(void 0, void 0)
true
@*/
Ox.isEqual = function(a, b) {
var ret = false, type = Ox.typeOf(a);
export function isEqual(a, b) {
var ret = false, type = typeOf(a);
if (a === b) {
// 0 === -0, but not equal
ret = a !== 0 || 1 / a === 1 / b;
} else if (type == Ox.typeOf(b)) {
} else if (type == typeOf(b)) {
// NaN !== NaN, but equal
if (a == b || a !== a) {
ret = true;
@ -193,8 +207,8 @@ Ox.isError <f> Tests if a value is an error
> Ox.isError(new Error())
true
@*/
Ox.isError = function(value) {
return Ox.typeOf(value) == 'error';
export function isError(value) {
return typeOf(value) == 'error';
};
/*@
@ -206,8 +220,8 @@ Ox.isFunction <f> Tests if a value is a function
> Ox.isFunction(new RegExp())
false
@*/
Ox.isFunction = function(value) {
return Ox.typeOf(value) == 'function';
export function isFunction(value) {
return typeOf(value) == 'function';
};
/*@
@ -221,8 +235,8 @@ Ox.isInfinity <f> Tests if a value is positive or negative Infinity
> Ox.isInfinity(NaN)
false
@*/
Ox.isInfinity = function(value) {
return Ox.typeOf(value) == 'number' && !isFinite(value) && !Ox.isNaN(value);
export function isInfinity(value) {
return typeOf(value) == 'number' && !isFinite(value) && !Ox.isNaN(value);
};
/*@
@ -236,7 +250,7 @@ Ox.isInt <f> Tests if a value is an integer
> Ox.isInt(Infinity)
false
@*/
Ox.isInt = function(value) {
export function isInt(value) {
return isFinite(value) && value === Math.floor(value);
};
@ -247,7 +261,7 @@ Ox.isInvalidDate <f> Tests if a value is an invalid date
> Ox.isInvalidDate(new Date('foo'))
true
@*/
Ox.isInvalidDate = function(value) {
export function isInvalidDate(value) {
return Ox.isDate(value) && Ox.isNaN(value.getTime());
};
@ -258,7 +272,7 @@ Ox.isNaN <f> Tests if a value is `NaN`
> Ox.isNaN(NaN)
true
@*/
Ox.isNaN = function(value) {
export function isNaN(value) {
return value !== value;
};
@ -268,8 +282,8 @@ Ox.isNodeList <f> Tests if a value is a nodelist
> Ox.isNodeList(document.getElementsByTagName('a'))
true
@*/
Ox.isNodeList = function(value) {
return Ox.typeOf(value) == 'nodelist';
export function isNodeList(value) {
return typeOf(value) == 'nodelist';
};
/*@
@ -279,8 +293,8 @@ Ox.isNull <f> Tests if a value is `null`
> Ox.isNull(null)
true
@*/
Ox.isNull = function(value) {
return Ox.typeOf(value) == 'null';
export function isNull(value) {
return typeOf(value) == 'null';
};
/*@
@ -296,8 +310,8 @@ Ox.isNumber <f> Tests if a value is a number
> Ox.isNumber(NaN)
true
@*/
Ox.isNumber = function(value) {
return Ox.typeOf(value) == 'number';
export function isNumber(value) {
return typeOf(value) == 'number';
};
/*@
@ -315,8 +329,8 @@ Ox.isObject <f> Tests if a value is a an object
> Ox.isObject(/ /)
false
@*/
Ox.isObject = function(value) {
return Ox.typeOf(value) == 'object';
export function isObject(value) {
return typeOf(value) == 'object';
};
/*@
@ -338,9 +352,9 @@ Ox.isPrimitive <f> Tests if a value is a primitive
> Ox.isPrimitive({})
false
@*/
Ox.isPrimitive = function(value) {
export function isPrimitive(value) {
return Ox.contains(
['boolean', 'null', 'number', 'string', 'undefined'], Ox.typeOf(value)
['boolean', 'null', 'number', 'string', 'undefined'], typeOf(value)
);
};
@ -351,8 +365,8 @@ Ox.isRegExp <f> Tests if a value is a regular expression
> Ox.isRegExp(new RegExp())
true
@*/
Ox.isRegExp = function(value) {
return Ox.typeOf(value) == 'regexp';
export function isRegExp(value) {
return typeOf(value) == 'regexp';
};
/*@
@ -362,8 +376,8 @@ Ox.isString <f> Tests if a value is a string
> Ox.isString('')
true
@*/
Ox.isString = function(value) {
return Ox.typeOf(value) == 'string';
export function isString(value) {
return typeOf(value) == 'string';
};
/*@
@ -373,8 +387,8 @@ Ox.isUndefined <f> Tests if a value is undefined
> Ox.isUndefined()
true
@*/
Ox.isUndefined = function(value) {
return Ox.typeOf(value) == 'undefined';
export function isUndefined(value) {
return typeOf(value) == 'undefined';
};
/*@
@ -384,7 +398,7 @@ Ox.isValidDate <f> Tests if a value is a valid date
> Ox.isValidDate(new Date())
true
@*/
Ox.isValidDate = function(value) {
export function isValidDate(value) {
return Ox.isDate(value) && !Ox.isNaN(value.getTime());
};
@ -433,7 +447,7 @@ Ox.typeOf <f> Returns the type of a value
> Ox.typeOf(JSON)
'json'
@*/
Ox.typeOf = function(value) {
export function typeOf(value) {
return Object.prototype.toString.call(value).slice(8, -1).toLowerCase();
};
// Firefox 3.6 returns 'Object' for arguments,
@ -442,13 +456,13 @@ Ox.typeOf = function(value) {
// Mobile Safari returns 'DOMWindow' for null and undefined
// Firefox 30+ returns 'window' for window
if (
Ox.typeOf((function() { return arguments; }())) != 'arguments'
|| Ox.typeOf(document.getElementsByTagName('a')) != 'nodelist'
|| Ox.typeOf(null) != 'null'
|| Ox.typeOf(window) != 'global'
|| Ox.typeOf() != 'undefined'
typeOf((function() { return arguments; }())) != 'arguments'
|| (typeof document !== 'undefined' && typeOf(document.getElementsByTagName('a')) != 'nodelist')
|| typeof null != 'null'
|| typeof window != 'global'
|| typeOf() != 'undefined'
) {
Ox.typeOf = function(value) {
typeOf = function(value) {
var type = Object.prototype.toString.call(
value
).slice(8, -1).toLowerCase();
@ -456,7 +470,7 @@ if (
type = 'null';
} else if (value === void 0) {
type = 'undefined';
} else if (value === window) {
} else if (typeof window !== 'undefined' && value === window) {
type = 'global';
} else if (type == 'object' && typeof value.callee == 'function') {
type = 'arguments';

View file

@ -1,11 +1,35 @@
'use strict';
import * as OxCore from './Core.js';
import * as OxType from './Type.js';
import * as OxArray from './Array.js';
import * as OxObject from './Object.js';
import * as OxCollection from './Collection.js';
import * as OxFunction from './Function.js';
import * as OxConstants from './Constants.js';
import * as OxMath from './Math.js';
import * as OxString from './String.js';
const Ox = {};
Object.assign(Ox,
OxCore,
OxType,
OxArray,
OxObject,
OxFunction,
OxCollection,
OxConstants,
OxMath,
OxString,
);
/*@
Ox.getVideoFormat <f> Get supported video format
(formats) -> <a> List of supported formats
format <s> First supported format form list
@*/
Ox.getVideoFormat = function(formats) {
export function getVideoFormat(formats) {
var aliases = {
mp4: 'h264',
m4v: 'h264',

548
source/UI/index.js Normal file
View file

@ -0,0 +1,548 @@
'use strict';
import * as AudioAudioElement from './js/Audio/AudioElement.js';
import * as AudioAudioPlayer from './js/Audio/AudioPlayer.js';
import * as BarBar from './js/Bar/Bar.js';
import * as BarProgressbar from './js/Bar/Progressbar.js';
import * as BarResizebar from './js/Bar/Resizebar.js';
import * as BarTabbar from './js/Bar/Tabbar.js';
import * as CalendarCalendarEditor from './js/Calendar/CalendarEditor.js';
import * as CalendarCalendar from './js/Calendar/Calendar.js';
import * as CodeDocPage from './js/Code/DocPage.js';
import * as CodeDocPanel from './js/Code/DocPanel.js';
import * as CodeExamplePage from './js/Code/ExamplePage.js';
import * as CodeExamplePanel from './js/Code/ExamplePanel.js';
import * as CodeSourceViewer from './js/Code/SourceViewer.js';
import * as CodeSyntaxHighlighter from './js/Code/SyntaxHighlighter.js';
import * as CoreAPI from './js/Core/API.js';
import * as CoreApp from './js/Core/App.js';
import * as CoreClipboard from './js/Core/Clipboard.js';
import * as CoreContainer from './js/Core/Container.js';
import * as CoreCookies from './js/Core/Cookies.js';
import * as CoreElement from './js/Core/Element.js';
import * as CoreEvent from './js/Core/Event.js';
import * as CoreFocus from './js/Core/Focus.js';
import * as CoreFullscreen from './js/Core/Fullscreen.js';
import * as CoreGarbageCollection from './js/Core/GarbageCollection.js';
import * as CoreHistory from './js/Core/History.js';
import * as CoreLoadingIcon from './js/Core/LoadingIcon.js';
import * as CoreLoadingScreen from './js/Core/LoadingScreen.js';
import * as CoreRequest from './js/Core/Request.js';
import * as CoreTheme from './js/Core/Theme.js';
import * as CoreUI from './js/Core/UI.js';
import * as CoreURL from './js/Core/URL.js';
import * as FormArrayEditable from './js/Form/ArrayEditable.js';
import * as FormArrayInput from './js/Form/ArrayInput.js';
import * as FormButtonGroup from './js/Form/ButtonGroup.js';
import * as FormButton from './js/Form/Button.js';
import * as FormCheckboxGroup from './js/Form/CheckboxGroup.js';
import * as FormCheckbox from './js/Form/Checkbox.js';
import * as FormColorInput from './js/Form/ColorInput.js';
import * as FormColorPicker from './js/Form/ColorPicker.js';
import * as FormDateInput from './js/Form/DateInput.js';
import * as FormDateTimeInput from './js/Form/DateTimeInput.js';
import * as FormEditableContent from './js/Form/EditableContent.js';
import * as FormEditable from './js/Form/Editable.js';
import * as FormFileButton from './js/Form/FileButton.js';
import * as FormFileInput from './js/Form/FileInput.js';
import * as FormFilter from './js/Form/Filter.js';
import * as FormFormElementGroup from './js/Form/FormElementGroup.js';
import * as FormFormItem from './js/Form/FormItem.js';
import * as FormForm from './js/Form/Form.js';
import * as FormFormPanel from './js/Form/FormPanel.js';
import * as FormInputGroup from './js/Form/InputGroup.js';
import * as FormInput from './js/Form/Input.js';
import * as FormInsertHTMLDialog from './js/Form/InsertHTMLDialog.js';
import * as FormLabel from './js/Form/Label.js';
import * as FormObjectArrayInput from './js/Form/ObjectArrayInput.js';
import * as FormObjectInput from './js/Form/ObjectInput.js';
import * as FormOptionGroup from './js/Form/OptionGroup.js';
import * as FormPicker from './js/Form/Picker.js';
import * as FormPlaceInput from './js/Form/PlaceInput.js';
import * as FormPlacePicker from './js/Form/PlacePicker.js';
import * as FormRange from './js/Form/Range.js';
import * as FormSelectInput from './js/Form/SelectInput.js';
import * as FormSelect from './js/Form/Select.js';
import * as FormSpreadsheet from './js/Form/Spreadsheet.js';
import * as FormTimeInput from './js/Form/TimeInput.js';
import * as ImageImageElement from './js/Image/ImageElement.js';
import * as ImageImageViewer from './js/Image/ImageViewer.js';
import * as ListChart from './js/List/Chart.js';
import * as ListColumnList from './js/List/ColumnList.js';
import * as ListCustomList from './js/List/CustomList.js';
import * as ListIconItem from './js/List/IconItem.js';
import * as ListIconList from './js/List/IconList.js';
import * as ListInfoList from './js/List/InfoList.js';
import * as ListListItem from './js/List/ListItem.js';
import * as ListList from './js/List/List.js';
import * as ListSortList from './js/List/SortList.js';
import * as ListTableList from './js/List/TableList.js';
import * as ListTreeList from './js/List/TreeList.js';
import * as MapMapEditor from './js/Map/MapEditor.js';
import * as MapMapImage from './js/Map/MapImage.js';
import * as MapMap from './js/Map/Map.js';
import * as MapMapMarkerImage from './js/Map/MapMarkerImage.js';
import * as MapMapMarker from './js/Map/MapMarker.js';
import * as MapMapPlace from './js/Map/MapPlace.js';
import * as MapMapRectangle from './js/Map/MapRectangle.js';
import * as MapMapRectangleMarker from './js/Map/MapRectangleMarker.js';
import * as MenuMainMenu from './js/Menu/MainMenu.js';
import * as MenuMenuButton from './js/Menu/MenuButton.js';
import * as MenuMenuItem from './js/Menu/MenuItem.js';
import * as MenuMenu from './js/Menu/Menu.js';
import * as PanelCollapsePanel from './js/Panel/CollapsePanel.js';
import * as PanelSlidePanel from './js/Panel/SlidePanel.js';
import * as PanelSplitPanel from './js/Panel/SplitPanel.js';
import * as PanelTabPanel from './js/Panel/TabPanel.js';
import * as VideoAnnotationFolder from './js/Video/AnnotationFolder.js';
import * as VideoAnnotationPanel from './js/Video/AnnotationPanel.js';
import * as VideoBlockVideoTimeline from './js/Video/BlockVideoTimeline.js';
import * as VideoClipPanel from './js/Video/ClipPanel.js';
import * as VideoLargeVideoTimeline from './js/Video/LargeVideoTimeline.js';
import * as VideoSmallVideoTimelineImage from './js/Video/SmallVideoTimelineImage.js';
import * as VideoSmallVideoTimeline from './js/Video/SmallVideoTimeline.js';
import * as VideoVideoAnnotationPanel from './js/Video/VideoAnnotationPanel.js';
import * as VideoVideoEditPanel from './js/Video/VideoEditPanel.js';
import * as VideoVideoElement from './js/Video/VideoElement.js';
import * as VideoVideoPlayer from './js/Video/VideoPlayer.js';
import * as VideoVideoPlayerMenu from './js/Video/VideoPlayerMenu.js';
import * as VideoVideoPlayerPanel from './js/Video/VideoPlayerPanel.js';
import * as VideoVideoPreview from './js/Video/VideoPreview.js';
import * as VideoVideoTimelinePanel from './js/Video/VideoTimelinePanel.js';
import * as VideoVideoTimelinePlayer from './js/Video/VideoTimelinePlayer.js';
import * as VideoYouTubeElement from './js/Video/YouTubeElement.js';
import * as WindowDialog from './js/Window/Dialog.js';
import * as WindowLayer from './js/Window/Layer.js';
import * as WindowSortDialog from './js/Window/SortDialog.js';
import * as WindowTooltip from './js/Window/Tooltip.js';
const UI = {}
Object.assign(UI,
AudioAudioElement,
AudioAudioPlayer,
BarBar,
BarProgressbar,
BarResizebar,
BarTabbar,
CalendarCalendarEditor,
CalendarCalendar,
CodeDocPage,
CodeDocPanel,
CodeExamplePage,
CodeExamplePanel,
CodeSourceViewer,
CodeSyntaxHighlighter,
CoreAPI,
CoreApp,
CoreClipboard,
CoreContainer,
CoreCookies,
CoreElement,
CoreEvent,
CoreFocus,
CoreFullscreen,
CoreGarbageCollection,
CoreHistory,
CoreLoadingIcon,
CoreLoadingScreen,
CoreRequest,
CoreTheme,
CoreUI,
CoreURL,
FormArrayEditable,
FormArrayInput,
FormButtonGroup,
FormButton,
FormCheckboxGroup,
FormCheckbox,
FormColorInput,
FormColorPicker,
FormDateInput,
FormDateTimeInput,
FormEditableContent,
FormEditable,
FormFileButton,
FormFileInput,
FormFilter,
FormFormElementGroup,
FormFormItem,
FormForm,
FormFormPanel,
FormInputGroup,
FormInput,
FormInsertHTMLDialog,
FormLabel,
FormObjectArrayInput,
FormObjectInput,
FormOptionGroup,
FormPicker,
FormPlaceInput,
FormPlacePicker,
FormRange,
FormSelectInput,
FormSelect,
FormSpreadsheet,
FormTimeInput,
ImageImageElement,
ImageImageViewer,
ListChart,
ListColumnList,
ListCustomList,
ListIconItem,
ListIconList,
ListInfoList,
ListListItem,
ListList,
ListSortList,
ListTableList,
ListTreeList,
MapMapEditor,
MapMapImage,
MapMap,
MapMapMarkerImage,
MapMapMarker,
MapMapPlace,
MapMapRectangle,
MapMapRectangleMarker,
MenuMainMenu,
MenuMenuButton,
MenuMenuItem,
MenuMenu,
PanelCollapsePanel,
PanelSlidePanel,
PanelSplitPanel,
PanelTabPanel,
VideoAnnotationFolder,
VideoAnnotationPanel,
VideoBlockVideoTimeline,
VideoClipPanel,
VideoLargeVideoTimeline,
VideoSmallVideoTimelineImage,
VideoSmallVideoTimeline,
VideoVideoAnnotationPanel,
VideoVideoEditPanel,
VideoVideoElement,
VideoVideoPlayer,
VideoVideoPlayerMenu,
VideoVideoPlayerPanel,
VideoVideoPreview,
VideoVideoTimelinePanel,
VideoVideoTimelinePlayer,
VideoYouTubeElement,
WindowDialog,
WindowLayer,
WindowSortDialog,
WindowTooltip,
);
export default UI;
export { UI };
if (typeof window !== 'undefined') {
window.Ox.UI = UI
Ox.load.UI = function(options, callback) {
options = Ox.extend({
hideScreen: true,
loadCSS: true,
loadThemes: true,
showScreen: false,
theme: 'oxlight'
}, options);
var browsers = [
{
name: 'Chrome Frame',
url: 'http://www.google.com/chromeframe/'
},
{
name: 'Chrome',
regexp: /Chrome\/(\d+)\./,
url: 'http://www.google.com/chrome/',
version: 10
},
{
name: 'Firefox',
regexp: /Firefox\/(\d+)\./,
url: 'http://www.mozilla.org/firefox/',
version: 4
},
{
name: 'Safari',
regexp: /Version\/(\d+).*? Safari/,
url: 'http://www.apple.com/safari/',
version: 5
},
{
name: 'WebKit',
regexp: /AppleWebKit\/(\d+)\./,
version: 534
},
{
name: 'Googlebot',
regexp: /Googlebot\/(\d+)\./,
version: 2
},
{
name: 'YandexBot',
regexp: /YandexBot\/(\d+)\./,
version: 3
},
{
name: 'YandexMobileBot',
regexp: /YandexMobileBot\/(\d+)\./,
version: 3
},
{
name: 'Internet Explorer',
url: 'http://windows.microsoft.com/en-US/internet-explorer/products/ie/home',
version: 9
}
],
browserSupported = false,
isInternetExplorer = /MSIE/.test(navigator.userAgent);
browsers.forEach(function(browser) {
var match = browser.regexp && browser.regexp.exec(navigator.userAgent);
if (match && match[1] >= browser.version) {
browserSupported = true;
}
});
Ox.UI = {};
Ox.UI.LoadingScreen = (function() {
var $body = Ox.$('body'),
$screen = Ox.$('<div>')
.addClass('OxLoadingScreen')
.css({
position: 'absolute',
left: 0,
top: 0,
right: 0,
bottom: 0,
padding: '4px',
background: 'rgb(' + (
options.theme == 'oxlight' ? '240, 240, 240'
: options.theme == 'oxmedium' ? '144, 144, 144'
: '16, 16, 16'
) + ')',
opacity: 1,
zIndex: 1000
}),
css = {
position: 'absolute',
left: 0,
top: 0,
right: 0,
bottom: 0,
margin: 'auto',
MozUserSelect: 'none',
WebkitUserSelect: 'none'
},
loadingInterval,
$icon,
deg = 0;
browserSupported ? showIcon() : showWarning();
function showIcon() {
/*
// SVG transform performs worse than CSS transform
var src = Ox.PATH + 'UI/themes/' + options.theme + '/svg/symbolLoadingAnimated.svg'
Ox.getFile(src, function() {
Ox.$('<img>')
.attr({
src: src
})
.css(Ox.extend({
width: '32px',
height: '32px'
}, css))
.on({
mousedown: function(e) {
e.preventDefault();
}
})
.appendTo(div);
});
*/
var src = Ox.PATH + 'UI/themes/' + options.theme + '/svg/symbolLoading.svg'
Ox.getFile(src, function() {
$icon = Ox.$('<img>')
.attr({
src: src
})
.css(Ox.extend({
width: '32px',
height: '32px'
}, css))
.on({
mousedown: function(e) {
e.preventDefault()
}
})
.appendTo($screen);
});
}
function showWarning() {
var counter = 0;
browsers = browsers.filter(function(browser) {
return browser.url;
});
isInternetExplorer ? browsers.pop() : browsers.shift();
browsers.forEach(function(browser) {
browser.src = Ox.PATH + 'UI/png/browser' + browser.name.replace(' ', '') + '128.png';
Ox.getFile(browser.src, function() {
++counter == browsers.length && showIcons();
});
});
function showIcons() {
var $box = Ox.$('<div>')
.css(Ox.extend({
width: (browsers.length * 72) + 'px',
height: '72px'
}, css))
.appendTo($screen);
browsers.forEach(function(browser, i) {
Ox.$('<a>')
.attr({
href: browser.url,
title: (
browser.name == 'Chrome Frame'
? Ox._('Install') : Ox._('Download')
) + ' ' + browser.name
})
.css({
position: 'absolute',
left: (i * 72) + 'px',
width: '72px',
height: '72px'
})
.append(
Ox.$('<img>')
.attr({
src: browser.src
})
.css(Ox.extend({
width: '64px',
height: '64px',
border: 0,
cursor: 'pointer'
}, css))
.on({
mousedown: function(e) {
e.preventDefault();
}
})
)
.appendTo($box);
});
}
}
return {
hide: function() {
$('.OxLoadingScreen').animate({
opacity: browserSupported ? 0 : 0.9
}, 1000, function() {
if (browserSupported) {
clearInterval(loadingInterval);
loadingInterval = null;
$screen.remove();
} else {
$screen.on({
click: function() {
$screen.remove();
}
});
}
});
},
show: function() {
if (!loadingInterval) {
loadingInterval = setInterval(function() {
if ($icon) {
deg = (deg + 30) % 360;
$icon.css({
MozTransform: 'rotate(' + deg + 'deg)',
OTransform: 'rotate(' + deg + 'deg)',
WebkitTransform: 'rotate(' + deg + 'deg)',
transform: 'rotate(' + deg + 'deg)'
});
}
}, 83);
}
$screen.appendTo($body);
}
};
}());
Ox.documentReady(function() {
Ox.$('body').addClass('OxTheme' + Ox.toTitleCase(options.theme));
options.showScreen && Ox.UI.LoadingScreen.show();
});
loadUI();
function loadUI() {
var path = Ox.PATH + 'UI/jquery/jquery.js?' + Ox.VERSION;
Ox.getFile(path, function() {
path = Ox.PATH + 'UI/json/UI.json?' + Ox.VERSION;
Ox.getJSON(path, function(data) {
var counter = 0, length;
if (!options.loadCSS) {
data.files = data.files.filter(function(file) {
return !Ox.endsWith(file, '.css');
});
}
if (!options.loadThemes) {
data.files = data.files.filter(function(file) {
return !Ox.contains(file, '/themes/');
});
}
length = data.files.length;
Ox.UI.IMAGES = data.images;
Ox.UI.THEMES = {};
data.files.forEach(function(file) {
path = Ox.PATH + file + '?' + Ox.VERSION;
if (/\.jsonc$/.test(file)) {
Ox.getJSONC(path, function(data) {
var theme = /\/themes\/(\w+)\/json\//.exec(file)[1];
Ox.UI.THEMES[theme] = data;
++counter == length && initUI();
});
} else {
Ox.getFile(path, function() {
++counter == length && initUI();
});
}
});
});
});
}
function initUI() {
Ox.documentReady(function() {
// fixme: is this the right place to do this?
$.browser.mozilla && Ox.$document.on('dragstart', function() {
return false;
});
if (options.showScreen && options.hideScreen) {
Ox.UI.LoadingScreen.hide();
}
callback(browserSupported);
});
}
};
}