// Skip.js
//
// Make JavaScript a little warmer, a little fuzzier.
//
// Author: Stewart Smith.
// Website: http://stewd.io
// GitHub: http://github.com/stewdio
// Twitter: http://twitter.com/stewd_io
// Copyright (C) 2013, Stewart Smith.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom
// the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
export function skipjs(){
globalThis.SKIP_JS = 20130821.1536
globalThis.forceAugment = function( type, name, data ){
var key
if( typeof name === 'string' && data ){
type.prototype[ name ] = data
}
else if( typeof name === 'object' && !data ){
for( key in name ) forceAugment( type, key, name[ key ] )
}
}
globalThis.augment = function( type, name, data ){
var key
if( typeof name === 'string' &&
type.prototype[ name ] === undefined &&
data ){
forceAugment( type, name, data )
}
else if( typeof name === 'object' && !data ){
for( key in name ) augment( type, key, name[ key ] )
}
}
globalThis.forceLearn = function( student, teacher ){
for( var p in teacher ){
if( teacher.hasOwnProperty( p )){
if( teacher[ p ].constructor === Object )
student[ p ] = forceLearn( student[ p ], teacher[ p ])
else student[ p ] = teacher[ p ]
}
}
return student
}
globalThis.learn = function( student, teacher ){
for( var p in teacher ){
if( teacher.hasOwnProperty( p ) && student[ p ] === undefined ){
if( teacher[ p ].constructor === Object )
student[ p ] = learn( student[ p ], teacher[ p ])
else student[ p ] = teacher[ p ]
}
}
return student
}
globalThis.cascade = function(){
var i, args = Array.prototype.slice.call( arguments )
for( i = 0; i < args.length; i ++ )
if( args[ i ] !== undefined ) return args[ i ]
return false
}
globalThis.coinFlip = function(){
return Math.round( Math.random() )
}
globalThis.isNumeric = function( n ){
return !isNaN( parseFloat( n )) && isFinite( n )
}
globalThis.E = Math.E
globalThis.HALF_PI = Math.PI / 2
globalThis.PI = Math.PI
globalThis.π = Math.PI
globalThis.TAU = Math.PI * 2
globalThis.SQRT2 = Math.SQRT2
globalThis.SQRT1_2 = Math.SQRT1_2
globalThis.LN2 = Math.LN2
globalThis.LN10 = Math.LN10
globalThis.LOG2E = Math.LOG2E
globalThis.LOG10E = Math.LOG10E
globalThis.SECOND = 1000
globalThis.MINUTE = SECOND * 60
globalThis.HOUR = MINUTE * 60
globalThis.DAY = HOUR * 24
globalThis.WEEK = DAY * 7
globalThis.MONTH = DAY * 30.4368499
globalThis.YEAR = DAY * 365.242199
globalThis.DECADE = YEAR * 10
globalThis.CENTURY = YEAR * 100
globalThis.now = function(){ return +Date.now() }
globalThis.MIN = Number.MIN_VALUE
globalThis.MAX = Number.MAX_VALUE
// augment( Array, {
// distanceTo : function( target ){
// var i, sum = 0
// if( arguments.length > 0 )
// target = Array.prototype.slice.call( arguments )
// if( this.length === target.length ){
// for( i = 0; i < this.length; i ++ )
// sum += Math.pow( target[i] - this[i], 2 )
// return Math.pow( sum, 0.5 )
// }
// else return null
// },
// first : function(){
// return this[ 0 ]
// },
// last : function(){
// return this[ this.length - 1 ]
// },
// maximum : function(){
// return Math.max.apply( null, this )
// },
// middle : function(){
// return this[ Math.round(( this.length - 1 ) / 2 ) ]
// },
// minimum : function(){
// return Math.min.apply( null, this )
// },
// indexOf : function( obj, fromIndex ){
// var i, j
// if( fromIndex === null )
// fromIndex = 0
// else if( fromIndex < 0 )
// fromIndex = Math.max( 0, this.length + fromIndex )
// for( i = fromIndex, j = this.length; i < j; i++ )
// if( this[i] === obj ) return i
// return -1// I'd rather return NaN, but this is more standard.
// },
// rand : function(){
// return this[ Math.floor( Math.random() * this.length )]
// },
// random : function(){// Convenience here. Exactly the same as .rand().
// return this[ Math.floor( Math.random() * this.length )]
// },
// // Ran into trouble here with Three.js. Will investigate....
// /*remove: function( from, to ){
// var rest = this.slice(( to || from ) + 1 || this.length )
// this.length = from < 0 ? this.length + from : from
// return this.push.apply( this, rest )
// },*/
// shuffle : function(){
// var
// copy = this,
// i = this.length,
// j,
// tempi,
// tempj
// if( i == 0 ) return false
// while( -- i ){
// j = Math.floor( Math.random() * ( i + 1 ))
// tempi = copy[ i ]
// tempj = copy[ j ]
// copy[ i ] = tempj
// copy[ j ] = tempi
// }
// return copy
// },
// toArray : function(){
// return this
// },
// toHtml : function(){
// var i, html = '
'
// for( i = 0; i < this.length; i ++ ){
// if( this[ i ] instanceof Array )
// html += this[ i ].toHtml()
// else
// html += '- ' + this[ i ] + '
'
// }
// html += '
'
// return html
// },
// toText : function( depth ){
// var i, indent, text
// depth = cascade( depth, 0 )
// indent = '\n' + '\t'.multiply( depth )
// text = ''
// for( i = 0; i < this.length; i ++ ){
// if( this[ i ] instanceof Array )
// text += indent + this[ i ].toText( depth + 1 )
// else
// text += indent + this[ i ]
// }
// return text
// }
// })
augment( Number, {
absolute : function(){
return Math.abs( this )
},
add : function(){
var sum = this
Array.prototype.slice.call( arguments ).forEach( function( n ){
sum += n
})
return sum
},
arcCosine : function(){
return Math.acos( this )
},
arcSine : function(){
return Math.asin( this )
},
arcTangent : function(){
return Math.atan( this )
},
constrain : function( a, b ){
var higher, lower, c = this
b = b || 0
higher = Math.max( a, b )
lower = Math.min( a, b )
c = Math.min( c, higher )
c = Math.max( c, lower )
return c
},
cosine : function(){
return Math.cos( this )
},
degreesToDirection : function(){
var d = this % 360,
directions = [ 'N', 'NNE', 'NE', 'NEE', 'E', 'SEE', 'SE', 'SSE', 'S', 'SSW', 'SW', 'SWW', 'W', 'NWW', 'NW', 'NNW', 'N' ]
return directions[ this.scale( 0, 360, 0, directions.length - 1 ).round() ]
},
degreesToRadians : function(){
return this * Math.PI / 180
},
divide : function(){
var sum = this
Array.prototype.slice.call( arguments ).forEach( function( n ){
sum /= n
})
return sum
},
isBetween : function( a, b ){
var
min = Math.min( a, b ),
max = Math.max( a, b )
return ( min <= this && this <= max )
},
lerp : function( a, b ){
return a + (b - a ) * this
},
log : function( base ){
return Math.log( this ) / ( base === undefined ? 1 : Math.log( base ))
},
log10 : function(){
// is this more pragmatic? ---> return ( '' + this.round() ).length;
return Math.log( this ) / Math.LN10
},
maximum : function( n ){
return Math.max( this, n )
},
minimum : function( n ){
return Math.min( this, n )
},
modulo : function( n ){
return (( this % n ) + n ) % n
},
multiply : function(){
var sum = this
Array.prototype.slice.call( arguments ).forEach( function( n ){
sum *= n
})
return sum
},
normalize : function( a, b ){
if( a == b ) return 1.0
return ( this - a ) / ( b - a )
},
raiseTo : function( exponent ){
return Math.pow( this, exponent )
},
radiansToDegrees : function(){
return this * 180 / Math.PI
},
rand : function( n ){
var min, max
if( n !== undefined ){
min = Math.min( this, n )
max = Math.max( this, n )
return min + Math.floor( Math.random() * ( max - min ))
}
return Math.floor( Math.random() * this )
},
random : function( n ){
var min, max
if( n !== undefined ){
min = Math.min( this, n )
max = Math.max( this, n )
return min + Math.random() * ( max - min )
}
return Math.random() * this
},
remainder : function( n ){
return this % n
},
round : function( decimals ){
var n = this
decimals = decimals || 0
n *= Math.pow( 10, decimals )
n = Math.round( n )
n /= Math.pow( 10, decimals )
return n
},
roundDown : function(){
return Math.floor( this )
},
roundUp : function(){
return Math.ceil( this )
},
scale : function( a0, a1, b0, b1 ){
var phase = this.normalize( a0, a1 )
if( b0 == b1 ) return b1
return b0 + phase * ( b1 - b0 )
},
sine : function(){
return Math.sin( this )
},
subtract : function(){
var sum = this
Array.prototype.slice.call( arguments ).forEach( function( n ){
sum -= n
})
return sum
},
tangent : function(){
return Math.tan( this )
},
toArray : function(){
return [ this.valueOf() ]
},
toNumber : function(){
return this.valueOf()
},
toPaddedString : function( digits, decimals ){
// @@
// Need to review this later.
// Mos def not bullet proof and also doesn't handle decimals.
var
i,
stringed = '' + this,
padding = ''
digits = digits || 2
decimals = decimals || 0
for( i = stringed.length; i < digits; i ++ )
padding += '0'
// so what about decimals? padding to right of decimal?
return padding + stringed
},
toSignedString : function(){
var stringed = '' + this
if( this >= 0 ) stringed = '+' + stringed
return stringed
},
toString : function(){
return ''+ this
},
// Fun with dates:
// ((2).months() + (3).weeks() + (5).days() + (9).hours() + MINUTE ).ago().toDate()
// Sat Jun 16 2012 13:03:07 GMT-0400 (EDT)
// ((2).months() + (3).weeks() + (5).days() + (9).hours() + MINUTE ).fromNow().toDate()
// Sat Dec 08 2012 00:01:23 GMT-0500 (EST)
// (2).days().ago().isBetween( (3).weeks().ago(), (2).hours().ago() )
// true
seconds : function(){
return this * SECOND
},
minutes : function(){
return this * MINUTE
},
hours : function(){
return this * HOUR
},
days : function(){
return this * DAY
},
weeks : function(){
return this * WEEK
},
months : function(){
return this * MONTH
},
years : function(){
return this * YEAR
},
decades : function(){
return this * DECADE
},
centuries : function(){
return this * CENTURY
},
ago : function(){
return +Date.now() - this
},
fromNow : function(){
return +Date.now() + this
},
toDate : function(){
return new Date( +this )
},
// Both the Unix epoch and the JavaScript epoch
// began on 01 January 1970 at 00:00:00 UTC.
// Unix counts time in SECONDS since then.
// JavaScript counts time in MILLISECONDS since then.
// Also don't forget that these below are in LOCAL timezones!
unixToYear : function(){
return ( new Date( this * 1000 )).getFullYear()
},
yearToUnix : function(){
// Pay attention: Every arg is zero-indexed
// except for the day of the month, which is one-indexed!!
return ( new Date( this, 0, 1, 0, 0, 0, 0 )).valueOf() / 1000
}
})
augment( String, {
capitalize : function(){
return this.charAt( 0 ).toUpperCase() + this.slice( 1 )//.toLowerCase()
},
invert: function(){
var
s = '',
i
for( i = 0; i < this.length; i ++ ){
if( this.charAt( i ) === this.charAt( i ).toUpperCase()) s += this.charAt( i ).toLowerCase()
else s += this.charAt( i ).toUpperCase()
}
return s
},
isEmpty : function(){
return this.length === 0 ? true : false
},
justifyCenter : function( n ){
var
thisLeftLength = Math.round( this.length / 2 ),
thisRightLength = this.length - thisLeftLength,
containerLeftLength = Math.round( n / 2 ),
containerRightLength = n - containerLeftLength,
padLeftLength = containerLeftLength - thisLeftLength,
padRightLength = containerRightLength - thisRightLength,
centered = this
if( padLeftLength > 0 ){
while( padLeftLength -- ) centered = ' ' + centered
}
else if( padLeftLength < 0 ){
centered = centered.substr( padLeftLength * -1 )
}
if( padRightLength > 0 ){
while( padRightLength -- ) centered += ' '
}
else if( padRightLength < 0 ){
centered = centered.substr( 0, centered.length + padRightLength )
}
return centered
},
justifyLeft: function( n ){
var justified = this
while( justified.length < n ) justified = justified + ' '
return justified
},
justifyRight: function( n ){
var justified = this
while( justified.length < n ) justified = ' ' + justified
return justified
},
multiply : function( n ){
var i, s = ''
n = cascade( n, 2 )
for( i = 0; i < n; i ++ ){
s += this
}
return s
},
reverse : function(){
var i, s = ''
for( i = 0; i < this.length; i ++ ){
s = this[ i ] + s
}
return s
},
size : function(){
return this.length
},
toEntities : function(){
var i, entities = ''
for( i = 0; i < this.length; i ++ ){
entities += '' + this.charCodeAt( i ) + ';'
}
return entities
},
toCamelCase : function(){
var
split = this.split( /\W+|_+/ ),
joined = split[ 0 ],
i
for( i = 1; i < split.length; i ++ )
joined += split[ i ].capitalize()
return joined
},
directionToDegrees : function(){
var
directions = [ 'N', 'NNE', 'NE', 'NEE', 'E', 'SEE', 'SE', 'SSE', 'S', 'SSW', 'SW', 'SWW', 'W', 'NWW', 'NW', 'NNW', 'N' ],
i = directions.indexOf( this.toUpperCase() )
return i >= 0 ? i.scale( 0, directions.length - 1, 0, 360 ) : Number.NaN
},
toArray : function(){
return [ this ]
},
toNumber : function(){
return parseFloat( this )
},
toString : function(){
return this
},
toUnderscoreCase : function(){
var underscored = this.replace( /[A-Z]+/g, function( $0 ){
return '_' + $0
})
if( underscored.charAt( 0 ) === '_' ) underscored = underscored.substr( 1 )
return underscored.toLowerCase()
},
toUnicode : function(){
var i, u, unicode = ''
for( i = 0; i < this.length; i ++ ){
u = this.charCodeAt( i ).toString( 16 ).toUpperCase()
while( u.length < 4 ){
u = '0' + u
}
unicode += '\\u' + u
}
return unicode
}
})
}