Last active
July 10, 2023 19:16
-
-
Save ScottKaye/9963117 to your computer and use it in GitHub Desktop.
A collection of potentially useful prototypes to make some things easier. Each of these should be crushable with http://www.iteral.com/jscrush/ . "Don't modify objects you don't own" is completely thrown out the window here in favour of coolness.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Get a range of numbers between two numbers | |
//Usage: [1, 10].range returns [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] | |
Object.defineProperty(Array.prototype, "range", { | |
get: function () { | |
var range = [this[0]], i; | |
for (var i = this[0], len = this[1]; i < len; range.push(++i)); | |
return range; | |
} | |
}); | |
// Golfed TypeScript: | |
const range=(n:number,x:number,s=1):number[]=>new Array(-~((x-n)/s)).fill``.map((_,i)=>n+i*s); | |
//Returns an array of values interpolated between the first and second element. | |
//This will continue up until the max argument (m): interpolate(max) | |
//Adds "null" to the end of the array if that array isn't supported/nothing to interpolate. | |
//Usage: [1, 3].interpolate(15) returns [1, 3, 5, 7, 9, 11, 13, 15] | |
Object.defineProperty(Array.prototype, "interpolate", { | |
value: function (m) { | |
var r = [this[0]], | |
s = this[1] - this[0], | |
i; | |
if (s && m > 0) { | |
for (i = 0; r[i] + s <= m; r.push(r[i++] + s)); | |
return r; | |
} | |
return this.concat(null); | |
} | |
}); | |
//Calculate values between an array of values for n passes | |
//Usage: [1, 2, 3, 4].granularize(3); returns [1, 1.25, 1.5, 1.75, 2, 2.25, 2.5, 2.75, 3, 3.25, 3.5, 3.75, 4] | |
// [1, 2, 3, 4].granularize(2); returns [1, 1.5, 2, 2.5, 3, 3.5, 4] | |
Object.defineProperty(Array.prototype, "granularize", { | |
value: function(passes) { | |
//Safety | |
if (passes > 20) throw new Error("Granularizing " + passes + " times is going to take a long time."); | |
var i, j, place, current = this.slice(0); | |
for (i = 1; i < passes; ++i) { | |
place = []; | |
var len; | |
for (j = 0, len = current.length; j < len; ++j) { | |
place.push(current[j]), place.push((current[j] + current[j + 1]) / 2); | |
} | |
place.pop(); | |
current = place; | |
} | |
return current; | |
} | |
}); | |
//Multiply an array by another array | |
//Usage: [2, 4].times([4, 8]) returns [8, 32] | |
Object.defineProperty(Array.prototype, "times", { | |
value: function (a) { | |
return this.map(function(c, i) { | |
return c * a[i]; | |
}); | |
} | |
}); | |
//Merge and remove duplicates of two arrays | |
//Usage: [1, 2, 3].merge([1, 2, 4, 5, 6]) returns [1, 2, 3, 4, 5, 6] | |
Object.defineProperty(Array.prototype, "merge", { | |
value: function (a) { | |
var s = this; | |
return this.concat(a.filter(function(c) { | |
return s.indexOf(c) < 0; | |
})); | |
} | |
}); | |
//Remove non-unique elements from an array | |
//Usage: ["one", "two", "one", "three"].unique returns ["one", "two", "three"] | |
Object.defineProperty(Array.prototype, "unique", { | |
get: function() { | |
return this.filter(function(c, i, a) { | |
return a.indexOf(c) == i; | |
}); | |
} | |
}); | |
//LINQ-ish where function | |
//Usage: [{val: 1}, {val: 2}, {val: 3}, {val: 4}].where('val > 2'); returns [{val: 3}, {val: 4}] | |
// [{val: 1}, {val: 2}, {val: 3}, {val: 4}].where(function() { return this.val > 2; })); returns [{val: 3}, {val: 4}] | |
Object.defineProperty(Array.prototype, "where", { | |
value: function(query) { | |
switch(typeof query) { | |
case "string": | |
return this.filter(function(obj) { | |
return eval('obj.' + query.trim()); | |
}); | |
default: | |
return this.filter(function(obj) { | |
return query.call(obj); | |
}); | |
} | |
} | |
}); | |
//Listen for an event | |
//Usage: element.on("click", function() { ... }); | |
Object.defineProperty(HTMLElement.prototype, "on", { | |
value: function(evt, func, capture) { | |
if (this.attachEvent) return this.attachEvent("on" + evt, func); | |
return this.addEventListener(evt, func, capture); | |
} | |
}); | |
//Extend an object's properties to a default object | |
//Usage: {num: 1}.extend({ num: 5, operation: "multiply" }); returns {num: 1, operation: "multiply"} | |
Object.defineProperty(Object.prototype, "extend", { | |
value: function(defaults) { | |
for (var prop in defaults) | |
if (this.hasOwnProperty(prop)) | |
defaults[prop] = this[prop]; | |
return defaults; | |
} | |
}); | |
//Converts an object (key=>value) to URL parameters, similar to PHP's http_build_query | |
//Usage: { key: "value", key2: "value2" }.asParams returns ?key=value&key2=value2 | |
Object.defineProperty(Object.prototype, "asParams", { | |
get: function () { | |
var self = this; | |
return "?" + Object.keys(self).map(function (key) { | |
return encodeURIComponent(key) + "=" + encodeURIComponent(self[key]); | |
}).join("&"); | |
} | |
}); | |
//Tests if two objects are equal by comparing each key | |
//Usage: { key: "value" }.equals({ key: "value" }) returns true | |
Object.defineProperty(Object.prototype, "equals", { | |
value: function(obj) { | |
for (var prop in this) | |
if (this.hasOwnProperty(prop) && this[prop] !== obj[prop]) | |
return false; | |
return true; | |
} | |
}); | |
//Returns the difference between two objects | |
//Usage: { key: "value", key2: "value2" }.diff({ key: "changed", key2: "value2"}) returns { key: "changed" } | |
Object.defineProperty(Object.prototype, "diff", { | |
value: function (obj) { | |
var diff = {}, prop; | |
for (prop in this) | |
this.hasOwnProperty(prop) && obj[prop] != this[prop] && (diff[prop] = this[prop]); | |
for (prop in obj) | |
obj.hasOwnProperty(prop) && this[prop] != obj[prop] && (diff[prop] = obj[prop]); | |
return diff; | |
} | |
}); | |
//Generates a "unique enough" ID to refer to objects as, one-way | |
Object.defineProperty(Object.prototype, "uniqid", { | |
get: function () { | |
return JSON.stringify(this).split("").map(function (m) { | |
return m.charCodeAt(0); | |
}).reduce(function (p, c, a) { | |
return p + c; | |
}).toString(36); | |
} | |
}); | |
//Get or set pseudo element styles of an element from Javascript using some Shadow DOM trickery | |
//Limitation: Cannot get (can still set) styles for hover, focus, active, or visited. Only works for pseudo ELEMENTS. | |
//Usage: element.pseudo("after", "background: red") would make element's :after pseudo-element red | |
//Can also specify a CSSStyleDeclaration (element.style): | |
//Usage: element.pseudo("hover", document.querySelector(".hoverStyles").style) | |
//Example: Can be used to "copy" styles from one element to another: https://jsfiddle.net/n4erpea5/ | |
Object.defineProperty(HTMLElement.prototype, "pseudo", { | |
value: function (pseudo, styles) { | |
if (styles) { | |
//Set style | |
var newStyles; | |
if (typeof styles === "string") { | |
newStyles = (styles + ";").replace(/;/g, " !important;"); | |
} else if (styles instanceof CSSStyleDeclaration) { | |
newStyles = []; | |
[].forEach.call(styles, function (s) { | |
newStyles.push(s + ":" + styles[s]); | |
}); | |
newStyles = newStyles.join(";"); | |
} | |
pseudo = pseudo.toLowerCase(); | |
//:before and :after can be set with :host:before and :host:after | |
//However, they won't work as :host(:before) and :host(:after) | |
//:hover, :focus, :active, and :visited will not with with :host:hover, etc | |
//However, they WILL work with :host(:hover), etc. | |
switch (pseudo) { | |
case "before": | |
case "after": | |
pseudo = ":" + pseudo; | |
break; | |
case "hover": | |
case "focus": | |
case "active": | |
case "visited": | |
pseudo = "(:" + pseudo + ")"; | |
break; | |
default: | |
pseudo = ""; | |
} | |
var root = this.createShadowRoot(); | |
var html = ""; | |
html += "<style>"; | |
html += ":host" + pseudo + " { " + newStyles + "}"; | |
html += "</style>"; | |
html += "<content></content>"; | |
root.innerHTML = html; | |
} else { | |
//Get style | |
pseudo = pseudo.replace(/:/g, ""); | |
return window.getComputedStyle(this, pseudo); | |
} | |
} | |
}); | |
//Converts a NodeList to an array | |
//Usage: document.getElementsByTagName("div").asArray; | |
Object.defineProperty(HTMLCollection.prototype, "asArray", { | |
get: function () { | |
var arr = [], i = this.length; | |
while (i--) arr.unshift(this[i]); | |
return arr; | |
} | |
}); | |
//Math stuff | |
//Geometric mean | |
Object.defineProperty(Array.prototype, "geometricMean", { | |
value: function() { | |
return Math.pow(this.reduce(function(p, c) { | |
return p * c; | |
}), 1 / this.length); | |
} | |
}); | |
//Average/mean | |
Object.defineProperty(Array.prototype, "mean", { | |
value: function() { | |
return this.reduce(function(p, c) { | |
return p + c; | |
}) / this.length; | |
} | |
}); | |
//Median | |
//Usage: [1, 1, 2, 5, 5, 6, 9].median() returns 5 | |
// [1, 1, 2, 6, 6, 9].median() returns 4 (average of 6 and 2) | |
Object.defineProperty(Array.prototype, "median", { | |
value: function() { | |
var self = this.sort(), m = this.length / 2; | |
return m % 1 ? self[m << 0] : (self[m << 0] + self[(m << 0) - 1]) / 2; | |
} | |
}); | |
// Golfed TypeScript: | |
const median=(a:number[],m=(a.sort(),a.length/2)):number=>(a[(m-.1)|0]+a[m|0])/2; | |
//Mode | |
//Returns null if there is no mode (all items in series are unique) | |
Object.defineProperty(Array.prototype, "mode", { | |
value: function () { | |
var uniqs = {}, mode = {}, i; | |
this.sort().forEach(function (c) { | |
uniqs[c] = (uniqs[c] || 0) + 1; | |
}); | |
if (Object.keys(uniqs).length == this.length) return null; | |
for (i in uniqs) { | |
mode = uniqs[i] > (mode.v || 0) ? { | |
i: i, | |
v: uniqs[i] | |
} : mode; | |
} | |
return mode.i; | |
} | |
}); | |
//Population standard deviation | |
Object.defineProperty(Array.prototype, "stdDevPop", { | |
value: function () { | |
var n = this.length; | |
if (!n) return 0; | |
var sum = 0, sq_sum = 0, i; | |
this.forEach(function(c) { | |
sum += c; | |
sq_sum += c * c; | |
}); | |
return Math.sqrt(sq_sum / n - Math.pow(sum / n, 2)); | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
http://i.imgur.com/fitGK.gif