/** 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 ) ;
}