WIP: try to convert to ES modules
This commit is contained in:
parent
ec5b050496
commit
299a08b6a3
29 changed files with 3003 additions and 2014 deletions
|
|
@ -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
18
source/Ox.compat.js
Normal 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
102
source/Ox/index.js
Normal 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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -1,287 +1,297 @@
|
||||||
'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 = {};
|
||||||
var type = Ox.typeOf(collection),
|
|
||||||
results = type == 'object' ? {} : [];
|
Object.assign(Ox,
|
||||||
callback = Ox.last(arguments);
|
OxObject,
|
||||||
that = arguments.length == 5 ? that : null;
|
OxConstants,
|
||||||
forEach(collection, function(value, key, collection, callback) {
|
OxMath
|
||||||
iterator(value, key, collection, function(value) {
|
);
|
||||||
results[key] = value;
|
|
||||||
callback();
|
|
||||||
});
|
function internalAsyncMap(forEach, collection, iterator, that, callback) {
|
||||||
}, that, function() {
|
var type = Ox.typeOf(collection),
|
||||||
callback(type == 'string' ? results.join('') : results);
|
results = type == 'object' ? {} : [];
|
||||||
|
callback = Ox.last(arguments);
|
||||||
|
that = arguments.length == 5 ? that : null;
|
||||||
|
forEach(collection, function(value, key, collection, callback) {
|
||||||
|
iterator(value, key, collection, function(value) {
|
||||||
|
results[key] = value;
|
||||||
|
callback();
|
||||||
});
|
});
|
||||||
|
}, that, function() {
|
||||||
|
callback(type == 'string' ? results.join('') : results);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function asyncMap(array, iterator, that, callback) {
|
||||||
|
array = Ox.makeArray(array);
|
||||||
|
callback = Ox.last(arguments);
|
||||||
|
that = arguments.length == 4 ? that : null;
|
||||||
|
if (array.some(Ox.isArray)) {
|
||||||
|
Ox.serialMap(array, function(value, key, array, callback) {
|
||||||
|
Ox.parallelMap(Ox.makeArray(value), iterator, callback);
|
||||||
|
}, callback);
|
||||||
|
} else {
|
||||||
|
Ox.parallelMap(array, iterator, callback);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Ox.asyncMap = function(array, iterator, that, callback) {
|
/*@
|
||||||
array = Ox.makeArray(array);
|
Ox.nonblockingForEach <f> Non-blocking `forEach` with synchronous iterator
|
||||||
callback = Ox.last(arguments);
|
(col, iterator[, that], callback[, ms]) -> <u> undefined
|
||||||
that = arguments.length == 4 ? that : null;
|
collection <a|o|s> Collection
|
||||||
if (array.some(Ox.isArray)) {
|
iterator <f> Iterator function
|
||||||
Ox.serialMap(array, function(value, key, array, callback) {
|
value <*> Value
|
||||||
Ox.parallelMap(Ox.makeArray(value), iterator, callback);
|
key <n|s> Key
|
||||||
}, callback);
|
collection <a|o|s> The collection
|
||||||
} else {
|
that <o> The iterator's `this` binding
|
||||||
Ox.parallelMap(array, iterator, callback);
|
callback <f> Callback function
|
||||||
}
|
ms <n> Number of milliseconds after which to insert a `setTimeout` call
|
||||||
};
|
@*/
|
||||||
|
export function nonblockingForEach(collection, iterator, that, callback, ms) {
|
||||||
/*@
|
var i = 0, keys, last = Ox.last(arguments),
|
||||||
Ox.nonblockingForEach <f> Non-blocking `forEach` with synchronous iterator
|
n, time, type = Ox.typeOf(collection);
|
||||||
(col, iterator[, that], callback[, ms]) -> <u> undefined
|
callback = Ox.isFunction(last) ? last : arguments[arguments.length - 2];
|
||||||
collection <a|o|s> Collection
|
collection = type == 'array' || type == 'object'
|
||||||
iterator <f> Iterator function
|
? collection : Ox.slice(collection);
|
||||||
value <*> Value
|
keys = type == 'object'
|
||||||
key <n|s> Key
|
? Object.keys(collection) : Ox.range(collection.length);
|
||||||
collection <a|o|s> The collection
|
ms = ms || 1000;
|
||||||
that <o> The iterator's `this` binding
|
n = Ox.len(collection);
|
||||||
callback <f> Callback function
|
that = arguments.length == 5 || (
|
||||||
ms <n> Number of milliseconds after which to insert a `setTimeout` call
|
arguments.length == 4 && Ox.isFunction(last)
|
||||||
@*/
|
) ? that : null;
|
||||||
Ox.nonblockingForEach = function(collection, iterator, that, callback, ms) {
|
time = +new Date();
|
||||||
var i = 0, keys, last = Ox.last(arguments),
|
iterate();
|
||||||
n, time, type = Ox.typeOf(collection);
|
function iterate() {
|
||||||
callback = Ox.isFunction(last) ? last : arguments[arguments.length - 2];
|
Ox.forEach(keys.slice(i), function(key) {
|
||||||
collection = type == 'array' || type == 'object'
|
if (key in collection) {
|
||||||
? collection : Ox.slice(collection);
|
if (iterator.call(
|
||||||
keys = type == 'object'
|
that, collection[key], key, collection
|
||||||
? Object.keys(collection) : Ox.range(collection.length);
|
) === false) {
|
||||||
ms = ms || 1000;
|
i = n;
|
||||||
n = Ox.len(collection);
|
return false;
|
||||||
that = arguments.length == 5 || (
|
|
||||||
arguments.length == 4 && Ox.isFunction(last)
|
|
||||||
) ? that : null;
|
|
||||||
time = +new Date();
|
|
||||||
iterate();
|
|
||||||
function iterate() {
|
|
||||||
Ox.forEach(keys.slice(i), function(key) {
|
|
||||||
if (key in collection) {
|
|
||||||
if (iterator.call(
|
|
||||||
that, collection[key], key, collection
|
|
||||||
) === false) {
|
|
||||||
i = n;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
i++;
|
|
||||||
if (+new Date() >= time + ms) {
|
|
||||||
return false; // break
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (i < n) {
|
|
||||||
setTimeout(function() {
|
|
||||||
time = +new Date();
|
|
||||||
iterate();
|
|
||||||
}, 1);
|
|
||||||
} else {
|
|
||||||
callback();
|
|
||||||
}
|
}
|
||||||
}
|
i++;
|
||||||
};
|
if (+new Date() >= time + ms) {
|
||||||
|
return false; // break
|
||||||
/*@
|
}
|
||||||
Ox.nonblockingMap <f> Non-blocking `map` with synchronous iterator
|
|
||||||
(collection, iterator[, that], callback[, ms]) -> <u> undefined
|
|
||||||
collection <a|o|s> Collection
|
|
||||||
iterator <f> Iterator function
|
|
||||||
that <o> The iterator's `this` binding
|
|
||||||
callback <f> Callback function
|
|
||||||
ms <n> Number of milliseconds after which to insert a `setTimeout` call
|
|
||||||
<script>
|
|
||||||
// var time = +new Date();
|
|
||||||
// Ox.nonblockingMap(
|
|
||||||
// Ox.range(1000000),
|
|
||||||
// function (value, index, array) {
|
|
||||||
// return +new Date() - time;
|
|
||||||
// },
|
|
||||||
// function(results) {
|
|
||||||
// Ox.print(results.length);
|
|
||||||
// },
|
|
||||||
// 1000
|
|
||||||
// );
|
|
||||||
</script>
|
|
||||||
> Ox.nonblockingMap(Ox.range(100000), Ox.identity, function(r) { Ox.test(r.length, 100000); })
|
|
||||||
undefined
|
|
||||||
@*/
|
|
||||||
Ox.nonblockingMap = function(collection, iterator, that, callback, ms) {
|
|
||||||
var last = Ox.last(arguments),
|
|
||||||
type = Ox.typeOf(collection),
|
|
||||||
results = type == 'object' ? {} : [];
|
|
||||||
callback = Ox.isFunction(last) ? last : arguments[arguments.length - 2];
|
|
||||||
that = arguments.length == 5 || (
|
|
||||||
arguments.length == 4 && Ox.isFunction(last)
|
|
||||||
) ? that : null;
|
|
||||||
Ox.nonblockingForEach(collection, function(value, key, collection) {
|
|
||||||
results[key] = iterator.call(that, value, key, collection);
|
|
||||||
}, function() {
|
|
||||||
callback(type == 'string' ? results.join('') : results);
|
|
||||||
}, ms);
|
|
||||||
};
|
|
||||||
|
|
||||||
/*@
|
|
||||||
Ox.parallelForEach <f> `forEach` with asynchronous iterator, running in parallel
|
|
||||||
(collection, iterator[, that], callback) -> <u> undefined
|
|
||||||
collection <a|o|s> Collection
|
|
||||||
iterator <f> Iterator function
|
|
||||||
value <*> Value
|
|
||||||
key <n|s> Key
|
|
||||||
collection <a|o|s> The collection
|
|
||||||
callback <f> Callback function
|
|
||||||
that <o> The iterator's this binding
|
|
||||||
callback <f> Callback function
|
|
||||||
<script>
|
|
||||||
Ox.test.pfeNumber = 0;
|
|
||||||
Ox.test.pfeIterator = function(value, index, array, callback) {
|
|
||||||
if (index < 5) {
|
|
||||||
Ox.test.pfeNumber++;
|
|
||||||
}
|
|
||||||
setTimeout(callback);
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
> Ox.parallelForEach(Ox.range(10), Ox.test.pfeIterator, function() { Ox.test(Ox.test.pfeNumber, 5); })
|
|
||||||
undefined
|
|
||||||
@*/
|
|
||||||
Ox.parallelForEach = function(collection, iterator, that, callback) {
|
|
||||||
var i = 0, n, type = Ox.typeOf(collection);
|
|
||||||
callback = callback || (arguments.length == 3 ? arguments[2] : Ox.noop);
|
|
||||||
collection = type == 'array' || type == 'object'
|
|
||||||
? collection : Ox.slice(collection);
|
|
||||||
n = Ox.len(collection);
|
|
||||||
that = arguments.length == 4 ? that : null;
|
|
||||||
Ox.forEach(collection, function(value, key, collection) {
|
|
||||||
iterator.call(that, value, key, collection, function() {
|
|
||||||
++i == n && callback();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
};
|
if (i < n) {
|
||||||
|
setTimeout(function() {
|
||||||
/*@
|
time = +new Date();
|
||||||
Ox.parallelMap <f> Parallel `map` with asynchronous iterator
|
iterate();
|
||||||
(collection, iterator[, that], callback) -> <u> undefined
|
}, 1);
|
||||||
collection <a|o|s> Collection
|
} else {
|
||||||
iterator <f> Iterator function
|
callback();
|
||||||
value <*> Value
|
|
||||||
key <n|s> Key
|
|
||||||
collection <a|o|s> The collection
|
|
||||||
callback <f> Callback function
|
|
||||||
that <o> The iterator's this binding
|
|
||||||
callback <f> Callback function
|
|
||||||
results <a|o|s> Results
|
|
||||||
<script>
|
|
||||||
// var time = +new Date();
|
|
||||||
// Ox.parallelMap(
|
|
||||||
// Ox.range(10),
|
|
||||||
// function (value, index, array, callback) {
|
|
||||||
// setTimeout(function() {
|
|
||||||
// callback(+new Date() - time);
|
|
||||||
// }, Ox.random(1000));
|
|
||||||
// },
|
|
||||||
// function(results) {
|
|
||||||
// Ox.print(results);
|
|
||||||
// }
|
|
||||||
// );
|
|
||||||
Ox.test.pmIterator = function(value, index, array, callback) {
|
|
||||||
setTimeout(callback(value - index));
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
> Ox.parallelMap(Ox.range(10), Ox.test.pmIterator, function(r) { Ox.test(Ox.sum(r), 0); })
|
|
||||||
undefined
|
|
||||||
@*/
|
|
||||||
Ox.parallelMap = function() {
|
|
||||||
asyncMap.apply(null, [Ox.parallelForEach].concat(Ox.slice(arguments)));
|
|
||||||
};
|
|
||||||
|
|
||||||
/*@
|
|
||||||
Ox.serialForEach <f> `forEach` with asynchronous iterator, run serially
|
|
||||||
(collection, iterator[, that], callback) -> <u> undefined
|
|
||||||
collection <a|o|s> Collection
|
|
||||||
iterator <f> Iterator function
|
|
||||||
value <*> Value
|
|
||||||
key <n|s> Key
|
|
||||||
collection <a|o|s> The collection
|
|
||||||
callback <f> Callback function
|
|
||||||
that <o> The iterator's this binding
|
|
||||||
callback <f> Callback function
|
|
||||||
<script>
|
|
||||||
Ox.test.sfeNumber = 0;
|
|
||||||
Ox.test.sfeIterator = function(value, index, array, callback) {
|
|
||||||
Ox.test.sfeNumber++;
|
|
||||||
setTimeout(function() {
|
|
||||||
callback(index < 4);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
> Ox.serialForEach(Ox.range(10), Ox.test.sfeIterator, function() { Ox.test(Ox.test.sfeNumber, 5); })
|
|
||||||
undefined
|
|
||||||
@*/
|
|
||||||
Ox.serialForEach = function(collection, iterator, that, callback) {
|
|
||||||
var i = 0, keys, n, type = Ox.typeOf(collection);
|
|
||||||
callback = callback || (arguments.length == 3 ? arguments[2] : Ox.noop);
|
|
||||||
collection = type == 'array' || type == 'object'
|
|
||||||
? collection : Ox.slice(collection);
|
|
||||||
keys = type == 'object'
|
|
||||||
? Object.keys(collection) : Ox.range(collection.length);
|
|
||||||
n = Ox.len(collection);
|
|
||||||
that = arguments.length == 4 ? that : null;
|
|
||||||
iterate();
|
|
||||||
function iterate(value) {
|
|
||||||
if (value !== false) {
|
|
||||||
if (keys[i] in collection) {
|
|
||||||
iterator.call(
|
|
||||||
that,
|
|
||||||
collection[keys[i]],
|
|
||||||
keys[i],
|
|
||||||
collection,
|
|
||||||
++i < n ? iterate : callback
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
++i < n ? iterate() : callback();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/*@
|
/*@
|
||||||
Ox.serialMap <f> Serial `map` with asynchronous iterator
|
Ox.nonblockingMap <f> Non-blocking `map` with synchronous iterator
|
||||||
(collection, iterator[, that], callback) -> <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
|
||||||
value <*> Value
|
that <o> The iterator's `this` binding
|
||||||
key <n|s> Key
|
callback <f> Callback function
|
||||||
collection <a|o|s> The collection
|
ms <n> Number of milliseconds after which to insert a `setTimeout` call
|
||||||
callback <f> Callback function
|
<script>
|
||||||
that <o> The iterator's this binding
|
// var time = +new Date();
|
||||||
|
// Ox.nonblockingMap(
|
||||||
|
// Ox.range(1000000),
|
||||||
|
// function (value, index, array) {
|
||||||
|
// return +new Date() - time;
|
||||||
|
// },
|
||||||
|
// function(results) {
|
||||||
|
// Ox.print(results.length);
|
||||||
|
// },
|
||||||
|
// 1000
|
||||||
|
// );
|
||||||
|
</script>
|
||||||
|
> Ox.nonblockingMap(Ox.range(100000), Ox.identity, function(r) { Ox.test(r.length, 100000); })
|
||||||
|
undefined
|
||||||
|
@*/
|
||||||
|
export function nonblockingMap(collection, iterator, that, callback, ms) {
|
||||||
|
var last = Ox.last(arguments),
|
||||||
|
type = Ox.typeOf(collection),
|
||||||
|
results = type == 'object' ? {} : [];
|
||||||
|
callback = Ox.isFunction(last) ? last : arguments[arguments.length - 2];
|
||||||
|
that = arguments.length == 5 || (
|
||||||
|
arguments.length == 4 && Ox.isFunction(last)
|
||||||
|
) ? that : null;
|
||||||
|
Ox.nonblockingForEach(collection, function(value, key, collection) {
|
||||||
|
results[key] = iterator.call(that, value, key, collection);
|
||||||
|
}, function() {
|
||||||
|
callback(type == 'string' ? results.join('') : results);
|
||||||
|
}, ms);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*@
|
||||||
|
Ox.parallelForEach <f> `forEach` with asynchronous iterator, running in parallel
|
||||||
|
(collection, iterator[, that], callback) -> <u> undefined
|
||||||
|
collection <a|o|s> Collection
|
||||||
|
iterator <f> Iterator function
|
||||||
|
value <*> Value
|
||||||
|
key <n|s> Key
|
||||||
|
collection <a|o|s> The collection
|
||||||
callback <f> Callback function
|
callback <f> Callback function
|
||||||
results <a|o|s> Results
|
that <o> The iterator's this binding
|
||||||
<script>
|
callback <f> Callback function
|
||||||
// var time = +new Date();
|
<script>
|
||||||
// Ox.serialMap(
|
Ox.test.pfeNumber = 0;
|
||||||
// Ox.range(10),
|
Ox.test.pfeIterator = function(value, index, array, callback) {
|
||||||
// function (value, index, array, callback) {
|
if (index < 5) {
|
||||||
// setTimeout(function() {
|
Ox.test.pfeNumber++;
|
||||||
// callback(+new Date() - time);
|
}
|
||||||
// }, Ox.random(1000));
|
setTimeout(callback);
|
||||||
// },
|
};
|
||||||
// function(results) {
|
</script>
|
||||||
// Ox.print(results);
|
> Ox.parallelForEach(Ox.range(10), Ox.test.pfeIterator, function() { Ox.test(Ox.test.pfeNumber, 5); })
|
||||||
// }
|
undefined
|
||||||
// );
|
@*/
|
||||||
Ox.test.smIterator = function(value, index, array, callback) {
|
export function parallelForEach(collection, iterator, that, callback) {
|
||||||
setTimeout(callback(value - index));
|
var i = 0, n, type = Ox.typeOf(collection);
|
||||||
};
|
callback = callback || (arguments.length == 3 ? arguments[2] : Ox.noop);
|
||||||
</script>
|
collection = type == 'array' || type == 'object'
|
||||||
> Ox.serialMap(Ox.range(10), Ox.test.smIterator, function(r) { Ox.test(Ox.sum(r), 0); })
|
? collection : Ox.slice(collection);
|
||||||
undefined
|
n = Ox.len(collection);
|
||||||
@*/
|
that = arguments.length == 4 ? that : null;
|
||||||
Ox.serialMap = function(collection, iterator, that, callback) {
|
Ox.forEach(collection, function(value, key, collection) {
|
||||||
asyncMap.apply(null, [Ox.serialForEach].concat(Ox.slice(arguments)));
|
iterator.call(that, value, key, collection, function() {
|
||||||
};
|
++i == n && callback();
|
||||||
// FIXME: The above test with 10000 iterations blows the stack
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/*@
|
||||||
|
Ox.parallelMap <f> Parallel `map` with asynchronous iterator
|
||||||
|
(collection, iterator[, that], callback) -> <u> undefined
|
||||||
|
collection <a|o|s> Collection
|
||||||
|
iterator <f> Iterator function
|
||||||
|
value <*> Value
|
||||||
|
key <n|s> Key
|
||||||
|
collection <a|o|s> The collection
|
||||||
|
callback <f> Callback function
|
||||||
|
that <o> The iterator's this binding
|
||||||
|
callback <f> Callback function
|
||||||
|
results <a|o|s> Results
|
||||||
|
<script>
|
||||||
|
// var time = +new Date();
|
||||||
|
// Ox.parallelMap(
|
||||||
|
// Ox.range(10),
|
||||||
|
// function (value, index, array, callback) {
|
||||||
|
// setTimeout(function() {
|
||||||
|
// callback(+new Date() - time);
|
||||||
|
// }, Ox.random(1000));
|
||||||
|
// },
|
||||||
|
// function(results) {
|
||||||
|
// Ox.print(results);
|
||||||
|
// }
|
||||||
|
// );
|
||||||
|
Ox.test.pmIterator = function(value, index, array, callback) {
|
||||||
|
setTimeout(callback(value - index));
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
> Ox.parallelMap(Ox.range(10), Ox.test.pmIterator, function(r) { Ox.test(Ox.sum(r), 0); })
|
||||||
|
undefined
|
||||||
|
@*/
|
||||||
|
export function parallelMap() {
|
||||||
|
internalAsyncMap.apply(null, [Ox.parallelForEach].concat(Ox.slice(arguments)));
|
||||||
|
};
|
||||||
|
|
||||||
|
/*@
|
||||||
|
Ox.serialForEach <f> `forEach` with asynchronous iterator, run serially
|
||||||
|
(collection, iterator[, that], callback) -> <u> undefined
|
||||||
|
collection <a|o|s> Collection
|
||||||
|
iterator <f> Iterator function
|
||||||
|
value <*> Value
|
||||||
|
key <n|s> Key
|
||||||
|
collection <a|o|s> The collection
|
||||||
|
callback <f> Callback function
|
||||||
|
that <o> The iterator's this binding
|
||||||
|
callback <f> Callback function
|
||||||
|
<script>
|
||||||
|
Ox.test.sfeNumber = 0;
|
||||||
|
Ox.test.sfeIterator = function(value, index, array, callback) {
|
||||||
|
Ox.test.sfeNumber++;
|
||||||
|
setTimeout(function() {
|
||||||
|
callback(index < 4);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
> Ox.serialForEach(Ox.range(10), Ox.test.sfeIterator, function() { Ox.test(Ox.test.sfeNumber, 5); })
|
||||||
|
undefined
|
||||||
|
@*/
|
||||||
|
export function serialForEach(collection, iterator, that, callback) {
|
||||||
|
var i = 0, keys, n, type = Ox.typeOf(collection);
|
||||||
|
callback = callback || (arguments.length == 3 ? arguments[2] : Ox.noop);
|
||||||
|
collection = type == 'array' || type == 'object'
|
||||||
|
? collection : Ox.slice(collection);
|
||||||
|
keys = type == 'object'
|
||||||
|
? Object.keys(collection) : Ox.range(collection.length);
|
||||||
|
n = Ox.len(collection);
|
||||||
|
that = arguments.length == 4 ? that : null;
|
||||||
|
iterate();
|
||||||
|
function iterate(value) {
|
||||||
|
if (value !== false) {
|
||||||
|
if (keys[i] in collection) {
|
||||||
|
iterator.call(
|
||||||
|
that,
|
||||||
|
collection[keys[i]],
|
||||||
|
keys[i],
|
||||||
|
collection,
|
||||||
|
++i < n ? iterate : callback
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
++i < n ? iterate() : callback();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*@
|
||||||
|
Ox.serialMap <f> Serial `map` with asynchronous iterator
|
||||||
|
(collection, iterator[, that], callback) -> <u> undefined
|
||||||
|
collection <a|o|s> Collection
|
||||||
|
iterator <f> Iterator function
|
||||||
|
value <*> Value
|
||||||
|
key <n|s> Key
|
||||||
|
collection <a|o|s> The collection
|
||||||
|
callback <f> Callback function
|
||||||
|
that <o> The iterator's this binding
|
||||||
|
callback <f> Callback function
|
||||||
|
results <a|o|s> Results
|
||||||
|
<script>
|
||||||
|
// var time = +new Date();
|
||||||
|
// Ox.serialMap(
|
||||||
|
// Ox.range(10),
|
||||||
|
// function (value, index, array, callback) {
|
||||||
|
// setTimeout(function() {
|
||||||
|
// callback(+new Date() - time);
|
||||||
|
// }, Ox.random(1000));
|
||||||
|
// },
|
||||||
|
// function(results) {
|
||||||
|
// Ox.print(results);
|
||||||
|
// }
|
||||||
|
// );
|
||||||
|
Ox.test.smIterator = function(value, index, array, callback) {
|
||||||
|
setTimeout(callback(value - index));
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
> Ox.serialMap(Ox.range(10), Ox.test.smIterator, function(r) { Ox.test(Ox.sum(r), 0); })
|
||||||
|
undefined
|
||||||
|
@*/
|
||||||
|
export function serialMap(collection, iterator, that, callback) {
|
||||||
|
internalAsyncMap.apply(null, [Ox.serialForEach].concat(Ox.slice(arguments)));
|
||||||
|
};
|
||||||
|
// FIXME: The above test with 10000 iterations blows the stack
|
||||||
|
|
||||||
}());
|
|
||||||
|
|
|
||||||
49
source/Ox/js/Base.js
Normal file
49
source/Ox/js/Base.js
Normal 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;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
@ -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_);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -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 = {
|
||||||
'"': '"', '&': '&', "'": ''', '<': '<', '>': '>'
|
'"': '"', '&': '&', "'": ''', '<': '<', '>': '>'
|
||||||
};
|
};
|
||||||
//@ 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);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -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,20 +84,18 @@ 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) {
|
||||||
Ox.setLocale(Ox.LOCALE, function() {
|
Ox.setLocale(Ox.LOCALE, function() {
|
||||||
callback(succeeded == length);
|
callback(succeeded == length);
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -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;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}());
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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(
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -1,480 +1,488 @@
|
||||||
'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,
|
||||||
return Ox.map(point, function(val) {
|
OxObject,
|
||||||
return Ox.mod(Ox.deg(val) + 180, 360) - 180;
|
OxConstants,
|
||||||
});
|
OxMath
|
||||||
|
);
|
||||||
|
|
||||||
|
// fixme: make all this work with different types of "points"
|
||||||
|
// i.e. {lat, lng}, [lat, lng]
|
||||||
|
|
||||||
|
function deg(point) {
|
||||||
|
return Ox.map(point, function(val) {
|
||||||
|
return Ox.mod(Ox.deg(val) + 180, 360) - 180;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function rad(point) {
|
||||||
|
return Ox.map(point, function(val) {
|
||||||
|
return Ox.rad(val);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function splitArea(area) {
|
||||||
|
return Ox.crossesDateline(area.sw, area.ne) ? [
|
||||||
|
{sw: area.sw, ne: {lat: area.ne.lat, lng: 180}},
|
||||||
|
{sw: {lat: area.sw.lat, lng: -180}, ne: area.ne}
|
||||||
|
] : [area];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*@
|
||||||
|
Ox.crossesDateline <f> Returns true if a given line crosses the dateline
|
||||||
|
> Ox.crossesDateline({lat: 0, lng: -90}, {lat: 0, lng: 90})
|
||||||
|
false
|
||||||
|
> Ox.crossesDateline({lat: 0, lng: 90}, {lat: 0, lng: -90})
|
||||||
|
true
|
||||||
|
@*/
|
||||||
|
// FIXME: argument should be {w: ..., e: ...}
|
||||||
|
export function crossesDateline(pointA, pointB) {
|
||||||
|
return pointA.lng > pointB.lng;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*@
|
||||||
|
Ox.getArea <f> Returns the area in square meters of a given rectancle
|
||||||
|
@*/
|
||||||
|
// FIXME: argument should be {sw: ..., ne: ...}
|
||||||
|
export function getArea(pointA, pointB) {
|
||||||
|
/*
|
||||||
|
area of a ring between two latitudes:
|
||||||
|
2 * PI * r^2 * abs(sin(latA) - sin(latB))
|
||||||
|
see http://mathforum.org/library/drmath/view/63767.html
|
||||||
|
=>
|
||||||
|
2 * Math.PI
|
||||||
|
* Math.pow(Ox.EARTH_RADIUS, 2)
|
||||||
|
* Math.abs(Math.sin(Ox.rad(latA)) - Math.sin(Ox.rad(latB)))
|
||||||
|
* Math.abs(Ox.rad(lngA) - Ox.rad(lngB))
|
||||||
|
/ (2 * Math.PI)
|
||||||
|
*/
|
||||||
|
if (Ox.crossesDateline(pointA, pointB)) {
|
||||||
|
pointB.lng += 360;
|
||||||
}
|
}
|
||||||
|
pointA = rad(pointA);
|
||||||
|
pointB = rad(pointB);
|
||||||
|
return Math.pow(Ox.EARTH_RADIUS, 2)
|
||||||
|
* Math.abs(Math.sin(pointA.lat) - Math.sin(pointB.lat))
|
||||||
|
* Math.abs(pointA.lng - pointB.lng);
|
||||||
|
};
|
||||||
|
|
||||||
function rad(point) {
|
/*@
|
||||||
return Ox.map(point, function(val) {
|
Ox.getAverageBearing <f> Returns the average of two bearings
|
||||||
return Ox.rad(val);
|
> Ox.getAverageBearing(0, 90)
|
||||||
});
|
45
|
||||||
|
> Ox.getAverageBearing(10, 350)
|
||||||
|
0
|
||||||
|
@*/
|
||||||
|
// FIXME: find the proper name of this operation
|
||||||
|
// FIMXE: use in manhattan grid example
|
||||||
|
export function getAverageBearing(bearingA, bearingB) {
|
||||||
|
return Ox.mod((bearingA + bearingB) / 2 + (
|
||||||
|
Math.abs(bearingA - bearingB) > 180 ? 180 : 0
|
||||||
|
), 360);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*@
|
||||||
|
Ox.getBearing <f> Returns the bearing from one point to another
|
||||||
|
> Ox.getBearing({lat: -45, lng: 0}, {lat: 45, lng: 0})
|
||||||
|
0
|
||||||
|
> Ox.getBearing({lat: 0, lng: -90}, {lat: 0, lng: 90})
|
||||||
|
90
|
||||||
|
@*/
|
||||||
|
export function getBearing(pointA, pointB) {
|
||||||
|
pointA = rad(pointA);
|
||||||
|
pointB = rad(pointB);
|
||||||
|
var x = Math.cos(pointA.lat) * Math.sin(pointB.lat)
|
||||||
|
- Math.sin(pointA.lat) * Math.cos(pointB.lat)
|
||||||
|
* Math.cos(pointB.lng - pointA.lng),
|
||||||
|
y = Math.sin(pointB.lng - pointA.lng)
|
||||||
|
* Math.cos(pointB.lat);
|
||||||
|
return (Ox.deg(Math.atan2(y, x)) + 360) % 360;
|
||||||
|
};
|
||||||
|
|
||||||
|
// FIXME: name, docs
|
||||||
|
export function getBearingDifference(bearingA, bearingB) {
|
||||||
|
var difference = Math.abs(bearingA - bearingB);
|
||||||
|
return difference > 180 ? 360 - difference : difference;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*@
|
||||||
|
Ox.getCenter <f> Returns the center of a recangle on a spehre
|
||||||
|
> Ox.getCenter({lat: -45, lng: -90}, {lat: 45, lng: 90})
|
||||||
|
{lat: 0, lng: 0}
|
||||||
|
@*/
|
||||||
|
export function getCenter(pointA, pointB) {
|
||||||
|
pointA = rad(pointA);
|
||||||
|
pointB = rad(pointB);
|
||||||
|
var x = Math.cos(pointB.lat)
|
||||||
|
* Math.cos(pointB.lng - pointA.lng),
|
||||||
|
y = Math.cos(pointB.lat)
|
||||||
|
* Math.sin(pointB.lng - pointA.lng),
|
||||||
|
d = Math.sqrt(
|
||||||
|
Math.pow(Math.cos(pointA.lat) + x, 2) + Math.pow(y, 2)
|
||||||
|
),
|
||||||
|
lat = Math.atan2(Math.sin(pointA.lat) + Math.sin(pointB.lat), d),
|
||||||
|
lng = pointA.lng + Math.atan2(y, Math.cos(pointA.lat) + x);
|
||||||
|
return deg({lat: lat, lng: lng});
|
||||||
|
};
|
||||||
|
|
||||||
|
/*@
|
||||||
|
Ox.getCircle <f> Returns points on a circle around a given point
|
||||||
|
(center, radius, precision) -> <a> Points
|
||||||
|
center <o> Center point ({lat, lng})
|
||||||
|
radius <n> Radius in meters
|
||||||
|
precision <n> Precision (the circle will have 2^precision segments)
|
||||||
|
@*/
|
||||||
|
export function getCircle(center, radius, precision) {
|
||||||
|
return Ox.range(
|
||||||
|
0, 360, 360 / Math.pow(2, precision)
|
||||||
|
).map(function(bearing) {
|
||||||
|
return Ox.getPoint(center, radius, bearing);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// FIXME: name, docs
|
||||||
|
export function getClosestBearing(bearing, bearings) {
|
||||||
|
var differences = bearings.map(function(bearing_) {
|
||||||
|
return getBearingDifference(bearing, bearing_);
|
||||||
|
});
|
||||||
|
return bearings[differences.indexOf(Ox.min(differences))];
|
||||||
|
};
|
||||||
|
|
||||||
|
/*@
|
||||||
|
Ox.getDegreesPerMeter <f> Returns degrees per meter at a given latitude
|
||||||
|
> 360 / Ox.getDegreesPerMeter(0)
|
||||||
|
Ox.EARTH_CIRCUMFERENCE
|
||||||
|
@*/
|
||||||
|
export function getDegreesPerMeter(lat) {
|
||||||
|
return 360 / Ox.EARTH_CIRCUMFERENCE / Math.cos(lat * Math.PI / 180);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*@
|
||||||
|
Ox.getDistance <f> Returns the distance in meters between two points
|
||||||
|
> Ox.getDistance({lat: -45, lng: -90}, {lat: 45, lng: 90}) * 2
|
||||||
|
Ox.EARTH_CIRCUMFERENCE
|
||||||
|
@*/
|
||||||
|
export function getDistance(pointA, pointB) {
|
||||||
|
pointA = rad(pointA);
|
||||||
|
pointB = rad(pointB);
|
||||||
|
return Math.acos(
|
||||||
|
Math.sin(pointA.lat) * Math.sin(pointB.lat)
|
||||||
|
+ Math.cos(pointA.lat) * Math.cos(pointB.lat)
|
||||||
|
* Math.cos(pointB.lng - pointA.lng)
|
||||||
|
) * Ox.EARTH_RADIUS;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*@
|
||||||
|
Ox.getLatLngByXY <f> Returns lat/lng for a given x/y on a 1x1 mercator projection
|
||||||
|
> Ox.getLatLngByXY({x: 0.5, y: 0.5})
|
||||||
|
{lat: -0, lng: 0}
|
||||||
|
@*/
|
||||||
|
export function getLatLngByXY(xy) {
|
||||||
|
function getValue(value) {
|
||||||
|
return (value - 0.5) * 2 * Math.PI;
|
||||||
}
|
}
|
||||||
|
return {
|
||||||
|
lat: -Ox.deg(Math.atan(Ox.sinh(getValue(xy.y)))),
|
||||||
|
lng: Ox.deg(getValue(xy.x))
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
function splitArea(area) {
|
/*@
|
||||||
return Ox.crossesDateline(area.sw, area.ne) ? [
|
Ox.getLine <f> Returns points on a line between two points
|
||||||
{sw: area.sw, ne: {lat: area.ne.lat, lng: 180}},
|
(pointA, pointB, precision) -> <a> Points
|
||||||
{sw: {lat: area.sw.lat, lng: -180}, ne: area.ne}
|
pointA <o> Start point ({lat, lng})
|
||||||
] : [area];
|
pointB <o> End point ({lat, lng})
|
||||||
|
precision <n> Precision (the line will have 2^precision segments)
|
||||||
|
@*/
|
||||||
|
export function getLine(pointA, pointB, precision) {
|
||||||
|
var line = [pointA, pointB], points;
|
||||||
|
while (precision > 0) {
|
||||||
|
points = [line[0]];
|
||||||
|
Ox.loop(line.length - 1, function(i) {
|
||||||
|
points.push(
|
||||||
|
Ox.getCenter(line[i], line[i + 1]),
|
||||||
|
line[i + 1]
|
||||||
|
);
|
||||||
|
});
|
||||||
|
line = points;
|
||||||
|
precision--;
|
||||||
}
|
}
|
||||||
|
return line;
|
||||||
|
};
|
||||||
|
|
||||||
/*@
|
/*@
|
||||||
Ox.crossesDateline <f> Returns true if a given line crosses the dateline
|
Ox.getMetersPerDegree <f> Returns meters per degree at a given latitude
|
||||||
> Ox.crossesDateline({lat: 0, lng: -90}, {lat: 0, lng: 90})
|
> Ox.getMetersPerDegree(0) * 360
|
||||||
false
|
Ox.EARTH_CIRCUMFERENCE
|
||||||
> Ox.crossesDateline({lat: 0, lng: 90}, {lat: 0, lng: -90})
|
@*/
|
||||||
true
|
export function getMetersPerDegree(lat) {
|
||||||
@*/
|
return Math.cos(lat * Math.PI / 180) * Ox.EARTH_CIRCUMFERENCE / 360;
|
||||||
// FIXME: argument should be {w: ..., e: ...}
|
};
|
||||||
Ox.crossesDateline = function(pointA, pointB) {
|
|
||||||
return pointA.lng > pointB.lng;
|
/*@
|
||||||
|
Ox.getPoint <f> Returns a point at a given distance/bearing from a given point
|
||||||
|
> Ox.getPoint({lat: -45, lng: 0}, Ox.EARTH_CIRCUMFERENCE / 4, 0)
|
||||||
|
{lat: 45, lng: 0}
|
||||||
|
@*/
|
||||||
|
export function getPoint(point, distance, bearing) {
|
||||||
|
var pointB = {};
|
||||||
|
point = rad(point);
|
||||||
|
distance /= Ox.EARTH_RADIUS;
|
||||||
|
bearing = Ox.rad(bearing);
|
||||||
|
pointB.lat = Math.asin(
|
||||||
|
Math.sin(point.lat) * Math.cos(distance)
|
||||||
|
+ Math.cos(point.lat) * Math.sin(distance) * Math.cos(bearing)
|
||||||
|
);
|
||||||
|
pointB.lng = point.lng + Math.atan2(
|
||||||
|
Math.sin(bearing) * Math.sin(distance) * Math.cos(point.lat),
|
||||||
|
Math.cos(distance) - Math.sin(point.lat) * Math.sin(pointB.lat)
|
||||||
|
);
|
||||||
|
return deg(pointB);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*@
|
||||||
|
Ox.getXYByLatLng <f> Returns x/y on a 1x1 mercator projection for a given lat/lng
|
||||||
|
> Ox.getXYByLatLng({lat: 0, lng: 0})
|
||||||
|
{x: 0.5, y: 0.5}
|
||||||
|
@*/
|
||||||
|
export function getXYByLatLng(latlng) {
|
||||||
|
function getValue(value) {
|
||||||
|
return value / (2 * Math.PI) + 0.5;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
x: getValue(Ox.rad(latlng.lng)),
|
||||||
|
y: getValue(Ox.asinh(Math.tan(Ox.rad(-latlng.lat))))
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
/*@
|
/*@
|
||||||
Ox.getArea <f> Returns the area in square meters of a given rectancle
|
Ox.isPolar <f> Returns true if a given point is outside the bounds of a mercator projection
|
||||||
@*/
|
> Ox.isPolar({lat: 90, lng: 0})
|
||||||
// FIXME: argument should be {sw: ..., ne: ...}
|
true
|
||||||
Ox.getArea = function(pointA, pointB) {
|
@*/
|
||||||
/*
|
export function isPolar(point) {
|
||||||
area of a ring between two latitudes:
|
return point.lat < Ox.MIN_LATITUDE || point.lat > Ox.MAX_LATITUDE;
|
||||||
2 * PI * r^2 * abs(sin(latA) - sin(latB))
|
};
|
||||||
see http://mathforum.org/library/drmath/view/63767.html
|
|
||||||
=>
|
|
||||||
2 * Math.PI
|
|
||||||
* Math.pow(Ox.EARTH_RADIUS, 2)
|
|
||||||
* Math.abs(Math.sin(Ox.rad(latA)) - Math.sin(Ox.rad(latB)))
|
|
||||||
* Math.abs(Ox.rad(lngA) - Ox.rad(lngB))
|
|
||||||
/ (2 * Math.PI)
|
|
||||||
*/
|
|
||||||
if (Ox.crossesDateline(pointA, pointB)) {
|
|
||||||
pointB.lng += 360;
|
|
||||||
}
|
|
||||||
pointA = rad(pointA);
|
|
||||||
pointB = rad(pointB);
|
|
||||||
return Math.pow(Ox.EARTH_RADIUS, 2)
|
|
||||||
* Math.abs(Math.sin(pointA.lat) - Math.sin(pointB.lat))
|
|
||||||
* Math.abs(pointA.lng - pointB.lng);
|
|
||||||
};
|
|
||||||
|
|
||||||
/*@
|
/*@
|
||||||
Ox.getAverageBearing <f> Returns the average of two bearings
|
Ox.containsArea <f> Returns true if an area contains another area
|
||||||
> Ox.getAverageBearing(0, 90)
|
<script>
|
||||||
45
|
Ox.test.areas = [
|
||||||
> Ox.getAverageBearing(10, 350)
|
{sw: {lat: -30, lng: -30}, ne: {lat: 30, lng: 30}},
|
||||||
0
|
{sw: {lat: -20, lng: -40}, ne: {lat: 20, lng: 40}},
|
||||||
@*/
|
{sw: {lat: -30, lng: 150}, ne: {lat: 30, lng: -150}},
|
||||||
// FIXME: find the proper name of this operation
|
{sw: {lat: 10, lng: -170}, ne: {lat: 20, lng: -160}}
|
||||||
// FIMXE: use in manhattan grid example
|
];
|
||||||
Ox.getAverageBearing = function(bearingA, bearingB) {
|
</script>
|
||||||
return Ox.mod((bearingA + bearingB) / 2 + (
|
> Ox.containsArea(Ox.test.areas[0], Ox.test.areas[1])
|
||||||
Math.abs(bearingA - bearingB) > 180 ? 180 : 0
|
false
|
||||||
), 360);
|
> Ox.containsArea(Ox.test.areas[2], Ox.test.areas[3])
|
||||||
};
|
true
|
||||||
|
@*/
|
||||||
/*@
|
// FIXME: Shouldn't this be rewritten as a test
|
||||||
Ox.getBearing <f> Returns the bearing from one point to another
|
// if the intersection is equal to the inner area?
|
||||||
> Ox.getBearing({lat: -45, lng: 0}, {lat: 45, lng: 0})
|
export function containsArea(areaA, areaB) {
|
||||||
0
|
// If an area crosses the dateline,
|
||||||
> Ox.getBearing({lat: 0, lng: -90}, {lat: 0, lng: 90})
|
// we split it into two parts,
|
||||||
90
|
// west and east of the dateline
|
||||||
@*/
|
var areas = [areaA, areaB].map(splitArea), ret;
|
||||||
Ox.getBearing = function(pointA, pointB) {
|
function contains(areaA, areaB) {
|
||||||
pointA = rad(pointA);
|
return areaA.sw.lat <= areaB.sw.lat
|
||||||
pointB = rad(pointB);
|
&& areaA.sw.lng <= areaB.sw.lng
|
||||||
var x = Math.cos(pointA.lat) * Math.sin(pointB.lat)
|
&& areaA.ne.lat >= areaB.ne.lat
|
||||||
- Math.sin(pointA.lat) * Math.cos(pointB.lat)
|
&& areaA.ne.lng >= areaB.ne.lng;
|
||||||
* Math.cos(pointB.lng - pointA.lng),
|
}
|
||||||
y = Math.sin(pointB.lng - pointA.lng)
|
// For each part of the inner area, test if it
|
||||||
* Math.cos(pointB.lat);
|
// is contained in any part of the outer area
|
||||||
return (Ox.deg(Math.atan2(y, x)) + 360) % 360;
|
Ox.forEach(areas[1], function(area1) {
|
||||||
};
|
Ox.forEach(areas[0], function(area0) {
|
||||||
|
ret = contains(area0, area1);
|
||||||
// FIXME: name, docs
|
// Break if the outer part contains the inner part
|
||||||
Ox.getBearingDifference = function(bearingA, bearingB) {
|
return !ret;
|
||||||
var difference = Math.abs(bearingA - bearingB);
|
|
||||||
return difference > 180 ? 360 - difference : difference;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*@
|
|
||||||
Ox.getCenter <f> Returns the center of a recangle on a spehre
|
|
||||||
> Ox.getCenter({lat: -45, lng: -90}, {lat: 45, lng: 90})
|
|
||||||
{lat: 0, lng: 0}
|
|
||||||
@*/
|
|
||||||
Ox.getCenter = function(pointA, pointB) {
|
|
||||||
pointA = rad(pointA);
|
|
||||||
pointB = rad(pointB);
|
|
||||||
var x = Math.cos(pointB.lat)
|
|
||||||
* Math.cos(pointB.lng - pointA.lng),
|
|
||||||
y = Math.cos(pointB.lat)
|
|
||||||
* Math.sin(pointB.lng - pointA.lng),
|
|
||||||
d = Math.sqrt(
|
|
||||||
Math.pow(Math.cos(pointA.lat) + x, 2) + Math.pow(y, 2)
|
|
||||||
),
|
|
||||||
lat = Math.atan2(Math.sin(pointA.lat) + Math.sin(pointB.lat), d),
|
|
||||||
lng = pointA.lng + Math.atan2(y, Math.cos(pointA.lat) + x);
|
|
||||||
return deg({lat: lat, lng: lng});
|
|
||||||
};
|
|
||||||
|
|
||||||
/*@
|
|
||||||
Ox.getCircle <f> Returns points on a circle around a given point
|
|
||||||
(center, radius, precision) -> <a> Points
|
|
||||||
center <o> Center point ({lat, lng})
|
|
||||||
radius <n> Radius in meters
|
|
||||||
precision <n> Precision (the circle will have 2^precision segments)
|
|
||||||
@*/
|
|
||||||
Ox.getCircle = function(center, radius, precision) {
|
|
||||||
return Ox.range(
|
|
||||||
0, 360, 360 / Math.pow(2, precision)
|
|
||||||
).map(function(bearing) {
|
|
||||||
return Ox.getPoint(center, radius, bearing);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// FIXME: name, docs
|
|
||||||
Ox.getClosestBearing = function(bearing, bearings) {
|
|
||||||
var differences = bearings.map(function(bearing_) {
|
|
||||||
return getBearingDifference(bearing, bearing_);
|
|
||||||
});
|
|
||||||
return bearings[differences.indexOf(Ox.min(differences))];
|
|
||||||
};
|
|
||||||
|
|
||||||
/*@
|
|
||||||
Ox.getDegreesPerMeter <f> Returns degrees per meter at a given latitude
|
|
||||||
> 360 / Ox.getDegreesPerMeter(0)
|
|
||||||
Ox.EARTH_CIRCUMFERENCE
|
|
||||||
@*/
|
|
||||||
Ox.getDegreesPerMeter = function(lat) {
|
|
||||||
return 360 / Ox.EARTH_CIRCUMFERENCE / Math.cos(lat * Math.PI / 180);
|
|
||||||
};
|
|
||||||
|
|
||||||
/*@
|
|
||||||
Ox.getDistance <f> Returns the distance in meters between two points
|
|
||||||
> Ox.getDistance({lat: -45, lng: -90}, {lat: 45, lng: 90}) * 2
|
|
||||||
Ox.EARTH_CIRCUMFERENCE
|
|
||||||
@*/
|
|
||||||
Ox.getDistance = function(pointA, pointB) {
|
|
||||||
pointA = rad(pointA);
|
|
||||||
pointB = rad(pointB);
|
|
||||||
return Math.acos(
|
|
||||||
Math.sin(pointA.lat) * Math.sin(pointB.lat)
|
|
||||||
+ Math.cos(pointA.lat) * Math.cos(pointB.lat)
|
|
||||||
* Math.cos(pointB.lng - pointA.lng)
|
|
||||||
) * Ox.EARTH_RADIUS;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*@
|
|
||||||
Ox.getLatLngByXY <f> Returns lat/lng for a given x/y on a 1x1 mercator projection
|
|
||||||
> Ox.getLatLngByXY({x: 0.5, y: 0.5})
|
|
||||||
{lat: -0, lng: 0}
|
|
||||||
@*/
|
|
||||||
Ox.getLatLngByXY = function(xy) {
|
|
||||||
function getValue(value) {
|
|
||||||
return (value - 0.5) * 2 * Math.PI;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
lat: -Ox.deg(Math.atan(Ox.sinh(getValue(xy.y)))),
|
|
||||||
lng: Ox.deg(getValue(xy.x))
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/*@
|
|
||||||
Ox.getLine <f> Returns points on a line between two points
|
|
||||||
(pointA, pointB, precision) -> <a> Points
|
|
||||||
pointA <o> Start point ({lat, lng})
|
|
||||||
pointB <o> End point ({lat, lng})
|
|
||||||
precision <n> Precision (the line will have 2^precision segments)
|
|
||||||
@*/
|
|
||||||
Ox.getLine = function(pointA, pointB, precision) {
|
|
||||||
var line = [pointA, pointB], points;
|
|
||||||
while (precision > 0) {
|
|
||||||
points = [line[0]];
|
|
||||||
Ox.loop(line.length - 1, function(i) {
|
|
||||||
points.push(
|
|
||||||
Ox.getCenter(line[i], line[i + 1]),
|
|
||||||
line[i + 1]
|
|
||||||
);
|
|
||||||
});
|
|
||||||
line = points;
|
|
||||||
precision--;
|
|
||||||
}
|
|
||||||
return line;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*@
|
|
||||||
Ox.getMetersPerDegree <f> Returns meters per degree at a given latitude
|
|
||||||
> Ox.getMetersPerDegree(0) * 360
|
|
||||||
Ox.EARTH_CIRCUMFERENCE
|
|
||||||
@*/
|
|
||||||
Ox.getMetersPerDegree = function(lat) {
|
|
||||||
return Math.cos(lat * Math.PI / 180) * Ox.EARTH_CIRCUMFERENCE / 360;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*@
|
|
||||||
Ox.getPoint <f> Returns a point at a given distance/bearing from a given point
|
|
||||||
> Ox.getPoint({lat: -45, lng: 0}, Ox.EARTH_CIRCUMFERENCE / 4, 0)
|
|
||||||
{lat: 45, lng: 0}
|
|
||||||
@*/
|
|
||||||
Ox.getPoint = function(point, distance, bearing) {
|
|
||||||
var pointB = {};
|
|
||||||
point = rad(point);
|
|
||||||
distance /= Ox.EARTH_RADIUS;
|
|
||||||
bearing = Ox.rad(bearing);
|
|
||||||
pointB.lat = Math.asin(
|
|
||||||
Math.sin(point.lat) * Math.cos(distance)
|
|
||||||
+ Math.cos(point.lat) * Math.sin(distance) * Math.cos(bearing)
|
|
||||||
);
|
|
||||||
pointB.lng = point.lng + Math.atan2(
|
|
||||||
Math.sin(bearing) * Math.sin(distance) * Math.cos(point.lat),
|
|
||||||
Math.cos(distance) - Math.sin(point.lat) * Math.sin(pointB.lat)
|
|
||||||
);
|
|
||||||
return deg(pointB);
|
|
||||||
};
|
|
||||||
|
|
||||||
/*@
|
|
||||||
Ox.getXYByLatLng <f> Returns x/y on a 1x1 mercator projection for a given lat/lng
|
|
||||||
> Ox.getXYByLatLng({lat: 0, lng: 0})
|
|
||||||
{x: 0.5, y: 0.5}
|
|
||||||
@*/
|
|
||||||
Ox.getXYByLatLng = function(latlng) {
|
|
||||||
function getValue(value) {
|
|
||||||
return value / (2 * Math.PI) + 0.5;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
x: getValue(Ox.rad(latlng.lng)),
|
|
||||||
y: getValue(Ox.asinh(Math.tan(Ox.rad(-latlng.lat))))
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/*@
|
|
||||||
Ox.isPolar <f> Returns true if a given point is outside the bounds of a mercator projection
|
|
||||||
> Ox.isPolar({lat: 90, lng: 0})
|
|
||||||
true
|
|
||||||
@*/
|
|
||||||
Ox.isPolar = function(point) {
|
|
||||||
return point.lat < Ox.MIN_LATITUDE || point.lat > Ox.MAX_LATITUDE;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*@
|
|
||||||
Ox.containsArea <f> Returns true if an area contains another area
|
|
||||||
<script>
|
|
||||||
Ox.test.areas = [
|
|
||||||
{sw: {lat: -30, lng: -30}, ne: {lat: 30, lng: 30}},
|
|
||||||
{sw: {lat: -20, lng: -40}, ne: {lat: 20, lng: 40}},
|
|
||||||
{sw: {lat: -30, lng: 150}, ne: {lat: 30, lng: -150}},
|
|
||||||
{sw: {lat: 10, lng: -170}, ne: {lat: 20, lng: -160}}
|
|
||||||
];
|
|
||||||
</script>
|
|
||||||
> Ox.containsArea(Ox.test.areas[0], Ox.test.areas[1])
|
|
||||||
false
|
|
||||||
> Ox.containsArea(Ox.test.areas[2], Ox.test.areas[3])
|
|
||||||
true
|
|
||||||
@*/
|
|
||||||
// FIXME: Shouldn't this be rewritten as a test
|
|
||||||
// if the intersection is equal to the inner area?
|
|
||||||
Ox.containsArea = function(areaA, areaB) {
|
|
||||||
// If an area crosses the dateline,
|
|
||||||
// we split it into two parts,
|
|
||||||
// west and east of the dateline
|
|
||||||
var areas = [areaA, areaB].map(splitArea), ret;
|
|
||||||
function contains(areaA, areaB) {
|
|
||||||
return areaA.sw.lat <= areaB.sw.lat
|
|
||||||
&& areaA.sw.lng <= areaB.sw.lng
|
|
||||||
&& areaA.ne.lat >= areaB.ne.lat
|
|
||||||
&& areaA.ne.lng >= areaB.ne.lng;
|
|
||||||
}
|
|
||||||
// For each part of the inner area, test if it
|
|
||||||
// is contained in any part of the outer area
|
|
||||||
Ox.forEach(areas[1], function(area1) {
|
|
||||||
Ox.forEach(areas[0], function(area0) {
|
|
||||||
ret = contains(area0, area1);
|
|
||||||
// Break if the outer part contains the inner part
|
|
||||||
return !ret;
|
|
||||||
});
|
|
||||||
// Break if no outer part contains the inner part
|
|
||||||
return ret;
|
|
||||||
});
|
});
|
||||||
|
// Break if no outer part contains the inner part
|
||||||
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}},
|
||||||
{sw: {lat: 0, lng: 0}, ne: {lat: 10, lng: 10}},
|
{sw: {lat: 0, lng: 0}, ne: {lat: 10, lng: 10}},
|
||||||
{sw: {lat: -30, lng: 150}, ne: {lat: 30, lng: -150}},
|
{sw: {lat: -30, lng: 150}, ne: {lat: 30, lng: -150}},
|
||||||
{sw: {lat: 25, lng: -155}, ne: {lat: 35, lng: -145}}
|
{sw: {lat: 25, lng: -155}, ne: {lat: 35, lng: -145}}
|
||||||
];
|
];
|
||||||
</script>
|
</script>
|
||||||
> Ox.intersectAreas([Ox.test.areas[0], Ox.test.areas[1]])
|
> Ox.intersectAreas([Ox.test.areas[0], Ox.test.areas[1]])
|
||||||
{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,
|
||||||
// west and east of the dateline
|
// west and east of the dateline
|
||||||
areas = areas.map(splitArea);
|
areas = areas.map(splitArea);
|
||||||
ret = areas[0];
|
ret = areas[0];
|
||||||
function intersect(areaA, areaB) {
|
function intersect(areaA, areaB) {
|
||||||
return areaA.sw.lat > areaB.ne.lat
|
return areaA.sw.lat > areaB.ne.lat
|
||||||
|| areaA.sw.lng > areaB.ne.lng
|
|| areaA.sw.lng > areaB.ne.lng
|
||||||
|| areaA.ne.lat < areaB.sw.lat
|
|| areaA.ne.lat < areaB.sw.lat
|
||||||
|| areaA.ne.lng < areaB.sw.lng
|
|| areaA.ne.lng < areaB.sw.lng
|
||||||
? null : {
|
? null : {
|
||||||
sw: {
|
sw: {
|
||||||
lat: Math.max(areaA.sw.lat, areaB.sw.lat),
|
lat: Math.max(areaA.sw.lat, areaB.sw.lat),
|
||||||
lng: Math.max(areaA.sw.lng, areaB.sw.lng)
|
lng: Math.max(areaA.sw.lng, areaB.sw.lng)
|
||||||
},
|
},
|
||||||
ne: {
|
ne: {
|
||||||
lat: Math.min(areaA.ne.lat, areaB.ne.lat),
|
lat: Math.min(areaA.ne.lat, areaB.ne.lat),
|
||||||
lng: Math.min(areaA.ne.lng, areaB.ne.lng)
|
lng: Math.min(areaA.ne.lng, areaB.ne.lng)
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
Ox.forEach(areas.slice(1), function(parts) {
|
|
||||||
if (ret.length == 1 && parts.length == 1) {
|
|
||||||
ret = intersect(ret[0], parts[0]);
|
|
||||||
} else {
|
|
||||||
// intersect each part of the intersection
|
|
||||||
// with all parts of the next area
|
|
||||||
intersections = Ox.compact(ret.map(function(part) {
|
|
||||||
return Ox.intersectAreas(parts.concat(part));
|
|
||||||
}));
|
|
||||||
ret = intersections.length == 0 ? null
|
|
||||||
: Ox.joinAreas(intersections);
|
|
||||||
}
|
}
|
||||||
if (ret === null) {
|
};
|
||||||
return false; // break
|
}
|
||||||
} else {
|
Ox.forEach(areas.slice(1), function(parts) {
|
||||||
ret = splitArea(ret);
|
if (ret.length == 1 && parts.length == 1) {
|
||||||
}
|
ret = intersect(ret[0], parts[0]);
|
||||||
});
|
|
||||||
return ret ? Ox.joinAreas(ret) : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*@
|
|
||||||
Ox.joinAreas <f> Joins an array of areas
|
|
||||||
<script>
|
|
||||||
Ox.test.areas = [
|
|
||||||
{sw: {lat: -30, lng: 150}, ne: {lat: -20, lng: 160}},
|
|
||||||
{sw: {lat: -10, lng: 170}, ne: {lat: 10, lng: -170}},
|
|
||||||
{sw: {lat: 20, lng: -160}, ne: {lat: 30, lng: -150}}
|
|
||||||
];
|
|
||||||
</script>
|
|
||||||
> Ox.joinAreas(Ox.test.areas)
|
|
||||||
{sw: {lat: -30, lng: 150}, ne: {lat: 30, lng: -150}}
|
|
||||||
@*/
|
|
||||||
Ox.joinAreas = function(areas) {
|
|
||||||
// While the combined latitude is trivial (min to max), the combined longitude
|
|
||||||
// spans from the eastern to the western edge of the largest gap between areas
|
|
||||||
var ret = areas[0],
|
|
||||||
gaps = [{
|
|
||||||
sw: {lat: -90, lng: ret.ne.lng},
|
|
||||||
ne: {lat: 90, lng: ret.sw.lng}
|
|
||||||
}];
|
|
||||||
function containsGaps(area) {
|
|
||||||
return Ox.getIndices(gaps, function(gap) {
|
|
||||||
return Ox.containsArea({
|
|
||||||
sw: {lat: -90, lng: area.sw.lng},
|
|
||||||
ne: {lat: 90, lng: area.ne.lng}
|
|
||||||
}, gap);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
function intersectsWithGaps(area) {
|
|
||||||
var ret = {};
|
|
||||||
gaps.forEach(function(gap, i) {
|
|
||||||
var intersection = Ox.intersectAreas([area, gap]);
|
|
||||||
if (intersection) {
|
|
||||||
ret[i] = intersection;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
function isContainedInGap(area) {
|
|
||||||
var ret = -1;
|
|
||||||
Ox.forEach(gaps, function(gap, i) {
|
|
||||||
if (Ox.containsArea(gap, area)) {
|
|
||||||
ret = i;
|
|
||||||
return false; // break
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
areas.slice(1).forEach(function(area) {
|
|
||||||
var index, indices, intersections;
|
|
||||||
if (area.sw.lat < ret.sw.lat) {
|
|
||||||
ret.sw.lat = area.sw.lat;
|
|
||||||
}
|
|
||||||
if (area.ne.lat > ret.ne.lat) {
|
|
||||||
ret.ne.lat = area.ne.lat;
|
|
||||||
}
|
|
||||||
// If the area is contained in a gap, split the gap in two
|
|
||||||
index = isContainedInGap(area);
|
|
||||||
if (index > -1) {
|
|
||||||
gaps.push({
|
|
||||||
sw: gaps[index].sw,
|
|
||||||
ne: {lat: 90, lng: area.sw.lng}
|
|
||||||
});
|
|
||||||
gaps.push({
|
|
||||||
sw: {lat: -90, lng: area.ne.lng},
|
|
||||||
ne: gaps[index].ne
|
|
||||||
});
|
|
||||||
gaps.splice(index, 1);
|
|
||||||
} else {
|
|
||||||
// If the area contains gaps, remove them
|
|
||||||
indices = containsGaps(area);
|
|
||||||
Ox.reverse(indices).forEach(function(index) {
|
|
||||||
gaps.splice(index, 1);
|
|
||||||
});
|
|
||||||
// If the area intersects with gaps, shrink them
|
|
||||||
intersections = intersectsWithGaps(area);
|
|
||||||
Ox.forEach(intersections, function(intersection, index) {
|
|
||||||
gaps[index] = {
|
|
||||||
sw: {
|
|
||||||
lat: -90,
|
|
||||||
lng: gaps[index].sw.lng == intersection.sw.lng
|
|
||||||
? intersection.ne.lng : gaps[index].sw.lng
|
|
||||||
},
|
|
||||||
ne: {
|
|
||||||
lat: 90,
|
|
||||||
lng: gaps[index].ne.lng == intersection.ne.lng
|
|
||||||
? intersection.sw.lng : gaps[index].ne.lng
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (gaps.length == 0) {
|
|
||||||
ret.sw.lng = -180;
|
|
||||||
ret.ne.lng = 180;
|
|
||||||
} else {
|
} else {
|
||||||
gaps.sort(function(a, b) {
|
// intersect each part of the intersection
|
||||||
return (
|
// with all parts of the next area
|
||||||
b.ne.lng
|
intersections = Ox.compact(ret.map(function(part) {
|
||||||
+ (Ox.crossesDateline(b.sw, b.ne) ? 360 : 0)
|
return Ox.intersectAreas(parts.concat(part));
|
||||||
- b.sw.lng
|
}));
|
||||||
) - (
|
ret = intersections.length == 0 ? null
|
||||||
a.ne.lng
|
: Ox.joinAreas(intersections);
|
||||||
+ (Ox.crossesDateline(a.sw, a.ne) ? 360 : 0)
|
|
||||||
- a.sw.lng
|
|
||||||
);
|
|
||||||
});
|
|
||||||
ret.sw.lng = gaps[0].ne.lng;
|
|
||||||
ret.ne.lng = gaps[0].sw.lng;
|
|
||||||
}
|
}
|
||||||
|
if (ret === null) {
|
||||||
|
return false; // break
|
||||||
|
} else {
|
||||||
|
ret = splitArea(ret);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return ret ? Ox.joinAreas(ret) : null;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*@
|
||||||
|
Ox.joinAreas <f> Joins an array of areas
|
||||||
|
<script>
|
||||||
|
Ox.test.areas = [
|
||||||
|
{sw: {lat: -30, lng: 150}, ne: {lat: -20, lng: 160}},
|
||||||
|
{sw: {lat: -10, lng: 170}, ne: {lat: 10, lng: -170}},
|
||||||
|
{sw: {lat: 20, lng: -160}, ne: {lat: 30, lng: -150}}
|
||||||
|
];
|
||||||
|
</script>
|
||||||
|
> Ox.joinAreas(Ox.test.areas)
|
||||||
|
{sw: {lat: -30, lng: 150}, ne: {lat: 30, lng: -150}}
|
||||||
|
@*/
|
||||||
|
export function joinAreas(areas) {
|
||||||
|
// While the combined latitude is trivial (min to max), the combined longitude
|
||||||
|
// spans from the eastern to the western edge of the largest gap between areas
|
||||||
|
var ret = areas[0],
|
||||||
|
gaps = [{
|
||||||
|
sw: {lat: -90, lng: ret.ne.lng},
|
||||||
|
ne: {lat: 90, lng: ret.sw.lng}
|
||||||
|
}];
|
||||||
|
function containsGaps(area) {
|
||||||
|
return Ox.getIndices(gaps, function(gap) {
|
||||||
|
return Ox.containsArea({
|
||||||
|
sw: {lat: -90, lng: area.sw.lng},
|
||||||
|
ne: {lat: 90, lng: area.ne.lng}
|
||||||
|
}, gap);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function intersectsWithGaps(area) {
|
||||||
|
var ret = {};
|
||||||
|
gaps.forEach(function(gap, i) {
|
||||||
|
var intersection = Ox.intersectAreas([area, gap]);
|
||||||
|
if (intersection) {
|
||||||
|
ret[i] = intersection;
|
||||||
|
}
|
||||||
|
});
|
||||||
return ret;
|
return ret;
|
||||||
};
|
}
|
||||||
|
function isContainedInGap(area) {
|
||||||
}());
|
var ret = -1;
|
||||||
|
Ox.forEach(gaps, function(gap, i) {
|
||||||
|
if (Ox.containsArea(gap, area)) {
|
||||||
|
ret = i;
|
||||||
|
return false; // break
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
areas.slice(1).forEach(function(area) {
|
||||||
|
var index, indices, intersections;
|
||||||
|
if (area.sw.lat < ret.sw.lat) {
|
||||||
|
ret.sw.lat = area.sw.lat;
|
||||||
|
}
|
||||||
|
if (area.ne.lat > ret.ne.lat) {
|
||||||
|
ret.ne.lat = area.ne.lat;
|
||||||
|
}
|
||||||
|
// If the area is contained in a gap, split the gap in two
|
||||||
|
index = isContainedInGap(area);
|
||||||
|
if (index > -1) {
|
||||||
|
gaps.push({
|
||||||
|
sw: gaps[index].sw,
|
||||||
|
ne: {lat: 90, lng: area.sw.lng}
|
||||||
|
});
|
||||||
|
gaps.push({
|
||||||
|
sw: {lat: -90, lng: area.ne.lng},
|
||||||
|
ne: gaps[index].ne
|
||||||
|
});
|
||||||
|
gaps.splice(index, 1);
|
||||||
|
} else {
|
||||||
|
// If the area contains gaps, remove them
|
||||||
|
indices = containsGaps(area);
|
||||||
|
Ox.reverse(indices).forEach(function(index) {
|
||||||
|
gaps.splice(index, 1);
|
||||||
|
});
|
||||||
|
// If the area intersects with gaps, shrink them
|
||||||
|
intersections = intersectsWithGaps(area);
|
||||||
|
Ox.forEach(intersections, function(intersection, index) {
|
||||||
|
gaps[index] = {
|
||||||
|
sw: {
|
||||||
|
lat: -90,
|
||||||
|
lng: gaps[index].sw.lng == intersection.sw.lng
|
||||||
|
? intersection.ne.lng : gaps[index].sw.lng
|
||||||
|
},
|
||||||
|
ne: {
|
||||||
|
lat: 90,
|
||||||
|
lng: gaps[index].ne.lng == intersection.ne.lng
|
||||||
|
? intersection.sw.lng : gaps[index].ne.lng
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (gaps.length == 0) {
|
||||||
|
ret.sw.lng = -180;
|
||||||
|
ret.ne.lng = 180;
|
||||||
|
} else {
|
||||||
|
gaps.sort(function(a, b) {
|
||||||
|
return (
|
||||||
|
b.ne.lng
|
||||||
|
+ (Ox.crossesDateline(b.sw, b.ne) ? 360 : 0)
|
||||||
|
- b.sw.lng
|
||||||
|
) - (
|
||||||
|
a.ne.lng
|
||||||
|
+ (Ox.crossesDateline(a.sw, a.ne) ? 360 : 0)
|
||||||
|
- a.sw.lng
|
||||||
|
);
|
||||||
|
});
|
||||||
|
ret.sw.lng = gaps[0].ne.lng;
|
||||||
|
ret.ne.lng = gaps[0].sw.lng;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
|
||||||
1322
source/Ox/js/HTML.js
1322
source/Ox/js/HTML.js
File diff suppressed because it is too large
Load diff
|
|
@ -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));
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -1,90 +1,103 @@
|
||||||
'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
|
|
||||||
() -> <s> Locale (like 'de' or 'fr')
|
|
||||||
@*/
|
|
||||||
Ox.getLocale = function() {
|
|
||||||
return Ox.LOCALE;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*@
|
var log, translations = {};
|
||||||
Ox.setLocale <f> Sets locale
|
|
||||||
(locale[, url], callback)
|
/*@
|
||||||
locale <s> Locale (like 'de' or 'fr')
|
Ox.getLocale <f> Returns locale
|
||||||
url <s|[s]> one or more URLs of JSON file with additional translations
|
() -> <s> Locale (like 'de' or 'fr')
|
||||||
callback <f> Callback function
|
@*/
|
||||||
success <b> If true, locale has been set
|
export function getLocale() {
|
||||||
@*/
|
return Ox.LOCALE;
|
||||||
Ox.setLocale = function(locale, url, callback) {
|
};
|
||||||
var isValidLocale = Ox.contains(Object.keys(Ox.LOCALE_NAMES), locale),
|
|
||||||
urls = [];
|
/*@
|
||||||
if (arguments.length == 2) {
|
Ox.setLocale <f> Sets locale
|
||||||
callback = arguments[1];
|
(locale[, url], callback)
|
||||||
url = null;
|
locale <s> Locale (like 'de' or 'fr')
|
||||||
}
|
url <s|[s]> one or more URLs of JSON file with additional translations
|
||||||
if (isValidLocale) {
|
callback <f> Callback function
|
||||||
Ox.LOCALE = locale;
|
success <b> If true, locale has been set
|
||||||
if (locale == 'en') {
|
@*/
|
||||||
translations = {};
|
export function setLocale(locale, url, callback) {
|
||||||
} else {
|
var isValidLocale = Ox.contains(Object.keys(Ox.LOCALE_NAMES), locale),
|
||||||
translations = {};
|
urls = [];
|
||||||
Ox.forEach(Ox.LOCALES, function(locales, module) {
|
if (arguments.length == 2) {
|
||||||
if (
|
callback = arguments[1];
|
||||||
(module == 'Ox' || Ox.load[module])
|
url = null;
|
||||||
&& Ox.contains(locales, locale)
|
}
|
||||||
) {
|
if (isValidLocale) {
|
||||||
urls.push([
|
Ox.LOCALE = locale;
|
||||||
Ox.PATH + module + '/json/locale.'
|
if (locale == 'en') {
|
||||||
+ locale + '.json'
|
translations = {};
|
||||||
]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
url && Ox.makeArray(url).forEach(function(value) {
|
|
||||||
urls.push(Ox.makeArray(value));
|
|
||||||
});
|
|
||||||
if (urls.length) {
|
|
||||||
Ox.getJSON(urls, function(data) {
|
|
||||||
Ox.forEach(data, function(values, url) {
|
|
||||||
Ox.extend(translations, values);
|
|
||||||
});
|
|
||||||
callback(true);
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
callback(true);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
callback(false);
|
translations = {};
|
||||||
|
Ox.forEach(Ox.LOCALES, function(locales, module) {
|
||||||
|
if (
|
||||||
|
(module == 'Ox' || Ox.load[module])
|
||||||
|
&& Ox.contains(locales, locale)
|
||||||
|
) {
|
||||||
|
urls.push([
|
||||||
|
Ox.PATH + module + '/json/locale.'
|
||||||
|
+ locale + '.json'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
url && Ox.makeArray(url).forEach(function(value) {
|
||||||
|
urls.push(Ox.makeArray(value));
|
||||||
|
});
|
||||||
|
if (urls.length) {
|
||||||
|
Ox.getJSON(urls, function(data) {
|
||||||
|
Ox.forEach(data, function(values, url) {
|
||||||
|
Ox.extend(translations, values);
|
||||||
|
});
|
||||||
|
callback(true);
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
callback(true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
})();
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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));
|
|
||||||
|
|
|
||||||
|
|
@ -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');
|
||||||
};
|
};
|
||||||
|
|
@ -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,142 +105,139 @@ 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) {
|
||||||
type = Ox.parseURL(url).pathname.split('.').pop();
|
type = Ox.parseURL(url).pathname.split('.').pop();
|
||||||
type = type == 'css' ? 'stylesheet'
|
type = type == 'css' ? 'stylesheet'
|
||||||
: type == 'js' ? 'script' : 'image';
|
: type == 'js' ? 'script' : 'image';
|
||||||
}
|
}
|
||||||
if (type == 'image') {
|
if (type == 'image') {
|
||||||
element = new Image();
|
element = new Image();
|
||||||
element.onerror = onError;
|
element.onerror = onError;
|
||||||
element.onload = onLoad;
|
element.onload = onLoad;
|
||||||
element.src = url;
|
element.src = url;
|
||||||
} else {
|
|
||||||
tagValue = type == 'script' ? 'script' : 'link';
|
|
||||||
typeValue = type == 'script' ? 'text/javascript' : 'text/css';
|
|
||||||
urlKey = type == 'script' ? 'src' : 'href';
|
|
||||||
if (Ox.some(
|
|
||||||
document.getElementsByTagName(tagValue),
|
|
||||||
function(element) {
|
|
||||||
return element[urlKey] == url;
|
|
||||||
}
|
|
||||||
)) {
|
|
||||||
onLoad();
|
|
||||||
} else {
|
|
||||||
element = document.createElement(tagValue);
|
|
||||||
element.onerror = onError;
|
|
||||||
element.onload = element.onreadystatechange = onLoad;
|
|
||||||
element.type = typeValue;
|
|
||||||
element[urlKey] = url;
|
|
||||||
if (type == 'stylesheet') {
|
|
||||||
element.rel = 'stylesheet';
|
|
||||||
}
|
|
||||||
head.appendChild(element);
|
|
||||||
}
|
|
||||||
if (type == 'stylesheet') {
|
|
||||||
//fixme only call if browser does not support onload
|
|
||||||
// Safari 5 does not fire onload
|
|
||||||
waitForCSS();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
|
tagValue = type == 'script' ? 'script' : 'link';
|
||||||
|
typeValue = type == 'script' ? 'text/javascript' : 'text/css';
|
||||||
|
urlKey = type == 'script' ? 'src' : 'href';
|
||||||
|
if (Ox.some(
|
||||||
|
document.getElementsByTagName(tagValue),
|
||||||
|
function(element) {
|
||||||
|
return element[urlKey] == url;
|
||||||
|
}
|
||||||
|
)) {
|
||||||
|
onLoad();
|
||||||
|
} else {
|
||||||
|
element = document.createElement(tagValue);
|
||||||
|
element.onerror = onError;
|
||||||
|
element.onload = element.onreadystatechange = onLoad;
|
||||||
|
element.type = typeValue;
|
||||||
|
element[urlKey] = url;
|
||||||
|
if (type == 'stylesheet') {
|
||||||
|
element.rel = 'stylesheet';
|
||||||
|
}
|
||||||
|
head.appendChild(element);
|
||||||
|
}
|
||||||
|
if (type == 'stylesheet') {
|
||||||
|
//fixme only call if browser does not support onload
|
||||||
|
// Safari 5 does not fire onload
|
||||||
|
waitForCSS();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
callback(cache[url], null);
|
||||||
|
}
|
||||||
|
function onError() {
|
||||||
|
callback(null, {code: 404, text: 'Not Found'});
|
||||||
|
}
|
||||||
|
function onLoad() {
|
||||||
|
if (
|
||||||
|
!this || !this.readyState
|
||||||
|
|| this.readyState == 'loaded' || this.readyState == 'complete'
|
||||||
|
) {
|
||||||
|
// for an image, keep a reference to the element
|
||||||
|
// to keep the image in the browser cache
|
||||||
|
cache[url] = type == 'image' ? this : true;
|
||||||
callback(cache[url], null);
|
callback(cache[url], null);
|
||||||
}
|
}
|
||||||
function onError() {
|
|
||||||
callback(null, {code: 404, text: 'Not Found'});
|
|
||||||
}
|
|
||||||
function onLoad() {
|
|
||||||
if (
|
|
||||||
!this || !this.readyState
|
|
||||||
|| this.readyState == 'loaded' || this.readyState == 'complete'
|
|
||||||
) {
|
|
||||||
// for an image, keep a reference to the element
|
|
||||||
// to keep the image in the browser cache
|
|
||||||
cache[url] = type == 'image' ? this : true;
|
|
||||||
callback(cache[url], null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function waitForCSS() {
|
|
||||||
var error = false;
|
|
||||||
try {
|
|
||||||
element.sheet.cssRule;
|
|
||||||
} catch (e) {
|
|
||||||
error = true;
|
|
||||||
setTimeout(function() {
|
|
||||||
waitForCSS();
|
|
||||||
}, 25);
|
|
||||||
}
|
|
||||||
!error && onLoad();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
function waitForCSS() {
|
||||||
function getFiles(type, urls, callback) {
|
var error = false;
|
||||||
Ox.getAsync(urls, function(url, callback) {
|
try {
|
||||||
getFile(type, url, callback);
|
element.sheet.cssRule;
|
||||||
}, callback);
|
} catch (e) {
|
||||||
|
error = true;
|
||||||
|
setTimeout(function() {
|
||||||
|
waitForCSS();
|
||||||
|
}, 25);
|
||||||
|
}
|
||||||
|
!error && onLoad();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*@
|
function getFiles(type, urls, callback) {
|
||||||
Ox.getFile <f> Loads a file (image, script or stylesheet)
|
getAsync(urls, function(url, callback) {
|
||||||
(file, callback) -> <u> undefined
|
_getFile(type, url, callback);
|
||||||
file <s|[s]> Local path or remote URL, or array of those, or array of such arrays
|
}, callback);
|
||||||
Multiple files in the same array will be processed simultaneously,
|
}
|
||||||
but multiple arrays of files will be processed in that order.
|
|
||||||
callback <f> Callback function
|
|
||||||
image <h> DOM element (if the file is an image)
|
|
||||||
@*/
|
|
||||||
Ox.getFile = function(url, callback) {
|
|
||||||
getFiles(null, url, callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
/*@
|
/*@
|
||||||
Ox.getImage <f> Loads an image
|
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
|
image <h> DOM element (if the file is an image)
|
||||||
@*/
|
@*/
|
||||||
Ox.getImage = function(url, callback) {
|
export function getFile(url, callback) {
|
||||||
getFiles('image', url, callback);
|
getFiles(null, url, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*@
|
/*@
|
||||||
Ox.getScript <f> Loads a script
|
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
|
||||||
Ox.getScript = function(url, callback) {
|
@*/
|
||||||
getFiles('script', url, callback);
|
export function getImage(url, callback) {
|
||||||
};
|
getFiles('image', url, callback);
|
||||||
|
};
|
||||||
|
|
||||||
/*@
|
/*@
|
||||||
Ox.getStylesheet <f> Loads a stylesheet
|
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.getStylesheet = function(url, callback) {
|
export function getScript(url, callback) {
|
||||||
getFiles('stylesheet', url, callback);
|
getFiles('script', url, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
}());
|
/*@
|
||||||
|
Ox.getStylesheet <f> Loads a stylesheet
|
||||||
|
(file, callback) -> <u> undefined
|
||||||
|
file <s|[s]> Local path or remote URL, or array of those, or array of such arrays
|
||||||
|
Multiple files in the same array will be processed simultaneously,
|
||||||
|
but multiple arrays of files will be processed in that order.
|
||||||
|
callback <f> Callback function
|
||||||
|
@*/
|
||||||
|
export function getStylesheet(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() {
|
||||||
|
|
|
||||||
|
|
@ -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,22 +276,35 @@ 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'
|
||||||
return function(string) {
|
];
|
||||||
var ret = {};
|
if (typeof document == 'undefined') {
|
||||||
a.href = string;
|
return function(string) {
|
||||||
keys.forEach(function(key) {
|
const a = new URL(string);
|
||||||
ret[key] = a[key];
|
var ret = {};
|
||||||
});
|
keys.forEach(function(key) {
|
||||||
return ret;
|
ret[key] = a[key];
|
||||||
};
|
});
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var a = document.createElement('a');
|
||||||
|
return function(string) {
|
||||||
|
var ret = {};
|
||||||
|
a.href = string;
|
||||||
|
keys.forEach(function(key) {
|
||||||
|
ret[key] = a[key];
|
||||||
|
});
|
||||||
|
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;
|
||||||
|
|
|
||||||
|
|
@ -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');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -83,8 +97,8 @@ Ox.isEmpty <f> Tests if a value is an empty array, object or string
|
||||||
true
|
true
|
||||||
> Ox.isEmpty('')
|
> Ox.isEmpty('')
|
||||||
true
|
true
|
||||||
> Ox.isEmpty(document.getElementsByTagName(''))
|
> Ox.isEmpty(document.getElementsByTagName(''))
|
||||||
true
|
true
|
||||||
> Ox.isEmpty(function() {})
|
> Ox.isEmpty(function() {})
|
||||||
false
|
false
|
||||||
> Ox.isEmpty(false)
|
> Ox.isEmpty(false)
|
||||||
|
|
@ -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';
|
||||||
|
|
|
||||||
|
|
@ -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
548
source/UI/index.js
Normal 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);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue