Last active
January 11, 2022 11:49
-
-
Save Buslowicz/d75c9757f1170f5eb8fef673dab5158e to your computer and use it in GitHub Desktop.
Helpers
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
Object.prototype.getPath = function(path) { | |
return path | |
.split(".") | |
.reduce((obj, p) => obj ? obj[p] : undefined, this); | |
} | |
Object.prototype.setPath = function(path) { | |
return path | |
.split(".") | |
.reduce((obj, p) => typeof obj[p] === 'object' ? obj[p] : (obj[p] = {}), this); | |
} | |
function throttle(cb, wait) { | |
"use strict"; | |
var lock = 0; | |
return function() { | |
if (lock) {return;} | |
lock = 1; | |
cb.apply(this, arguments); | |
setTimeout(function() {lock = 0;}, wait); | |
}; | |
} | |
function debounce(cb, wait) { | |
"use strict"; | |
var timer; | |
return function() { | |
clearTimeout(timer); | |
timer = setTimeout(function(self, args) { | |
cb.apply(self, args); | |
}, wait, this, arguments); | |
}; | |
} | |
const hashstr = s => { | |
let hash = 0; | |
if (s.length == 0) return hash; | |
for (let i = 0; i < s.length; i++) { | |
let char = s.charCodeAt(i); | |
hash = ((hash<<5)-hash)+char; | |
hash = hash & hash; // Convert to 32bit integer | |
} | |
return hash; | |
} | |
function getCSSValues(attribute, isNumeric) { | |
var els = document.querySelectorAll('*'); | |
var indexes = {}; | |
for (var i = 0; i < els.length; i++) { | |
var value = window.getComputedStyle(els[i], null)[attribute]; | |
if (isNumeric && isNaN(value = parseInt(value))) { | |
continue; | |
} | |
indexes[value] = true; | |
} | |
indexes = Object.keys(indexes); | |
if (isNumeric) { | |
return indexes.map(function(el) {return isNumeric ? parseInt(el) : el;}); | |
} else { | |
return indexes; | |
} | |
} | |
function getByCSS(styles) { | |
var els = document.querySelectorAll('*'); | |
var resultList = []; | |
for (var i = 0; i < els.length; i++) { | |
var elementStyle = window.getComputedStyle(els[i], null); | |
var matches = true; | |
for (var style in styles) { | |
if (styles[style] !== elementStyle[style]) { | |
matches = false; | |
break; | |
} | |
} | |
if (matches) resultList.push(els[i]); | |
} | |
return resultList; | |
} | |
String.prototype.get = function() {return document.querySelector(this.toString())}; | |
String.prototype.all = function() {return document.querySelectorAll(this.toString())}; | |
export const panStart = (node: HTMLElement) => merge( | |
fromEvent<TouchEvent>(node, 'touchstart') | |
.pipe( | |
map(({ touches }) => touches.item(0)) | |
), | |
fromEvent<MouseEvent>(node, 'mousedown') | |
); | |
export const panMove = (node: HTMLElement) => merge( | |
fromEvent<TouchEvent>(node, 'touchmove') | |
.pipe( | |
map(({ touches }) => touches.item(0)) | |
), | |
fromEvent<MouseEvent>(node, 'mousemove') | |
); | |
export const panEnd = (node: HTMLElement, complete: Subject<void>) => merge( | |
fromEvent(node, 'touchend'), | |
fromEvent(node, 'touchcancel'), | |
fromEvent(node, 'mouseup'), | |
complete | |
); | |
export const flattenHTMLElements = (nodes: Node[][], selector: string) => nodes | |
.flat() | |
.filter((node): node is HTMLElement => node instanceof HTMLElement) | |
.map((node) => (node.matches(selector) ? [node] : []).concat(Array.from<HTMLElement>(node.querySelectorAll(selector)))) | |
.flat(); | |
export const reactiveQuerySelector = (selector: string, root = document.body) => new Observable<HTMLElement[]>(sub => { | |
const nodes = new Set<HTMLElement>(Array.from(root.querySelectorAll(selector))); | |
const observer = new MutationObserver((records) => { | |
flattenHTMLElements(records.map(({addedNodes: added}) => Array.from(added)), selector) | |
.forEach((node) => nodes.add(node)); | |
flattenHTMLElements(records.map(({removedNodes: removed}) => Array.from(removed)), selector) | |
.forEach((node) => nodes.delete(node)); | |
sub.next([...nodes]); | |
}); | |
sub.next([...nodes]); | |
observer.observe(root, {childList: true, subtree: true}); | |
return () => observer.disconnect(); | |
}); | |
export const fromClientRect = (ref: Element, forceStart = false): Observable<ResizeObserverEntry[]> => { | |
return new Observable((trigger) => { | |
const observer = new ResizeObserver((entries) => trigger.next(entries)); | |
observer.observe(ref); | |
if (forceStart) { | |
trigger.next([{target: ref, contentRect: ref.getBoundingClientRect()}]); | |
} | |
return () => observer.unobserve(ref); | |
}); | |
}; | |
export const notNull = <T = any | null>(arg: T): arg is Exclude<T, null> => arg !== null; | |
export const notFalsy = <T = any | null | undefined | never>(arg: T): arg is Exclude<T, null | undefined | never> => { | |
return arg != null; | |
}; | |
export function toCamelCase(str: string) { | |
return ( | |
str | |
// loawercase first character | |
.replace(/^([A-Z])/, (_, c) => c.toLowerCase()) | |
// replace every letter prefixed with space, dash or underscore with an uppercase character (without the prefix) | |
.replace(/[ \-_][a-z]/gi, c => c[1].toUpperCase()) | |
); | |
} | |
/** | |
* Round date down to year, month and day, skipping time | |
*/ | |
export function roundDate(date: Date) { | |
return new Date(date.toDateString()); | |
} | |
/** | |
* Deep search an object for a string value matching a regexp pattern | |
*/ | |
export function objectSearch(obj = {}, value) { | |
const checked = new Set(); | |
const result = []; | |
const recursiveSearch = (obj = {}, path = []) => { | |
if (!obj || typeof obj !== 'object') { | |
return; | |
} | |
Object.keys(obj).forEach(function (k) { | |
if (obj[k] == null) { return; } | |
if (typeof obj[ k ] === 'string') { | |
value.test(obj[ k ]) && result.push({ obj, path }); | |
return; | |
} else if (typeof obj[k] === 'object') { | |
if (checked.has(obj[k])) { return; } | |
checked.add(obj[k]); | |
recursiveSearch(obj[ k ], [...path, k]); | |
} | |
}); | |
} | |
recursiveSearch(obj); | |
return result; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment