Skip to content

Instantly share code, notes, and snippets.

@samueleaton
Last active February 13, 2020 23:14
Show Gist options
  • Save samueleaton/aa96663f536bf3942630 to your computer and use it in GitHub Desktop.
Save samueleaton/aa96663f536bf3942630 to your computer and use it in GitHub Desktop.
Some basic functionality you would find with lodash
/* eslint-disable id-blacklist */
/* eslint-disable id-length */
/* eslint-disable no-param-reassign */
/* eslint-disable no-implicit-coercion */
/* eslint-disable no-undefined */
/* eslint-disable no-empty-function */
/* eslint-disable semi */
/* eslint-disable quotes */
/* eslint-disable no-eq-nullg */
/* depends on: forEach, forOwn */
export function assign(...args) {
forEach(args, (obj, i) => {
if (i === 0)
return
forOwn(obj, (val, key) => {
args[0][key] = val
})
})
return args[0]
}
export function reduce(list, func, accum) {
if (!list || !list.length)
return accum;
if (typeof accum === "undefined") {
if (list.length <= 1)
return list[0];
else {
const newAccum = list[0];
return reduce(list.slice(1), func, newAccum);
}
}
else {
const n = list[0];
const newAccum = func(accum, n);
return reduce(list.slice(1), func, newAccum);
}
}
export function toArray(obj) {
const arr = [];
for (let i = 0, ii = obj.length; i < ii; i++)
arr.push(obj[i]);
return arr;
}
export function toUpper(str) {
if (!str || typeof str !== "string")
return "";
if (str && typeof str.toUpperCase === "function")
return str.toUpperCase();
else
return str;
}
export function upperFirst(str) {
if (!str || typeof str !== "string")
return "";
return str.charAt(0).toUpperCase() + str.slice(1);
}
export function toLower(str) {
if (!str || typeof str !== "string")
return "";
if (str && typeof str.toLowerCase === "function")
return str.toLowerCase();
else
return str;
}
export function snakeCase(str) {
if (!str || typeof str !== "string")
return "";
const strArr = [];
for (let i = 0, ii = str.length; i < ii; i++) {
const char = str[i];
if (/^\w$/.test(char)) {
if (i !== 0 && !(/^[A-Z]$/).test(str[i - 1]) && (/^[A-Z]$/).test(char))
strArr.push("_");
strArr.push(char.toLowerCase());
}
}
return strArr.join("").replace(/_+/g, "_");
}
/* depends on: upperFirst */
export function startCase(str) {
if (!str || typeof str !== "string")
return "";
const string = str.replace(/(_|-)/g, " ");
const strArr = [];
for (let i = 0, ii = string.length; i < ii; i++) {
const char = string[i];
if (/^(\w| )$/.test(char)) {
if (i !== 0 && !(/^[A-Z]$/).test(string[i - 1]) && (/^[A-Z]$/).test(char))
strArr.push(" ");
if (strArr[strArr.length - 1] === " ")
strArr.push(char.toUpperCase());
else
strArr.push(char);
}
}
return upperFirst(strArr.join("").replace(/ +/g, " ").trim());
}
export function escape(str) {
if (!str || typeof str !== "string")
return "";
return str.replace(/&/g, "&amp;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#39;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;");
}
export function unescape(str) {
if (!str || typeof str !== "string")
return "";
return str.replace(/&amp;/g, "&")
.replace(/&quot;/g, "\"")
.replace(/&#39;/g, "'")
.replace(/&lt;/g, "<")
.replace(/&gt;/g, ">");
}
export function truncate(str, length = 30, sub = "...") {
if (!str || typeof str !== "string")
return "";
const size = parseInt(length) || 30;
if (str.length > size) {
const truncated = str.slice(0, size);
if (sub.length)
return truncated.slice(0, 0 - sub.length) + sub;
else
return truncated;
}
else
return str;
}
export function split(string, dilimiter) {
if (string && string.split)
return string.split(dilimiter);
else
return [];
}
export function replace(arg, regex, string = "") {
if (typeof string !== "string")
return console.error("3rd params must be strings");
if (arg && arg.replace)
return arg.replace(regex, string);
else
return arg;
}
export function trim(string) {
if (!string || typeof string !== "string")
return "";
if (string && string.trim)
return string.trim();
else
return string;
}
// compresses consecutuve spaces into a single space
export function compress(string) {
if (!string || typeof string !== "string") {
return "";
}
return string.replace(/\s+/g, " ").trim();
}
export function isUndefined(arg) {
return typeof arg === "undefined";
}
export function isString(arg) {
return typeof arg === "string";
}
export function isBoolean(arg) {
return typeof arg === "boolean" || arg === true || arg === false || false;
}
export function isFunction(func) {
return typeof func === "function";
}
export function isObject(value) {
const type = typeof value;
return !!value && (type === "object" || type === "function");
}
export function isEmpty(value) {
if (value === null || typeof value === "undefined")
return true
if (typeof value.length === "number")
return !value.length
for (const key in value) {
if (hasOwnProperty.call(value, key))
return false
}
return true
}
export function isNil(value) {
if (value) {
return false
}
if (typeof value === "undefined" || value === null) {
return true
}
return false
}
export function includes(arg, elm) {
if (!arg || !arg.indexOf)
return false;
else if (arg.indexOf(elm) > -1)
return true;
else
return false;
}
export function getProto(arg) {
return Object.getPrototypeOf(Object(arg));
}
/* depends on: forEach, isArray */
export function flatten(arr) {
const result = [];
forEach(arr, elm => {
if (isArray(elm))
forEach(elm, elm2 => result.push(elm2));
else
result.push(elm);
});
return result;
}
export function forOwn(arg, func) {
for (const key in arg) {
if (arg.hasOwnProperty(key)) {
if (typeof func === "function")
func(arg[key], key);
}
}
}
export function invert(arg, func) {
const newObj = {};
for (const key in arg) {
if (arg.hasOwnProperty(key))
newObj[arg[key]] = key;
}
return newObj;
}
/* depends on: forEach, get, set */
export function pick(obj, paths) {
const result = {};
forEach(paths, path => {
const value = get(obj, path)
if (typeof value !== "undefined")
set(result, path, value)
})
return result;
}
export function pickBy(obj, func) {
const result = {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
if (typeof func === "function") {
if (func(obj[key], key))
result[key] = obj[key];
}
else if (obj[key])
result[key] = obj[key];
}
}
return result;
}
/* depends on: isArray, forEach */
export function keyBy(arr, func = element => element) {
if (!isArray(arr))
return console.error("keyBy takes an array");
if (typeof func !== "function")
return {};
const result = {};
forEach(arr, elm => {
result[func(elm)] = elm;
});
return result;
}
/* depends on: isArray, getProto */
export function isPlainObject(obj) {
if (!obj)
return false;
if (typeof obj !== "object")
return false;
if (isArray(obj))
return false;
const proto = getProto(obj);
if (proto === null)
return true;
const cnstcr = Object.prototype.hasOwnProperty.call(proto, "constructor") && proto.constructor;
const funcToString = Function.prototype.toString;
return (
typeof cnstcr === "function" &&
cnstcr instanceof cnstcr &&
funcToString.call(cnstcr) === funcToString.call(Object));
}
export function keys(obj) {
const arr = [];
for (const key in obj) {
if (hasOwnProperty.call(obj, key) && key !== "constructor")
arr.push(key);
}
return arr;
}
export function isArray(obj) {
if (!obj)
return false;
return (
typeof obj === "object" &&
(
(Array.isArray && Array.isArray(obj)) ||
obj.constructor === Array ||
obj instanceof Array
)
);
}
export function forEach(list, func) {
if (!list || !list.length)
return null;
if (typeof func !== "function")
return console.error("2nd param to forEach must be function");
for (let i = 0, ii = list.length; i < ii; i++)
func(list[i], i);
}
export function forEachRight(list, func) {
if (!list || !list.length)
return null;
if (typeof func !== "function")
return console.error("2nd param to forEach must be function");
for (let i = list.length - 1, ii = 0; i >= ii; i--)
func(list[i], i);
}
export function find(list, func) {
if (!list || !list.length || typeof func !== "function")
return null;
for (let i = 0, ii = list.length; i < ii; i++) {
if (func(list[i], i))
return list[i];
}
return null;
}
export function findFromIndex(list, startIndex, func) {
if (!list || !list.length || typeof func !== "function")
return null;
if (startIndex >= list.length)
return null;
for (let i = startIndex, ii = list.length; i < ii; i++) {
if (func(list[i], i))
return list[i];
}
return null;
}
export function findIndex(list, func) {
if (!list || !list.length || typeof func !== "function")
return null;
for (let i = 0, ii = list.length; i < ii; i++) {
if (func(list[i], i))
return i;
}
return null;
}
export function findIndexFromIndex(list, startIndex, func) {
if (!list || !list.length || typeof func !== "function")
return null;
if (startIndex >= list.length)
return null;
for (let i = startIndex, ii = list.length; i < ii; i++) {
if (func(list[i], i))
return i;
}
return null;
}
export function some(list, func) {
if (!list || !list.length || typeof func !== "function")
return false;
for (let i = 0, ii = list.length; i < ii; i++) {
if (func(list[i], i))
return true;
}
return false;
}
export function every(list, func) {
if (!list || !list.length || typeof func !== "function")
return true;
for (let i = 0, ii = list.length; i < ii; i++) {
if (!func(list[i], i))
return false;
}
return true;
}
export function map(list, func) {
if (!list || !list.length)
return [];
if (typeof func !== "function")
func = x => x;
const arr = [];
for (let i = 0, ii = list.length; i < ii; i++)
arr.push(func(list[i], i));
return arr;
}
export function mapValues(obj, func) {
const result = {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
if (typeof func === "function") {
result[key] = func(obj[key], key);
}
else
result[key] = obj[key];
}
}
return result;
}
export function compactMap(list, func) {
if (!list || !list.length)
return [];
if (typeof func !== "function")
func = x => x;
const arr = [];
for (let i = 0, ii = list.length; i < ii; i++) {
const result = func(list[i], i)
if (result !== null && typeof result !== "undefined")
arr.push(result);
}
return arr;
}
export function filter(list, func) {
if (!list || !list.length)
return [];
if (typeof func !== "function")
return [];
const arr = [];
for (let i = 0, ii = list.length; i < ii; i++) {
if (func(list[i]))
arr.push(list[i]);
}
return arr;
}
/* depends on: forEachRight */
/* mutates array */
export function remove(list, func) {
if (!list || !list.length)
return list
forEachRight(list, (elm, i) => {
if (typeof func !== "function") {
if (elm === func) {
list.splice(i, 1)
}
}
else if (func(elm, i)) {
list.splice(i, 1)
}
})
return list
}
export function compact(list) {
if (!list || !list.length)
return [];
const arr = [];
for (let i = 0, ii = list.length; i < ii; i++) {
if (list[i])
arr.push(list[i]);
}
return arr;
}
/* depends on: isArray, split */
export function has(obj, path) {
if (typeof obj === "undefined" || obj === null) {
return false;
}
if (typeof path === "undefined" || path === null || path === "") {
return true;
}
let pathArr;
if (isArray(path)) {
pathArr = path
}
else if (typeof path === "number") {
pathArr = [ path ]
}
else {
pathArr = split(path, ".")
}
if (!pathArr.length) {
return true;
}
if (obj.hasOwnProperty(pathArr[0])) {
const sliced = pathArr.slice(1);
if (sliced.length === 0) {
return true;
}
return has(obj[pathArr[0]], sliced);
}
return false;
}
/* depends on: isArray, split */
export function get(obj, path, defaultVal = null) {
if (typeof obj === "undefined" || obj === null)
return defaultVal;
if (typeof path === "undefined" || path === null || path === "")
return defaultVal || obj;
const pathArr = isArray(path) ? path : split(path, ".");
if (!pathArr.length)
return defaultVal || obj;
if (obj[pathArr[0]]) {
const sliced = pathArr.slice(1);
if (sliced.length === 0)
return obj[pathArr[0]];
return get(obj[pathArr[0]], sliced);
}
return defaultVal;
}
/* depends on: isArray, split */
export function set(obj, path, value) {
if (typeof obj === "undefined" || obj === null)
return null;
if (typeof path === "undefined" || path === null || path === "")
return obj;
const uIntRegex = /^(?:0|[1-9]\d*)$/
const pathArr = isArray(path) ? path : split(path, ".");
for (let i = 0, object = obj; i < pathArr.length; i++) {
if (typeof object[pathArr[i]] !== "object") {
if (i >= pathArr.length - 1)
object[pathArr[i]] = value
else if (typeof pathArr[i + 1] === "number" || uIntRegex.test(pathArr[i + 1]))
object[pathArr[i]] = []
else
object[pathArr[i]] = {}
}
else if (i >= pathArr.length - 1)
object[pathArr[i]] = value
object = object[pathArr[i]]
}
return obj;
}
/* depends on: includes */
export function removeDuplicates(arr) {
const newArr = [];
for (let i = 0, ii = arr.length; i < ii; i++) {
if (!includes(newArr, arr[i]))
newArr.push(arr[i]);
}
return newArr;
}
/* depends on: isArray */
export function chunk(arr, size, chunks = []) {
if (!isArray(arr) || !arr.length)
return chunks;
const chunked = arr.splice(0, size);
chunks.push(chunked);
return chunk(arr, size, chunks);
}
/* depends on: isArray */
export function chunkRight(arr, size, chunks = []) {
if (!isArray(arr) || !arr.length)
return chunks;
const chunked = arr.splice(0 - size);
chunks.unshift(chunked);
return chunkRight(arr, size, chunks);
}
/* delimits a string from the left side */
export function delimit(obj, count, delimiter = "") {
return map(chunk(obj.split(""), count), arr => arr.join("")).join(delimiter);
}
/* delimits a string from the right side */
export function delimitRight(obj, count, delimiter = "") {
return map(chunkRight(obj.split(""), count), arr => arr.join("")).join(delimiter);
}
/* depends on: flatten */
export function concat(arr, ...args) {
const newArr = [];
for (let i = 0, ii = arr.length; i < ii; i++)
newArr.push(arr[i]);
for (let i = 0, ii = args.length; i < ii; i++)
newArr.push(args[i]);
return flatten(newArr);
}
export function debounce(func, debounceTime, runImmediately = false) {
if (typeof func !== "function")
return console.error("first arg must be a function");
const time = parseInt(debounceTime);
if (isNaN(time) || time !== debounceTime)
return console.error("debounce time must be an integer (in milliseconds)");
if (time < 0)
return console.error("time must be a positive integer");
let timeout = null;
return function debounced(...args) {
if (timeout) {
window.clearTimeout(timeout);
}
else if (runImmediately) {
func(...args)
}
timeout = setTimeout(() => {
func(...args);
timeout = null;
}, time);
}
}
export function chunkBy(list, keys) {
if (!list || !list.length) return [];
if (!keys || !keys.length) return list;
const chunks = [];
for (let i = 0; i < list.length; i++) {
const item = list[i];
const lastChunk = chunks[chunks.length - 1];
const lastItemOfLastChunk = lastChunk && lastChunk[lastChunk.length - 1];
if (lastItemOfLastChunk && every(keys, k => lastItemOfLastChunk[k] === item[k])) {
lastChunk.push(item);
} else {
chunks.push([list[i]]);
}
}
return chunks;
}
/* depends on: isArray, forEach */
export function groupBy(arr, func = element => [element]) {
if (!isArray(arr)) return console.error("groupBy takes an array");
if (typeof func !== "function") return {};
const result = {};
forEach(arr, elm => {
const key = func(elm);
if (!result[key]) {
result[key] = [];
}
result[key].push(elm);
});
return result;
}
/*
usage: rand(length, optionalExtraChars)
example: rand()
example: rand(36)
example: rand(24, "$@_*")
*/
export const rand = (() => {
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
return (size = 12, optChars) => {
const srcStr = chars + (optChars || "")
let randomChars = "";
for (let i = 0; i < size; i++)
randomChars += srcStr.charAt(Math.floor(Math.random() * srcStr.length));
return randomChars;
}
})()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment