You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
161 lines
3.3 KiB
161 lines
3.3 KiB
/** Make a node */
|
|
function mk(e) {return document.createElement(e)}
|
|
|
|
/** Find one by query */
|
|
function qs(s) {return document.querySelector(s)}
|
|
|
|
/** Find all by query */
|
|
function qsa(s) {return document.querySelectorAll(s)}
|
|
|
|
/** Convert any to bool safely */
|
|
function bool(x) {
|
|
return (x === 1 || x === '1' || x === true || x === 'true');
|
|
}
|
|
|
|
/**
|
|
* Filter 'spacebar' and 'return' from keypress handler,
|
|
* and when they're pressed, fire the callback.
|
|
* use $(...).on('keypress', cr(handler))
|
|
*/
|
|
function cr(hdl) {
|
|
return function(e) {
|
|
if (e.which == 10 || e.which == 13 || e.which == 32) {
|
|
hdl();
|
|
}
|
|
};
|
|
}
|
|
|
|
/** Extend an objects with options */
|
|
function extend(defaults, options) {
|
|
var target = {};
|
|
|
|
Object.keys(defaults).forEach(function(k){
|
|
target[k] = defaults[k];
|
|
});
|
|
|
|
Object.keys(options).forEach(function(k){
|
|
target[k] = options[k];
|
|
});
|
|
|
|
return target;
|
|
}
|
|
|
|
/** Escape string for use as literal in RegExp */
|
|
function rgxe(str) {
|
|
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
|
|
}
|
|
|
|
/** Format number to N decimal places, output as string */
|
|
function numfmt(x, places) {
|
|
var pow = Math.pow(10, places);
|
|
return Math.round(x*pow) / pow;
|
|
}
|
|
|
|
/** Get millisecond timestamp */
|
|
function msNow() {
|
|
return +(new Date);
|
|
}
|
|
|
|
/** Get ms elapsed since msNow() */
|
|
function msElapsed(start) {
|
|
return msNow() - start;
|
|
}
|
|
|
|
/** Shim for log base 10 */
|
|
Math.log10 = Math.log10 || function(x) {
|
|
return Math.log(x) / Math.LN10;
|
|
};
|
|
|
|
/**
|
|
* Perform a substitution in the given string.
|
|
*
|
|
* Arguments - array or list of replacements.
|
|
* Arguments numeric keys will replace {0}, {1} etc.
|
|
* Named keys also work, ie. {foo: "bar"} -> replaces {foo} with bar.
|
|
*
|
|
* Braces are added to keys if missing.
|
|
*
|
|
* @returns {String} result
|
|
*/
|
|
String.prototype.format = function () {
|
|
var out = this;
|
|
var repl = arguments;
|
|
|
|
if (arguments.length == 1 && (Array.isArray(arguments[0]) || typeof arguments[0] == 'object')) {
|
|
repl = arguments[0];
|
|
}
|
|
|
|
for (var ph in repl) {
|
|
if (repl.hasOwnProperty(ph)) {
|
|
var ph_orig = ph;
|
|
|
|
if (!ph.match(/^\{.*\}$/)) {
|
|
ph = '{' + ph + '}';
|
|
}
|
|
|
|
// replace all occurrences
|
|
var pattern = new RegExp(rgxe(ph), "g");
|
|
out = out.replace(pattern, repl[ph_orig]);
|
|
}
|
|
}
|
|
|
|
return out;
|
|
};
|
|
|
|
/** HTML escape */
|
|
function e(str) {
|
|
return $.htmlEscape(str);
|
|
}
|
|
|
|
/** Check for undefined */
|
|
function undef(x) {
|
|
return typeof x == 'undefined';
|
|
}
|
|
|
|
/** Safe json parse */
|
|
function jsp(str) {
|
|
try {
|
|
return JSON.parse(str);
|
|
} catch(e) {
|
|
console.error(e);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/** Create a character from ASCII code */
|
|
function Chr(n) {
|
|
return String.fromCharCode(n);
|
|
}
|
|
|
|
/** Decode number from 2B encoding */
|
|
function parse2B(s, i=0) {
|
|
return (s.charCodeAt(i++) - 1) + (s.charCodeAt(i) - 1) * 127;
|
|
}
|
|
|
|
/** Decode number from 3B encoding */
|
|
function parse3B(s, i=0) {
|
|
return (s.charCodeAt(i) - 1) + (s.charCodeAt(i+1) - 1) * 127 + (s.charCodeAt(i+2) - 1) * 127 * 127;
|
|
}
|
|
|
|
/** Encode using 2B encoding, returns string. */
|
|
function encode2B(n) {
|
|
var lsb, msb;
|
|
lsb = (n % 127);
|
|
n = ((n - lsb) / 127);
|
|
lsb += 1;
|
|
msb = (n + 1);
|
|
return Chr(lsb) + Chr(msb);
|
|
}
|
|
|
|
/** Encode using 3B encoding, returns string. */
|
|
function encode3B(n) {
|
|
var lsb, msb, xsb;
|
|
lsb = (n % 127);
|
|
n = (n - lsb) / 127;
|
|
lsb += 1;
|
|
msb = (n % 127);
|
|
n = (n - msb) / 127;
|
|
msb += 1;
|
|
xsb = (n + 1);
|
|
return Chr(lsb) + Chr(msb) + Chr(xsb);
|
|
}
|
|
|