frontend/1/mario/toned.js
2023-05-21 21:16:27 -04:00

244 lines
7.5 KiB
JavaScript

/* toned.js */
// A mini-library I use for some short, useful functions
// Pass in true to give all the functions to window
function TonedJS(give_window) {
var toned = {
/* Object Shenanigans */
// Blindly hand all members of the donor variable to the recipient
// Ex: give(toned, window);
giveSup: function(donor, recipient) {
recipient = recipient || {};
for(var i in donor)
recipient[i] = donor[i];
return recipient
},
// Like giveSup/erior, but it doesn't override pre-existing members
giveSub: function(donor, recipient) {
recipient = recipient || {};
for(var i in donor)
if(!recipient[i])
recipient[i] = donor[i];
return recipient
},
// Proliferates all members of settings to the element recursively
proliferate: function(elem, settings, no_override) {
var setting, i;
for(i in settings) {
if(no_override && elem[i]) continue;
if(typeof(setting = settings[i]) == "object") {
if(!elem[i]) elem[i] = {};
proliferate(elem[i], setting, no_override);
}
else elem[i] = setting;
}
return elem;
},
// Blindly grabs the first key or value of the object, depending on grabkey
getFirst: function(obj, grabkey) {
for(var i in obj) return grabkey ? i : obj[i];
},
// Blindly grabs the last key or value of the object, depending on grabkey
getLast: function(obj, grabkey) {
for(var i in obj) {} return grabkey ? i : obj[i];
},
// Follows a path inside an object recursively
// Path is ["path", "to", "target"], where num is how far along the path it is
// Num must be given at start, for performance reasons
// To do: allow a function version?
followPath: function(obj, path, num) {
if(path[num] != null && obj[path[num]] != null)
return followPath(obj[path[num]], path, ++num);
return obj;
},
/* HTML Element Manipulations */
// Creates an element, and uses proliferate on all the other arguments
// * createElement() // (just returns a new div)
// * createElement("div", {width: "350px", style: {class: "Toned"}});
createElement: function(type) {
var elem = document.createElement(type || "div"),
i = arguments.length;
while(--i > 0) // because negative
proliferate(elem, arguments[i]);
return elem;
},
// Simple expressions to add/remove classes
classAdd: function(me, strin) { me.className += " " + strin; },
classRemove: function(me, strout) { me.className = me.className.replace(new RegExp(" " + strout, "gm"), ""); },
// Position changing
elementSetPosition: function(me, left, top) {
if(left == undefined) left = me.left;
if(top == undefined) top = me.top;
proliferate(me, {
left: left,
top: top,
style: {
marginLeft: left + "px",
marginTop: top + "px"
}
});
},
elementShiftLeft: function(me, left) {
if(!me.left) me.left = Number(me.style.marginLeft.replace("px", ""));
me.style.marginLeft = round(me.left += left) + "px";
},
elementShiftTop: function(me, top) {
if(!me.top) me.top = Number(me.style.marginLeft.replace("px", ""));
me.style.marginTop = round(me.top += top) + "px";
},
// Deletes an element if it's in its parent, or the body
removeChildSafe: function(child, container) {
if(!child) return;
container = container || document.body;
if(container.contains(child)) container.removeChild(child);
},
// Attempts to find the soonest parent with this tag
findParentOfType: function(child, type) {
var parent = child.parentElement;
if(!parent || parent.nodeName == type) return parent;
return findParentType(parent, type);
},
// Clears all timer events from setTimeout and setInterval
clearAllTimeouts: function() {
var id = setTimeout(function() {});
while(id--) clearTimeout(id);
},
/* String manipulations */
// Removes leading and trailing whitespace (thanks, IE<=8)
stringTrim: function(me) {
return me.replace(/^\s+|\s+$/g,'');
},
// Similar to arrayOf
stringOf: function(me, n) {
return (n == 0) ? '' : new Array(1 + (n || 1)).join(me);
},
// Checks if a haystack contains a needle
stringHas: function(haystack, needle) {
return haystack.indexOf(needle) != -1;
},
// Case insensitive version of stringHas
stringHasI: function(haystack, needle) {
return haystack.toLowerCase().indexOf(needle.toLowerCase()) != -1;
},
// Capitalizes only the first 1 or n charactacters of a string
capitalizeFirst: function(str, n) {
n = n || 1;
return str.substr(0,n).toUpperCase() + str.substr(n).toLowerCase();
},
/* Array manipulations */
// It's nice to have X-dimensional arrays
ArrayD: function(dim) {
// 1-dimensionals are easy
if(arguments.length == 1) return new Array(dim);
// Otherwise recurse
var rargs = arrayMake(arguments),
me = new Array(dim),
i;
rargs.shift();
for(i = dim - 1; i >= 0; --i) {
me[i]= ArrayD.apply(this, rargs);
}
return me;
},
// Similar to stringOf
arrayOf: function(me, n) {
n = n || 1;
var arr = new Array(n);
while(n--) arr[n] = me;
return arr;
},
// Looking at you, function arguments
arrayMake: function(me) {
return Array.prototype.slice.call(me);
},
// (7,10) = [7,8,9,10]
arrayRange: function(a, b) {
var len = 1 + b - a,
arr = new Array(len),
val = a, i = 0;
while(i < len) arr[i++] = val++;
return arr;
},
arrayShuffle: function(arr, start, end) {
start = start || 0;
end = end || arr.length;
for(var i = start, temp, sloc; i <= end; ++i) {
sloc = randInt(i+1);
temp = arr[i];
arr[i] = arr[sloc];
arr[sloc] = temp;
}
return arr;
},
// O(n^2) removal
removeDuplicates: function(arr) {
var output = [],
me, hasdup,
len, i, j;
for(i = 0, len = arr.length; i < len; ++i) {
me = arr[i];
hasdup = false;
for(j = 0; j < i; ++j) {
if(arr[j] == me) {
hasdup = true;
break;
}
}
if(!hasdup) output.push(me);
}
return output;
},
/* Number manipulations */
// Converts ('7',3,1) to '117'
makeDigit: function(num, size, fill) {
num = String(num);
return stringOf(fill || 0, max(0, size - num.length)) + num;
},
roundDigit: function(n, d) { return Number(d ? ~~(0.5 + (n / d)) * d : round(n)); },
// It's often faster to store references to common Math functions
sign: function(n) { return n ? n < 0 ? -1 : 1 : 0; },
round: function(n) { return ~~(0.5 + n); },
max: Math.max,
min: Math.min,
abs: Math.abs,
pow: Math.pow,
ceil: Math.ceil,
floor: Math.floor,
random: Math.random,
// Returns a number between [0, n)
randInt: function(n) { return floor(Math.random() * (n || 1)); },
// Positives are true, negatives are false
signBool: function(n) { return n > 0 ? true : false; },
/* Etcetera */
// It's nice being able log without going through console.. hopefully it gets optimized!
log: console.log.bind(console),
// Timing
now: Date.now
};
if(give_window) toned.giveSub(toned, window);
return toned;
}