Compare commits

..

1 commit

Author SHA1 Message Date
j
299a08b6a3 WIP: try to convert to ES modules 2026-02-09 18:59:12 +01:00
29 changed files with 3003 additions and 2014 deletions

View file

@ -4,7 +4,8 @@
<title>OxJS - A JavaScript Library for Web Applications</title> <title>OxJS - A JavaScript Library for Web Applications</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<link rel="stylesheet" type="text/css" href="index.css"/> <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> <script type="text/javascript" src="index.js"></script>
</head> </head>
<body></body> <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'; '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 <f> Turns an array into a list API
`Ox.api` takes an array and returns a function that allows you to run `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 > Ox.test.apiResults[9].data
{items: [{name: 'John Cale'}, {name: 'Brian Eno'}]} {items: [{name: 'John Cale'}, {name: 'Brian Eno'}]}
@*/ @*/
Ox.api = function(items, options) { export function api(items, options) {
options = options || {}; options = options || {};
@ -442,7 +456,7 @@ Ox.compact <f> Removes `null` or `undefined` values from an array
> Ox.compact([null,,1,,2,,3]) > Ox.compact([null,,1,,2,,3])
[1, 2, 3] [1, 2, 3]
@*/ @*/
Ox.compact = function(array) { export function compact(array) {
return array.filter(function(value) { return array.filter(function(value) {
return value != null; 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) > Ox.find(['Bar', 'Barfoo', 'Foo', 'Foobar'], 'foo', true)
['Foo', 'Foobar'] ['Foo', 'Foobar']
@*/ @*/
Ox.find = function(array, string, leading) { export function find(array, string, leading) {
var matches = [[], []]; var matches = [[], []];
string = string.toLowerCase(); string = string.toLowerCase();
array.forEach(function(value) { array.forEach(function(value) {
@ -480,7 +494,7 @@ Ox.flatten <f> Flattens an array
> Ox.flatten([1, [2, [3], 2], 1]) > Ox.flatten([1, [2, [3], 2], 1])
[1, 2, 3, 2, 1] [1, 2, 3, 2, 1]
@*/ @*/
Ox.flatten = function(array) { export function flatten(array) {
var ret = []; var ret = [];
array.forEach(function(value) { array.forEach(function(value) {
if (Ox.isArray(value)) { if (Ox.isArray(value)) {
@ -493,7 +507,7 @@ Ox.flatten = function(array) {
}; };
// FIXME: add docs and tests // FIXME: add docs and tests
Ox.getIndex = function(array, key, value) { export function getIndex(array, key, value) {
return Ox.indexOf(array, function(obj) { return Ox.indexOf(array, function(obj) {
return obj[key] === value; 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') > Ox.getIndexById([{id: 'foo', str: 'Foo'}, {id: 'bar', str: 'Bar'}], 'baz')
-1 -1
@*/ @*/
Ox.getIndexById = function(array, id) { export function getIndexById(array, id) {
return Ox.getIndex(array, 'id', id); return getIndex(array, 'id', id);
}; };
// FIXME: add docs and tests // FIXME: add docs and tests
Ox.getObject = function(array, key, value) { export function getObject(array, key, value) {
var index = Ox.getIndex(array, key, value); var index = getIndex(array, key, value);
return index > -1 ? array[index] : null; 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') > Ox.getObjectById([{id: 'foo', str: 'Foo'}, {id: 'bar', str: 'Bar'}], 'baz')
null null
@*/ @*/
Ox.getObjectById = function(array, id) { export function getObjectById(array, id) {
return Ox.getObject(array, 'id', id); return getObject(array, 'id', id);
}; };
/* /*
Ox.indexOf = function(arr) { export function indexOf(arr) {
// indexOf for primitives, test for function, deep equal for others // 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') > Ox.last('123')
'3' '3'
@*/ @*/
Ox.last = function(array, value) { export function last(array, value) {
var ret; var ret;
if (arguments.length == 1) { if (arguments.length == 1) {
ret = array[array.length - 1]; ret = array[array.length - 1];
@ -576,7 +590,7 @@ Ox.makeArray <f> Wraps any non-array in an array.
['foo'] ['foo']
@*/ @*/
// FIXME: rename to toArray // FIXME: rename to toArray
Ox.makeArray = function(value) { export function makeArray(value) {
var ret, type = Ox.typeOf(value); var ret, type = Ox.typeOf(value);
if (type == 'arguments' || type == 'nodelist') { if (type == 'arguments' || type == 'nodelist') {
ret = Ox.slice(value); 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) > Ox.nextValue([], 1, 1)
void 0 void 0
@*/ @*/
Ox.nextValue = function(array, value, direction) { export function nextValue(array, value, direction) {
var found = false, nextValue; var found = false, nextValue;
direction = direction || 1; direction = direction || 1;
direction == -1 && array.reverse(); direction == -1 && array.reverse();
@ -641,7 +655,7 @@ Ox.range <f> Python-style range
> Ox.range(-1, -2, -0.5) > Ox.range(-1, -2, -0.5)
[-1, -1.5] [-1, -1.5]
@*/ @*/
Ox.range = function() { export function range() {
var array = []; var array = [];
Ox.loop.apply(null, Ox.slice(arguments).concat(function(index) { Ox.loop.apply(null, Ox.slice(arguments).concat(function(index) {
array.push(index); array.push(index);
@ -768,7 +782,7 @@ Ox.unique <f> Removes duplicate values from an array
> Ox.unique('foo') > Ox.unique('foo')
'fo' 'fo'
@*/ @*/
Ox.unique = function(array) { export function unique(array) {
return Ox.filter(array, function(value, index) { return Ox.filter(array, function(value, index) {
return array.indexOf(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]) > Ox.zip([0, 1, 2], [3, 4, 5])
[[0, 3], [1, 4], [2, 5]] [[0, 3], [1, 4], [2, 5]]
@*/ @*/
Ox.zip = function() { export function zip() {
var args = arguments.length == 1 ? arguments[0] : Ox.slice(arguments), var args = arguments.length == 1 ? arguments[0] : Ox.slice(arguments),
array = []; array = [];
args[0].forEach(function(value, index) { args[0].forEach(function(value, index) {

View file

@ -1,8 +1,19 @@
'use strict'; '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), var type = Ox.typeOf(collection),
results = type == 'object' ? {} : []; results = type == 'object' ? {} : [];
callback = Ox.last(arguments); callback = Ox.last(arguments);
@ -15,9 +26,9 @@
}, that, function() { }, that, function() {
callback(type == 'string' ? results.join('') : results); callback(type == 'string' ? results.join('') : results);
}); });
} }
Ox.asyncMap = function(array, iterator, that, callback) { export function asyncMap(array, iterator, that, callback) {
array = Ox.makeArray(array); array = Ox.makeArray(array);
callback = Ox.last(arguments); callback = Ox.last(arguments);
that = arguments.length == 4 ? that : null; that = arguments.length == 4 ? that : null;
@ -28,10 +39,10 @@
} else { } else {
Ox.parallelMap(array, iterator, callback); 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 (col, iterator[, that], callback[, ms]) -> <u> undefined
collection <a|o|s> Collection collection <a|o|s> Collection
iterator <f> Iterator function iterator <f> Iterator function
@ -41,8 +52,8 @@
that <o> The iterator's `this` binding that <o> The iterator's `this` binding
callback <f> Callback function callback <f> Callback function
ms <n> Number of milliseconds after which to insert a `setTimeout` call 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), var i = 0, keys, last = Ox.last(arguments),
n, time, type = Ox.typeOf(collection); n, time, type = Ox.typeOf(collection);
callback = Ox.isFunction(last) ? last : arguments[arguments.length - 2]; callback = Ox.isFunction(last) ? last : arguments[arguments.length - 2];
@ -81,10 +92,10 @@
callback(); 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, iterator[, that], callback[, ms]) -> <u> undefined
collection <a|o|s> Collection collection <a|o|s> Collection
iterator <f> Iterator function iterator <f> Iterator function
@ -106,8 +117,8 @@
</script> </script>
> Ox.nonblockingMap(Ox.range(100000), Ox.identity, function(r) { Ox.test(r.length, 100000); }) > Ox.nonblockingMap(Ox.range(100000), Ox.identity, function(r) { Ox.test(r.length, 100000); })
undefined undefined
@*/ @*/
Ox.nonblockingMap = function(collection, iterator, that, callback, ms) { export function nonblockingMap(collection, iterator, that, callback, ms) {
var last = Ox.last(arguments), var last = Ox.last(arguments),
type = Ox.typeOf(collection), type = Ox.typeOf(collection),
results = type == 'object' ? {} : []; results = type == 'object' ? {} : [];
@ -120,10 +131,10 @@
}, function() { }, function() {
callback(type == 'string' ? results.join('') : results); callback(type == 'string' ? results.join('') : results);
}, ms); }, 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, iterator[, that], callback) -> <u> undefined
collection <a|o|s> Collection collection <a|o|s> Collection
iterator <f> Iterator function iterator <f> Iterator function
@ -144,8 +155,8 @@
</script> </script>
> Ox.parallelForEach(Ox.range(10), Ox.test.pfeIterator, function() { Ox.test(Ox.test.pfeNumber, 5); }) > Ox.parallelForEach(Ox.range(10), Ox.test.pfeIterator, function() { Ox.test(Ox.test.pfeNumber, 5); })
undefined undefined
@*/ @*/
Ox.parallelForEach = function(collection, iterator, that, callback) { export function parallelForEach(collection, iterator, that, callback) {
var i = 0, n, type = Ox.typeOf(collection); var i = 0, n, type = Ox.typeOf(collection);
callback = callback || (arguments.length == 3 ? arguments[2] : Ox.noop); callback = callback || (arguments.length == 3 ? arguments[2] : Ox.noop);
collection = type == 'array' || type == 'object' collection = type == 'array' || type == 'object'
@ -157,10 +168,10 @@
++i == n && callback(); ++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, iterator[, that], callback) -> <u> undefined
collection <a|o|s> Collection collection <a|o|s> Collection
iterator <f> Iterator function iterator <f> Iterator function
@ -190,13 +201,13 @@
</script> </script>
> Ox.parallelMap(Ox.range(10), Ox.test.pmIterator, function(r) { Ox.test(Ox.sum(r), 0); }) > Ox.parallelMap(Ox.range(10), Ox.test.pmIterator, function(r) { Ox.test(Ox.sum(r), 0); })
undefined undefined
@*/ @*/
Ox.parallelMap = function() { export function parallelMap() {
asyncMap.apply(null, [Ox.parallelForEach].concat(Ox.slice(arguments))); 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, iterator[, that], callback) -> <u> undefined
collection <a|o|s> Collection collection <a|o|s> Collection
iterator <f> Iterator function iterator <f> Iterator function
@ -217,8 +228,8 @@
</script> </script>
> Ox.serialForEach(Ox.range(10), Ox.test.sfeIterator, function() { Ox.test(Ox.test.sfeNumber, 5); }) > Ox.serialForEach(Ox.range(10), Ox.test.sfeIterator, function() { Ox.test(Ox.test.sfeNumber, 5); })
undefined undefined
@*/ @*/
Ox.serialForEach = function(collection, iterator, that, callback) { export function serialForEach(collection, iterator, that, callback) {
var i = 0, keys, n, type = Ox.typeOf(collection); var i = 0, keys, n, type = Ox.typeOf(collection);
callback = callback || (arguments.length == 3 ? arguments[2] : Ox.noop); callback = callback || (arguments.length == 3 ? arguments[2] : Ox.noop);
collection = type == 'array' || type == 'object' collection = type == 'array' || type == 'object'
@ -245,10 +256,10 @@
callback(); callback();
} }
} }
}; };
/*@ /*@
Ox.serialMap <f> Serial `map` with asynchronous iterator Ox.serialMap <f> Serial `map` with asynchronous iterator
(collection, iterator[, that], callback) -> <u> undefined (collection, iterator[, that], callback) -> <u> undefined
collection <a|o|s> Collection collection <a|o|s> Collection
iterator <f> Iterator function iterator <f> Iterator function
@ -278,10 +289,9 @@
</script> </script>
> Ox.serialMap(Ox.range(10), Ox.test.smIterator, function(r) { Ox.test(Ox.sum(r), 0); }) > Ox.serialMap(Ox.range(10), Ox.test.smIterator, function(r) { Ox.test(Ox.sum(r), 0); })
undefined undefined
@*/ @*/
Ox.serialMap = function(collection, iterator, that, callback) { export function serialMap(collection, iterator, that, callback) {
asyncMap.apply(null, [Ox.serialForEach].concat(Ox.slice(arguments))); internalAsyncMap.apply(null, [Ox.serialForEach].concat(Ox.slice(arguments)));
}; };
// FIXME: The above test with 10000 iterations blows the stack // 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'; '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 Ox.avg <f> Returns the average of an array's values, or an object's properties
(collection) -> <n> Average value (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') > Ox.avg('avg is 0.1')
0.1 0.1
@*/ @*/
Ox.avg = function(collection) { export function avg(collection) {
return Ox.sum(collection) / Ox.len(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]; }()) > (function() { var a = [[0, 1]], b = Ox.clone(a, true); a[0][0] = null; return b[0]; }())
[0, 1] [0, 1]
@*/ @*/
Ox.clone = function(collection, deep) { export function clone(collection, deep) {
var ret, type = Ox.typeOf(collection); var ret, type = Ox.typeOf(collection);
if (type != 'array' && type != 'object') { if (type != 'array' && type != 'object') {
ret = collection; ret = collection;
} else if (deep) { } else if (deep) {
ret = type == 'array' ? [] : {}; ret = type == 'array' ? [] : {};
Ox.forEach(collection, function(value, key) { forEach(collection, function(value, key) {
type = Ox.typeOf(value); type = Ox.typeOf(value);
ret[key] = type == 'array' || type == 'object' ret[key] = type == 'array' || type == 'object'
? Ox.clone(value, true) : value; ? Ox.clone(value, true) : value;
@ -59,7 +76,7 @@ Ox.contains <f> Tests if a collection contains a value
> Ox.contains('foobar', 'bar') > Ox.contains('foobar', 'bar')
true true
@*/ @*/
Ox.contains = function(collection, value) { export function contains(collection, value) {
var type = Ox.typeOf(collection); var type = Ox.typeOf(collection);
return ( return (
type == 'nodelist' || type == 'object' type == 'nodelist' || type == 'object'
@ -84,9 +101,9 @@ Ox.count <f> Counts the occurences of values in a collection
> Ox.count('foo', 'x') > Ox.count('foo', 'x')
0 0
@*/ @*/
Ox.count = function(collection, value) { export function count(collection, value) {
var count = {}; var count = {};
Ox.forEach(collection, function(value) { forEach(collection, function(value) {
count[value] = (count[value] || 0) + 1; count[value] = (count[value] || 0) + 1;
}); });
return value ? count[value] || 0 : count; 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]) > Ox.every([true, true, true])
true true
@*/ @*/
Ox.every = function(collection, iterator, that) { export function every(collection, iterator, that) {
iterator = iterator || Ox.identity; 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); 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 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' }); > Ox.forEach({a: 'f', b: 'o', c: 'o'}, function(v, k) { return v != 'o' });
1 1
@*/ @*/
Ox.forEach = function(collection, iterator, that) { export function forEach(collection, iterator, that) {
var i = 0, key, type = Ox.typeOf(collection); var i = 0, key, type = Ox.typeOf(collection);
if (type == 'object' || type == 'storage') { if (type == 'object' || type == 'storage') {
for (key in collection) { for (key in collection) {
@ -197,25 +185,6 @@ Ox.forEach = function(collection, iterator, that) {
return i; 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 <f> Returns all indices of collection elements that pass a test
> Ox.indicesOf([1, 2, 3], function(val) { return val % 2 == 1; }) > 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([1, 2, 3], function(val) { return val == 0; })
[] []
@*/ @*/
Ox.indicesOf = function(collection, test) { export function indicesOf(collection, test) {
var ret = []; var ret = [];
Ox.forEach(collection, function(value, index) { forEach(collection, function(value, index) {
test(value) && ret.push(index); test(value) && ret.push(index);
}); });
return ret; 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) {}) > Ox.len(function(a, b, c) {})
undefined undefined
@*/ @*/
Ox.len = function(collection) { export function len(collection) {
var ret, type = Ox.typeOf(collection); var ret, type = Ox.typeOf(collection);
if ( if (
type == 'arguments' || type == 'array' 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(v, i) { return i; })
[,] [,]
@*/ @*/
Ox.map = function(collection, iterator, that) { export function map(collection, iterator, that) {
var ret, type = Ox.typeOf(collection); var ret, type = Ox.typeOf(collection);
if (type == 'object' || type == 'storage') { if (type == 'object' || type == 'storage') {
ret = {}; ret = {};
Ox.forEach(collection, function(value, key) { forEach(collection, function(value, key) {
ret[key] = iterator.call(that, value, key, collection); ret[key] = iterator.call(that, value, key, collection);
}); });
} else { } else {
@ -309,7 +278,7 @@ Ox.max <f> Returns the maximum value of a collection
> Ox.max([]) > Ox.max([])
-Infinity -Infinity
@*/ @*/
Ox.max = function(collection) { export function max(collection) {
var ret, values = Ox.values(collection); var ret, values = Ox.values(collection);
if (values.length < Ox.STACK_LENGTH) { if (values.length < Ox.STACK_LENGTH) {
ret = Math.max.apply(null, values); ret = Math.max.apply(null, values);
@ -332,7 +301,7 @@ Ox.min <f> Returns the minimum value of a collection
> Ox.min([]) > Ox.min([])
Infinity Infinity
@*/ @*/
Ox.min = function(collection) { export function min(collection) {
var ret, values = Ox.values(collection); var ret, values = Ox.values(collection);
if (values.length < Ox.STACK_LENGTH) { if (values.length < Ox.STACK_LENGTH) {
ret = Math.min.apply(null, values); 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]; }) > Ox.numberOf('foo', function(v, k, c) { return v == c[k - 1]; })
1 1
@*/ @*/
Ox.numberOf = function(collection, test) { export function numberOf(collection, test) {
return Ox.len(Ox.filter(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 > Ox.test.collection
[['a', 'c'], {a: 0, c: 2}] [['a', 'c'], {a: 0, c: 2}]
@*/ @*/
Ox.remove = function(collection, element) { export function remove(collection, element) {
var ret, key; var ret, key;
if (Ox.isArray(collection)) { if (Ox.isArray(collection)) {
key = collection.indexOf(element); key = collection.indexOf(element);
@ -405,7 +374,7 @@ Ox.reverse <f> Reverses an array or string
> Ox.reverse('foobar') > Ox.reverse('foobar')
'raboof' 'raboof'
@*/ @*/
Ox.reverse = function(collection) { export function reverse(collection) {
return Ox.isArray(collection) return Ox.isArray(collection)
? Ox.clone(collection).reverse() ? Ox.clone(collection).reverse()
: collection.toString().split('').reverse().join(''); : 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('') > Ox.shuffle('123').split('').sort().join('')
'123' '123'
@*/ @*/
Ox.shuffle = function(collection) { export function shuffle(collection) {
var keys, ret, type = Ox.typeOf(collection), values; var keys, ret, type = Ox.typeOf(collection), values;
if (type == 'object' || type == 'storage') { if (type == 'object' || type == 'storage') {
keys = Object.keys(collection); keys = Object.keys(collection);
@ -443,57 +412,6 @@ Ox.shuffle = function(collection) {
return ret; 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 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 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]) > Ox.some([false, null, 0, '', void 0])
false false
@*/ @*/
Ox.some = function(collection, iterator, that) { export function some(collection, iterator, that) {
iterator = iterator || Ox.identity; 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); 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') > Ox.sum('08', -2, 'foo')
6 6
@*/ @*/
Ox.sum = function(collection) { export function sum(collection) {
var ret = 0; var ret = 0;
collection = arguments.length > 1 ? Ox.slice(arguments) : collection; collection = arguments.length > 1 ? Ox.slice(arguments) : collection;
Ox.forEach(collection, function(value) { forEach(collection, function(value) {
value = +value; value = +value;
ret += isFinite(value) ? value : 0; ret += isFinite(value) ? value : 0;
}); });
@ -541,7 +459,7 @@ Ox.sum = function(collection) {
/* FIXME: do we need this kind of zip functionality? /* FIXME: do we need this kind of zip functionality?
Ox.arrayToObject = function(array, key) { export function arrayToObject(array, key) {
var ret = {}; var ret = {};
array.forEach(function(v) { array.forEach(function(v) {
ret[v[key]] = v; ret[v[key]] = v;
@ -549,9 +467,9 @@ Ox.arrayToObject = function(array, key) {
return ret; return ret;
}; };
Ox.objectToArray = function(object, key) { export function objectToArray(object, key) {
var ret = []; var ret = [];
Ox.forEach(object, function(v, k) { forEach(object, function(v, k) {
ret.push(Ox.extend(v, key, k)); ret.push(Ox.extend(v, key, k));
}); });
return ret; return ret;
@ -574,13 +492,13 @@ Ox.values <f> Returns the values of a collection
> Ox.values([1,,3]) > Ox.values([1,,3])
[1,,3] [1,,3]
@*/ @*/
Ox.values = function(collection) { export function values(collection) {
var ret, type = Ox.typeOf(collection); var ret, type = Ox.typeOf(collection);
if (type == 'array' || type == 'nodelist') { if (type == 'array' || type == 'nodelist') {
ret = Ox.slice(collection); ret = Ox.slice(collection);
} else if (type == 'object' || type == 'storage') { } else if (type == 'object' || type == 'storage') {
ret = []; ret = [];
Ox.forEach(collection, function(value) { forEach(collection, function(value) {
ret.push(value); ret.push(value);
}); });
} else if (type == 'string') { } else if (type == 'string') {
@ -613,9 +531,9 @@ Ox.walk <f> Iterates over a nested data structure
> Ox.test.array > Ox.test.array
[['a'], ['b', 'c'], ['b', 'd']] [['a'], ['b', 'c'], ['b', 'd']]
@*/ @*/
Ox.walk = function(collection, iterator, that, keys) { export function walk(collection, iterator, that, keys) {
keys = keys || []; keys = keys || [];
Ox.forEach(collection, function(value, key) { forEach(collection, function(value, key) {
var keys_ = keys.concat(key); var keys_ = keys.concat(key);
iterator.call(that, value, keys_, collection); iterator.call(that, value, keys_, collection);
Ox.walk(collection[key], iterator, that, keys_); Ox.walk(collection[key], iterator, that, keys_);

View file

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

View file

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

View file

@ -2,15 +2,23 @@
'use strict'; 'use strict';
/*@ import * as OxType from './Type.js';
Ox <f> The `Ox` object import * as OxCollection from './Collection.js';
See `Ox.wrap` for details. import * as OxObject from './Object.js';
(value) -> <o> wrapped value import * as OxDOM from './DOM.js';
value <*> Any value import * as OxString from './String.js';
@*/ import * as OxRequest from './Request.js';
this.Ox = function(value) {
return Ox.wrap(value); const Ox = {};
};
Object.assign(Ox,
OxType,
OxCollection,
OxObject,
OxDOM,
OxString,
OxRequest,
);
/*@ /*@
Ox.load <f> Loads OxJS and, optionally, one or more modules 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 callback <f> Callback function
success <b> If true, all modules have been loaded successfully success <b> If true, all modules have been loaded successfully
@*/ @*/
Ox.load = function() { export function load() {
var callback = arguments[arguments.length - 1], var callback = arguments[arguments.length - 1],
length, loaded = 0, localeFiles = [], modules = {}, succeeded = 0, length, loaded = 0, localeFiles = [], modules = {}, succeeded = 0,
type = Ox.typeOf(arguments[0]); type = Ox.typeOf(arguments[0]);
@ -76,10 +84,10 @@ Ox.load = function() {
if (!length) { if (!length) {
callback(true); callback(true);
} else { } else {
Ox.forEach(modules, function(options, module) { Ox.forEach(modules, async function(options, module) {
Ox.getFile( console.log("load module!", module, options)
Ox.PATH + module + '/' + module + '.js?' + Ox.VERSION, // Ox.PATH + module + '/index.js?' + Ox.VERSION,
function() { const obj = await import('../../' + module + '/index.js?' + Ox.VERSION);
Ox.load[module](options, function(success) { Ox.load[module](options, function(success) {
succeeded += success; succeeded += success;
if (++loaded == length) { 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.test.localStorage.delete('foo')()
{} {}
@*/ @*/
Ox.localStorage = function(namespace) { export function localStorage(namespace) {
var localStorage; var localStorage;
try { try {
// this will fail if third party cookies/storage is not allowed // 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 <f> Logging module
@*/ @*/
Ox.Log = (function() { Ox.Log = (function() {
var storage = Ox.localStorage('Ox'), var storage = localStorage('Ox'),
log = storage('log') || {filter: [], filterEnabled: true}, log = storage('log') || {filter: [], filterEnabled: true},
that = function() { that = function() {
var ret; var ret;
@ -239,7 +245,7 @@ Ox.loop <f> For-loop, functional-style
> Ox.loop(0, 3, 2, function() {}) > Ox.loop(0, 3, 2, function() {})
4 4
@*/ @*/
Ox.loop = function() { export function loop() {
var length = arguments.length, var length = arguments.length,
start = length > 2 ? arguments[0] : 0, start = length > 2 ? arguments[0] : 0,
stop = arguments[length > 2 ? 1 : 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(' ') > Ox.print('foo', 'bar').split(' ').slice(1).join(' ')
'foo bar' 'foo bar'
@*/ @*/
Ox.print = function() { export function print() {
var args = Ox.slice(arguments), date = new Date(); var args = Ox.slice(arguments), date = new Date();
args.unshift( args.unshift(
date.toString().split(' ')[4] + '.' + (+date).toString().slice(-3) 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 Ox.trace <f> Prints its arguments to the console, followed by a stack trace
(arg, ...) -> <s> String (arg, ...) -> <s> String
@*/ @*/
Ox.trace = function() { export function trace() {
var args = Ox.slice(arguments); var args = Ox.slice(arguments);
try { try {
throw new Error(); throw new Error();
@ -296,12 +302,10 @@ Ox.uid <f> Returns a unique id
> Ox.uid() != Ox.uid() > Ox.uid() != Ox.uid()
true true
@*/ @*/
Ox.uid = (function() { var _uid = 0;
var uid = 0; export function uid() {
return function() { return ++_uid;
return ++uid; }
};
}());
/*@ /*@
Ox.wrap <f> Wraps a value so that one can directly call any Ox function on it 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() > Ox.wrap('foobar').value()
'foobar' 'foobar'
@*/ @*/
Ox.wrap = function(value, chained) { export function wrap(value, chained) {
// somewhat inspired by underscore.js // somewhat inspired by underscore.js
var wrapper = { var wrapper = {
chain: function() { chain: function() {
@ -341,3 +345,55 @@ Ox.wrap = function(value, chained) {
}); });
return wrapper; 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'; '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 Ox.$ <f> Generic HTML element, mimics jQuery
value <s|h|w|?> tagname, selector, html element, `window`, or `document` 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() > Ox.$('<input>').val('red').val()
'red' 'red'
@*/ @*/
Ox.$ = Ox.element = function $(value) { export function element(value) {
var elements = Ox.isArray(value) ? value // array of elements var elements = Ox.isArray(value) ? value // array of elements
: Ox.isNodeList(value) ? Ox.slice(value) // nodelist : 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 Ox.canvas <function> Generic canvas object
Returns an object with the properties: `canvas`, `context`, `data` and 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 height <n> Height in px
image <e> Image object image <e> Image object
@*/ @*/
Ox.canvas = function() { export function canvas() {
var c = {}, isImage = arguments.length == 1, var c = {}, isImage = arguments.length == 1,
image = isImage ? arguments[0] : { image = isImage ? arguments[0] : {
width: arguments[0], height: arguments[1] width: arguments[0], height: arguments[1]
@ -821,13 +845,24 @@ Ox.canvas = function() {
return c; return c;
}; };
var callbacks = [];
/*@ /*@
Ox.documentReady <function> Calls a callback function once the DOM is ready Ox.documentReady <function> Calls a callback function once the DOM is ready
(callback) -> <b> If true, the document was ready (callback) -> <b> If true, the document was ready
callback <f> Callback function callback <f> Callback function
@*/ @*/
Ox.documentReady = (function() { export function documentReady(callback) {
var callbacks = []; if (document.readyState == 'complete') {
callback();
return true;
} else {
callbacks.push(callback);
return false;
}
}
if (typeof document !== 'undefined') {
document.onreadystatechange = window.onload = function() { document.onreadystatechange = window.onload = function() {
if (document.readyState == 'complete') { if (document.readyState == 'complete') {
callbacks.forEach(function(callback) { callbacks.forEach(function(callback) {
@ -836,13 +871,4 @@ Ox.documentReady = (function() {
document.onreadystatechange = window.onload = null; 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'; '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 //@ Ox.getDate <f> Get the day of a date, optionally UTC
// see Ox.setSeconds for source code // 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" "Monday, December 27, 1999"
@*/ @*/
// fixme: why is this Monday first? shouldn't it then be "getDateInISOWeek"?? // 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); date = Ox.makeDate(date);
var sourceWeekday = Ox.getISODay(date, utc), var sourceWeekday = Ox.getISODay(date, utc),
targetWeekday = Ox.isNumber(weekday) ? weekday 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")) > Ox.getDayOfTheYear(new Date("12/31/2004"))
366 366
@*/ @*/
Ox.getDayOfTheYear = function(date, utc) { export function getDayOfTheYear(date, utc) {
date = Ox.makeDate(date); date = Ox.makeDate(date);
var month = Ox.getMonth(date, utc), var month = Ox.getMonth(date, utc),
year = Ox.getFullYear(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") > Ox.getDaysInMonth(new Date('01/01/2004'), "February")
29 29
@*/ @*/
Ox.getDaysInMonth = function(year, month) { export function getDaysInMonth(year, month) {
year = Ox.makeYear(year); year = Ox.makeYear(year);
month = Ox.isNumber(month) ? month month = Ox.isNumber(month) ? month
: Ox.indexOf(Ox.MONTHS, function(v) { : 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')) > Ox.getDaysInYear(new Date('01/01/2004'))
366 366
@*/ @*/
Ox.getDaysInYear = function(year, utc) { export function getDaysInYear(year, utc) {
return 365 + Ox.isLeapYear(Ox.makeYear(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')) > Ox.getFirstDayOfTheYear(new Date('01/01/2000'))
6 6
@*/ @*/
Ox.getFirstDayOfTheYear = function(date, utc) { export function getFirstDayOfTheYear(date, utc) {
date = Ox.makeDate(date); date = Ox.makeDate(date);
date = Ox.setMonth(date, 0, utc); date = Ox.setMonth(date, 0, utc);
date = Ox.setDate(date, 1, 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')) > Ox.getISODate(new Date('01/01/2000'))
'2000-01-01T00:00:00Z' '2000-01-01T00:00:00Z'
@*/ @*/
Ox.getISODate = function(date, utc) { export function getISODate(date, utc) {
return Ox.formatDate(Ox.makeDate(date), '%FT%TZ', 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')) > Ox.getISODay(new Date('01/03/2000'))
1 1
@*/ @*/
Ox.getISODay = function(date, utc) { export function getISODay(date, utc) {
return Ox.getDay(Ox.makeDate(date), utc) || 7; return Ox.getDay(Ox.makeDate(date), utc) || 7;
}; };
@ -143,7 +155,7 @@ Ox.getISOWeek <f> Get the ISO week of a given date
1 1
@*/ @*/
Ox.getISOWeek = function(date, utc) { export function getISOWeek(date, utc) {
date = Ox.makeDate(date); date = Ox.makeDate(date);
// set date to Thursday of the same week // set date to Thursday of the same week
return Math.floor((Ox.getDayOfTheYear(Ox.setDate( return Math.floor((Ox.getDayOfTheYear(Ox.setDate(
@ -162,7 +174,7 @@ Ox.getISOYear <f> Get the ISO year of a given date
2000 2000
@*/ @*/
Ox.getISOYear = function(date, utc) { export function getISOYear(date, utc) {
date = Ox.makeDate(date); date = Ox.makeDate(date);
// set date to Thursday of the same week // set date to Thursday of the same week
return Ox.getFullYear(Ox.setDate( return Ox.getFullYear(Ox.setDate(
@ -180,7 +192,7 @@ Ox.getISOYear = function(date, utc) {
// see Ox.setSeconds for source code // see Ox.setSeconds for source code
//@ Ox.getTime <f> Alias for `+new Date()` //@ Ox.getTime <f> Alias for `+new Date()`
Ox.getTime = function(utc) { export function getTime(utc) {
return +new Date() - (utc ? Ox.getTimezoneOffset() : 0); 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]) -> <n> Offset in milliseconds
date <d|u> Return offset at this date (if undefined, return current offset) 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; 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 > Ox.getTimezoneOffsetString(new Date('01/01/2000')).length
5 5
@*/ @*/
Ox.getTimezoneOffsetString = function(date) { export function getTimezoneOffsetString(date) {
var offset = Ox.makeDate(date).getTimezoneOffset(); var offset = Ox.makeDate(date).getTimezoneOffset();
return (offset <= 0 ? '+' : '-') return (offset <= 0 ? '+' : '-')
+ Ox.pad(Math.floor(Math.abs(offset) / 60), 2) + 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')) > Ox.getWeek(new Date('01/03/2000'))
1 1
@*/ @*/
Ox.getWeek = function(date, utc) { export function getWeek(date, utc) {
date = Ox.makeDate(date); date = Ox.makeDate(date);
return Math.floor((Ox.getDayOfTheYear(date, utc) return Math.floor((Ox.getDayOfTheYear(date, utc)
+ Ox.getFirstDayOfTheYear(date, utc) - 1) / 7); + 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')) > Ox.isLeapYear(new Date('01/01/2004'))
true true
@*/ @*/
Ox.isLeapYear = function(year, utc) { export function isLeapYear(year, utc) {
year = Ox.makeYear(year, utc); year = Ox.makeYear(year, utc);
return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0); 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') > Ox.formatDate(Ox.makeDate(Ox.parseDate('-50')), '%Y')
'-50' '-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 // 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 (Ox.isString(date) && Ox.isInvalidDate(new Date(date))) {
if (/^\d{4}$/.test(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') > Ox.makeYear('1970')
1970 1970
@*/ @*/
Ox.makeYear = function(date, utc) { export function makeYear(date, utc) {
return Ox.isDate(date) ? Ox.getFullYear(date, utc) : parseInt(date, 10); 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() > Ox.parseDate('50', true).getUTCFullYear()
50 50
@*/ @*/
Ox.parseDate = function(string, utc) { export function parseDate(string, utc) {
var date, var date,
defaults = [, 1, 1, 0, 0, 0, 0], defaults = [, 1, 1, 0, 0, 0, 0],
values = /(-?\d+)-?(\d+)?-?(\d+)? ?(\d+)?:?(\d+)?:?(\d+)?\.?(\d+)?/ 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 = [ var dates = [
Ox.parseDate(start, utc), Ox.parseDate(start, utc),
Ox.parseDate(end, utc) Ox.parseDate(end, utc)

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,9 +1,21 @@
'use strict'; '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 <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 // Needs to go via string to work for files > 2GB
var hash = fromString(file.size.toString()); 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 <f> Calculates SHA1 hash of the given string
@*/ @*/
Ox.SHA1 = function(msg) { export function SHA1(msg) {
function rotate_left(n,s) { function rotate_left(n,s) {
var t4 = ( n<<s ) | (n>>>(32-s)); var t4 = ( n<<s ) | (n>>>(32-s));

View file

@ -1,5 +1,21 @@
'use strict'; '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 Ox.doc <f> Generates documentation for annotated JavaScript
(source) -> <[o]> Array of doc objects (source) -> <[o]> Array of doc objects

View file

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

View file

@ -1,12 +1,20 @@
'use strict'; 'use strict';
import * as OxArray from './Array.js';
const Ox = {};
Object.assign(Ox,
OxArray,
);
/*@ /*@
Ox.acosh <f> Inverse hyperbolic cosine Ox.acosh <f> Inverse hyperbolic cosine
Missing from `Math`. Missing from `Math`.
> Ox.acosh(1) > Ox.acosh(1)
0 0
@*/ @*/
Ox.acosh = function(x) { export function acosh(x) {
return Math.log(x + Math.sqrt(x * x - 1)); return Math.log(x + Math.sqrt(x * x - 1));
}; };
@ -16,7 +24,7 @@ Ox.asinh <f> Inverse hyperbolic sine
> Ox.asinh(0) > Ox.asinh(0)
0 0
@*/ @*/
Ox.asinh = function(x) { export function asinh(x) {
return Math.log(x + Math.sqrt(x * x + 1)); return Math.log(x + Math.sqrt(x * x + 1));
}; };
@ -26,7 +34,7 @@ Ox.atanh <f> Inverse hyperbolic tangent
> Ox.atanh(0) > Ox.atanh(0)
0 0
@*/ @*/
Ox.atanh = function(x) { export function atanh(x) {
return 0.5 * Math.log((1 + x) / (1 - x)); return 0.5 * Math.log((1 + x) / (1 - x));
}; };
@ -36,7 +44,7 @@ Ox.cosh <f> Hyperbolic cosine
> Ox.cosh(0) > Ox.cosh(0)
1 1
@*/ @*/
Ox.cosh = function(x) { export function cosh(x) {
return (Math.exp(x) + Math.exp(-x)) / 2; return (Math.exp(x) + Math.exp(-x)) / 2;
}; };
@ -46,7 +54,7 @@ Ox.deg <f> Takes radians, returns degrees
> Ox.deg(2 * Math.PI) > Ox.deg(2 * Math.PI)
360 360
@*/ @*/
Ox.deg = function(rad) { export function deg(rad) {
return rad * 180 / Math.PI; 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) > Ox.hypot(1, 1, 1)
Math.sqrt(3) Math.sqrt(3)
@*/ @*/
Ox.hypot = function() { export function hypot() {
return Math.sqrt(Ox.slice(arguments).reduce(function(sum, number) { return Math.sqrt(Ox.slice(arguments).reduce(function(sum, number) {
return sum + number * number; return sum + number * number;
}, 0)); }, 0));
@ -83,7 +91,7 @@ Ox.limit <f> Limits a number by a given mininum and maximum
> Ox.limit(-1, -2) > Ox.limit(-1, -2)
-2 -2
@*/ @*/
Ox.limit = function(/*number[[, min], max]*/) { export function limit(/*number[[, min], max]*/) {
var number = arguments[0], var number = arguments[0],
min = arguments.length == 3 ? arguments[1] : -Infinity, min = arguments.length == 3 ? arguments[1] : -Infinity,
max = arguments[arguments.length - 1]; 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) > Ox.log(Math.E)
1 1
@*/ @*/
Ox.log = function(number, base) { export function log(number, base) {
return Math.log(number) / Math.log(base || Math.E); return Math.log(number) / Math.log(base || Math.E);
}; };
@ -110,7 +118,7 @@ Ox.mod <f> Modulo function
> Ox.mod(-11, 10) > Ox.mod(-11, 10)
9 9
@*/ @*/
Ox.mod = function(number, by) { export function mod(number, by) {
return (number % by + by) % by; return (number % by + by) % by;
}; };
@ -120,7 +128,7 @@ Ox.rad <f> Takes degrees, returns radians
> Ox.rad(360) > Ox.rad(360)
2 * Math.PI 2 * Math.PI
@*/ @*/
Ox.rad = function(deg) { export function rad(deg) {
return deg * Math.PI / 180; 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 > Ox.random(1, 2) == 1
true true
@*/ @*/
Ox.random = function() { export function random() {
var min = arguments.length == 2 ? arguments[0] : 0, var min = arguments.length == 2 ? arguments[0] : 0,
max = arguments.length ? Ox.last(arguments) : 2; max = arguments.length ? Ox.last(arguments) : 2;
return min + Math.floor(Math.random() * (max - min)); 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) > Ox.round(1 / 2)
1 1
@*/ @*/
Ox.round = function(number, decimals) { export function round(number, decimals) {
var pow = Math.pow(10, decimals || 0); var pow = Math.pow(10, decimals || 0);
return Math.round(number * pow) / pow; 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) > Ox.sign(Infinity)
1 1
@*/ @*/
Ox.sign = function(x) { export function sign(x) {
x = +x; x = +x;
return x !== x || x === 0 ? x : x < 0 ? -1 : 1; return x !== x || x === 0 ? x : x < 0 ? -1 : 1;
}; };
@ -180,7 +188,7 @@ Ox.sinh <f> Hyperbolic sine
> Ox.sinh(0) > Ox.sinh(0)
0 0
@*/ @*/
Ox.sinh = function(x) { export function sinh(x) {
return (Math.exp(x) - Math.exp(-x)) / 2; 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) > Ox.splitInt(100, 6)
[16, 16, 17, 17, 17, 17] [16, 16, 17, 17, 17, 17]
@*/ @*/
Ox.splitInt = function(number, by) { export function splitInt(number, by) {
var div = Math.floor(number / by), var div = Math.floor(number / by),
mod = number % by; mod = number % by;
return Ox.range(by).map(function(i) { return Ox.range(by).map(function(i) {
@ -208,7 +216,7 @@ Ox.tanh <f> Hyperbolic tangent
> Ox.tanh(0) > Ox.tanh(0)
0 0
@*/ @*/
Ox.tanh = function(x) { export function tanh(x) {
return (Math.exp(x) - Math.exp(-x)) / (Math.exp(x) + Math.exp(-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) > Ox.trunc(-1.5)
-1 -1
@*/ @*/
Ox.trunc = function(x) { export function trunc(x) {
return ~~x; return ~~x;
}; };

View file

@ -1,5 +1,25 @@
'use strict'; '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 <function> Extends an object with one or more other objects
> Ox.extend({a: 1, b: 1, c: 1}, {b: 2, c: 2}, {c: 3}) > 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') > Ox.extend({a: 1}, 'b')
{a: 1, b: void 0} {a: 1, b: void 0}
@*/ @*/
Ox.extend = function(object) { export function extend(object) {
var args = Ox.slice(arguments, 1); var args = Ox.slice(arguments, 1);
if (!Ox.isObject(args[0])) { if (!Ox.isObject(args[0])) {
args = [Ox.makeObject(args)]; args = [makeObject(args)];
} }
Ox.forEach(args, function(arg) { Ox.forEach(args, function(arg) {
Ox.forEach(arg, function(value, key) { 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() > Ox.test.object.options({foo: "foo", bar: "bar"}).options()
{"key": "val", "foo": "foo", "bar": "bar"} {"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; var object_ = Ox.clone(object), ret;
if (args.length == 0) { if (args.length == 0) {
// [] // []
@ -72,7 +92,7 @@ Ox.getset = function(object, args, callback, that) {
ret = Ox.clone(object[args[0]]); ret = Ox.clone(object[args[0]]);
} else { } else {
// [key, val] or [{key: val, ...}] // [key, val] or [{key: val, ...}]
args = Ox.makeObject(args); args = makeObject(args);
object = Ox.extend(object, args); object = Ox.extend(object, args);
Ox.forEach(args, function(value, key) { Ox.forEach(args, function(value, key) {
if (!object_ || !Ox.isEqual(object_[key], value)) { if (!object_ || !Ox.isEqual(object_[key], value)) {
@ -84,7 +104,7 @@ Ox.getset = function(object, args, callback, that) {
return ret; return ret;
}; };
Ox.hasOwn = function(object, value) { export function hasOwn(object, value) {
return Object.prototype.hasOwnProperty.call(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) > Ox.keyOf({a: 1, b: 2, c: 3}, 1)
'a' 'a'
@*/ @*/
Ox.keyOf = function(object, value) { export function keyOf(object, value) {
var key; var key;
Ox.forEach(object, function(v, k) { Ox.forEach(object, function(v, k) {
if (v === value) { if (v === value) {
@ -117,7 +137,7 @@ Ox.makeObject <f> Takes an array and returns an object
> (function() { return Ox.makeObject(arguments); }()) > (function() { return Ox.makeObject(arguments); }())
{} {}
@*/ @*/
Ox.makeObject = function(array) { export function makeObject(array) {
var ret = {}; var ret = {};
if (Ox.isObject(array[0])) { if (Ox.isObject(array[0])) {
// [{foo: 'bar'}] // [{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: ''}) > Ox.methods({a: [], b: false, f: function() {}, n: 0, o: {}, s: ''})
['f'] ['f']
@*/ @*/
Ox.methods = function(object, includePrototype) { export function methods(object, includePrototype) {
var key, keys; var key, keys;
if (includePrototype) { if (includePrototype) {
keys = []; 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) > 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"' 'a=[1,2]&b=true&n=1&o={"k":"v"}&s="foo"'
@*/ @*/
Ox.serialize = function(object, isJSON) { export function serialize(object, isJSON) {
var ret = []; var ret = [];
Ox.forEach(object, function(value, key) { Ox.forEach(object, function(value, key) {
var value; 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'} {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 = {}; var ret = {};
Ox.filter(string.split('&')).forEach(function(value) { Ox.filter(string.split('&')).forEach(function(value) {
var array = value.split('='); 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]) > Ox.zipObject(['a', 'b'], [1, 2])
{a: 1, b: 2} {a: 1, b: 2}
@*/ @*/
Ox.zipObject = function(keys, values) { export function zipObject(keys, values) {
var object = {}; var object = {};
keys = Ox.makeArray(keys); keys = Ox.makeArray(keys);
values = Ox.makeArray(values); values = Ox.makeArray(values);

View file

@ -1,6 +1,6 @@
'use strict'; 'use strict';
(function(window) { export function loadPolyfill(window, Ox) {
var canDefineProperty = !!Object.defineProperty && (function() { var canDefineProperty = !!Object.defineProperty && (function() {
try { 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 Ox.escapeRegExp <f> Escapes a string for use in a regular expression
(str) -> <r> Escaped string (str) -> <r> Escaped string
@ -8,6 +10,6 @@ Ox.escapeRegExp <f> Escapes a string for use in a regular expression
true true
@*/ @*/
// see https://developer.mozilla.org/en/JavaScript/Guide/Regular_Expressions // see https://developer.mozilla.org/en/JavaScript/Guide/Regular_Expressions
Ox.escapeRegExp = function(string) { export function escapeRegExp(string) {
return (string + '').replace(/([\/\\^$*+?.\-|(){}[\]])/g, '\\$1'); return (string + '').replace(/([\/\\^$*+?.\-|(){}[\]])/g, '\\$1');
}; };

View file

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

View file

@ -1,9 +1,21 @@
'use strict'; '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 <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 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 ') > Ox.clean(' foo\tbar ')
'foo bar' 'foo bar'
@*/ @*/
Ox.clean = function(string) { export function clean(string) {
return Ox.filter(Ox.map(string.split('\n'), function(string) { return Ox.filter(Ox.map(string.split('\n'), function(string) {
return string.replace(/\s+/g, ' ').trim() || ''; return string.replace(/\s+/g, ' ').trim() || '';
})).join('\n'); })).join('\n');
@ -30,7 +42,7 @@ Ox.codePointAt <f> Returns the code point at a given index
> Ox.codePointAt('\uD83D\uDCA9', 0) > Ox.codePointAt('\uD83D\uDCA9', 0)
0x1F4A9 0x1F4A9
@*/ @*/
Ox.codePointAt = function(string, index) { export function codePointAt(string, index) {
var first, length = string.length, ret, second; var first, length = string.length, ret, second;
if (index >= 0 && index < length) { if (index >= 0 && index < length) {
first = string.charCodeAt(index); first = string.charCodeAt(index);
@ -55,7 +67,7 @@ Ox.endsWith <f> Tests if a string ends with a given substring
> Ox.endsWith('foobar', 'foo') > Ox.endsWith('foobar', 'foo')
false false
@*/ @*/
Ox.endsWith = function(string, substring) { export function endsWith(string, substring) {
string = string.toString(); string = string.toString();
substring = substring.toString(); substring = substring.toString();
return string.slice(string.length - substring.length) == substring; 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) > Ox.fromCodePoint(0x1F4A9)
'\uD83D\uDCA9' '\uD83D\uDCA9'
@*/ @*/
Ox.fromCodePoint = function() { export function fromCodePoint() {
var ret = ''; var ret = '';
Ox.forEach(arguments, function(number) { Ox.forEach(arguments, function(number) {
if (number < 0 || number > 0x10FFFF || !Ox.isInt(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') > Ox.isValidEmail('foo@bar..com')
false false
@*/ @*/
Ox.isValidEmail = function(string) { export function isValidEmail(string) {
return !!/^[0-9A-Z\.\+\-_]+@(?:[0-9A-Z\-]+\.)+[A-Z]{2,64}$/i.test(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('foo', -1)
'' ''
@*/ @*/
Ox.pad = function(string, position, length, padding) { export function pad(string, position, length, padding) {
var hasPosition = Ox.isString(arguments[1]), var hasPosition = Ox.isString(arguments[1]),
isNumber = Ox.isNumber(arguments[0]), isNumber = Ox.isNumber(arguments[0]),
last = Ox.last(arguments); last = Ox.last(arguments);
@ -166,7 +178,7 @@ Ox.parseDuration <f> Takes a formatted duration, returns seconds
> Ox.parseDuration('1::') > Ox.parseDuration('1::')
3600 3600
@*/ @*/
Ox.parseDuration = function(string) { export function parseDuration(string) {
return string.split(':').reverse().slice(0, 4).reduce(function(p, c, i) { return string.split(':').reverse().slice(0, 4).reduce(function(p, c, i) {
return p + (parseFloat(c) || 0) * (i == 3 ? 86400 : Math.pow(60, i)); return p + (parseFloat(c) || 0) * (i == 3 ? 86400 : Math.pow(60, i));
}, 0); }, 0);
@ -187,7 +199,7 @@ Ox.parsePath <f> Returns the components of a path
> Ox.parsePath('.foo') > Ox.parsePath('.foo')
{extension: '', filename: '.foo', pathname: ''} {extension: '', filename: '.foo', pathname: ''}
@*/ @*/
Ox.parsePath = function(string) { export function parsePath(string) {
var matches = /^(.+\/)?(.+?(\..+)?)?$/.exec(string); var matches = /^(.+\/)?(.+?(\..+)?)?$/.exec(string);
return { return {
pathname: matches[1] || '', 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') > Ox.parseSRT('1\n01:02:00,000 --> 01:02:03,400\nHello World')
[{'in': 3720, out: 3723.4, text: 'Hello 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') return string.replace(/\r\n/g, '\n').trim().split('\n\n')
.map(function(block) { .map(function(block) {
var lines = block.split('\n'), points; 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 > Ox.parseURL('http://www.foo.com:8080/bar/index.html?a=0&b=1#c').search
'?a=0&b=1' '?a=0&b=1'
@*/ @*/
Ox.parseURL = (function() { export const parseURL = (function() {
var a = document.createElement('a'), const keys = [
keys = ['hash', 'host', 'hostname', 'origin', 'hash', 'host', 'hostname', 'origin',
'pathname', 'port', 'protocol', 'search']; '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) { return function(string) {
var ret = {}; var ret = {};
a.href = string; a.href = string;
@ -276,10 +300,11 @@ Ox.parseURL = (function() {
}); });
return ret; return ret;
}; };
}
}()); }());
// FIXME: can we get rid of this? // FIXME: can we get rid of this?
Ox.parseUserAgent = function(userAgent) { export function parseUserAgent(userAgent) {
var aliases = { var aliases = {
browser: { browser: {
'Firefox': /(Fennec|Firebird|Iceweasel|Minefield|Namoroka|Phoenix|SeaMonkey|Shiretoko)/ '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 // FIXME: see https://github.com/paulmillr/es6-shim/blob/master/es6-shim.js
// for a faster version // for a faster version
Ox.repeat = function(value, times) { export function repeat(value, times) {
var ret; var ret;
if (Ox.isArray(value)) { if (Ox.isArray(value)) {
ret = []; 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) > Ox.splice('12xxxxx89', 2, 5, 3, 4, 5, 6, 7)
'123456789' '123456789'
@*/ @*/
Ox.splice = function(string, index, remove) { export function splice(string, index, remove) {
var array = string.split(''); var array = string.split('');
Array.prototype.splice.apply(array, Ox.slice(arguments, 1)); Array.prototype.splice.apply(array, Ox.slice(arguments, 1));
return array.join(''); return array.join('');
@ -474,7 +499,7 @@ Ox.startsWith <f> Tests if a string ends with a given substring
> Ox.startsWith('foobar', 'bar') > Ox.startsWith('foobar', 'bar')
false false
@*/ @*/
Ox.startsWith = function(string, substring) { export function startsWith(string, substring) {
string = string.toString(); string = string.toString();
substring = substring.toString(); substring = substring.toString();
return string.slice(0, substring.length) == substring; 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') > Ox.toCamelCase('foo_bar_baz')
'fooBarBaz' 'fooBarBaz'
@*/ @*/
Ox.toCamelCase = function(string) { export function toCamelCase(string) {
return string.replace(/[\-\/_][a-z]/g, function(string) { return string.replace(/[\-\/_][a-z]/g, function(string) {
return string[1].toUpperCase(); return string[1].toUpperCase();
}); });
@ -500,7 +525,7 @@ Ox.toDashes <f> Takes a camelCase string, returns a string with dashes
> Ox.toDashes('fooBarBaz') > Ox.toDashes('fooBarBaz')
'foo-bar-baz' 'foo-bar-baz'
@*/ @*/
Ox.toDashes = function(string) { export function toDashes(string) {
return string.replace(/[A-Z]/g, function(string) { return string.replace(/[A-Z]/g, function(string) {
return '-' + string.toLowerCase(); return '-' + string.toLowerCase();
}); });
@ -511,7 +536,7 @@ Ox.toSlashes <f> Takes a camelCase string, returns a string with slashes
> Ox.toSlashes('fooBarBaz') > Ox.toSlashes('fooBarBaz')
'foo/bar/baz' 'foo/bar/baz'
@*/ @*/
Ox.toSlashes = function(string) { export function toSlashes(string) {
return string.replace(/[A-Z]/g, function(string) { return string.replace(/[A-Z]/g, function(string) {
return '/' + string.toLowerCase(); return '/' + string.toLowerCase();
}); });
@ -524,7 +549,7 @@ Ox.toTitleCase <f> Returns a string with capitalized words
> Ox.toTitleCase('Apple releases iPhone, IBM stock plummets') > Ox.toTitleCase('Apple releases iPhone, IBM stock plummets')
'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) { return string.split(' ').map(function(value) {
var substring = value.slice(1), var substring = value.slice(1),
lowercase = substring.toLowerCase(); lowercase = substring.toLowerCase();
@ -540,7 +565,7 @@ Ox.toUnderscores <f> Takes a camelCase string, returns string with underscores
> Ox.toUnderscores('fooBarBaz') > Ox.toUnderscores('fooBarBaz')
'foo_bar_baz' 'foo_bar_baz'
@*/ @*/
Ox.toUnderscores = function(string) { export function toUnderscores(string) {
return string.replace(/[A-Z]/g, function(string) { return string.replace(/[A-Z]/g, function(string) {
return '_' + string.toLowerCase(); return '_' + string.toLowerCase();
}); });
@ -562,7 +587,7 @@ Ox.truncate <f> Truncate a string to a given length
> Ox.truncate('anticonstitutionellement', 'center', 16, '...') > Ox.truncate('anticonstitutionellement', 'center', 16, '...')
'anticon...lement' '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); var hasPosition = Ox.isString(arguments[1]), last = Ox.last(arguments);
position = hasPosition ? arguments[1] : 'right'; position = hasPosition ? arguments[1] : 'right';
length = hasPosition ? arguments[2] : arguments[1]; 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?') > Ox.words('Let\'s "split" array-likes into key/value pairs--okay?')
['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/), var array = string.toLowerCase().split(/\b/),
length = array.length, length = array.length,
startsWithWord = /\w/.test(array[0]); 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) > Ox.wordwrap('These are short words', 16, true)
'These are \nshort words' 'These are \nshort words'
@*/ @*/
Ox.wordwrap = function(string, length) { export function wordwrap(string, length) {
var balanced, lines, max, newline, words; var balanced, lines, max, newline, words;
string = String(string); string = String(string);
length = length || 80; length = length || 80;

View file

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

View file

@ -1,11 +1,35 @@
'use strict'; '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 Ox.getVideoFormat <f> Get supported video format
(formats) -> <a> List of supported formats (formats) -> <a> List of supported formats
format <s> First supported format form list format <s> First supported format form list
@*/ @*/
Ox.getVideoFormat = function(formats) { export function getVideoFormat(formats) {
var aliases = { var aliases = {
mp4: 'h264', mp4: 'h264',
m4v: '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);
});
}
};
}