Skip to content

Instantly share code, notes, and snippets.

View ryanmorr's full-sized avatar

Ryan Morr ryanmorr

View GitHub Profile
@ryanmorr
ryanmorr / compile-tagged-template.js
Created April 2, 2024 17:05
Simple function to compile a tagged template string with a callback function
function compileTaggedTemplate(strings, values, callback) {
return strings.raw.reduce((acc, str, i) => acc + (callback(values[i - 1])) + str);
}
// Usage:
const tag = (strings, ...values) => compileTaggedTemplate(strings, values, (val) => val.toUpperCase());
console.log(tag`Capitalize ${'all'} ${'substitutions'}`); //=> Capitalize ALL SUBSTITUTIONS
@ryanmorr
ryanmorr / raf-engine.js
Last active April 2, 2024 06:45
Simple abstraction for using requestAnimationFrame
let raf = 0;
const animations = [];
function remove(animation) {
const index = animations.indexOf(animation);
if (index > -1) {
animations.splice(index, 1);
}
}
@ryanmorr
ryanmorr / for-each-match.js
Last active April 1, 2024 20:26
Iterate through all the matches of a regular expression and call a function
function forEachMatch(regex, str, callback) {
if (regex.global) {
regex.lastIndex = 0;
}
let i = -1, match;
while ((match = regex.exec(str))) {
callback(match, i++, str, regex);
}
}
@ryanmorr
ryanmorr / attempt.js
Created April 1, 2024 20:24
Wrap a try/catch block with a promise for easy error handling
function attempt(fn) {
return new Promise((resolve, reject) => {
try {
resolve(fn());
} catch(e) {
reject(e);
}
});
}
@ryanmorr
ryanmorr / styles.js
Last active April 1, 2024 20:14
Get and set CSS styles, supporting camel-case, kebab-case, and custom properties
function getStyle(el, prop) {
const style = getComputedStyle(el);
return prop.includes('-') ? style.getPropertyValue(prop) : style[prop];
}
function setStyle(el, prop, value) {
if (prop.includes('-')) {
el.style.setProperty(prop, value);
} else {
el.style[prop] = value;
@ryanmorr
ryanmorr / create-class.js
Last active April 1, 2024 20:11
Generate a class name for a DOM element with a string, array, or object literal
// Courtesy of: https://github.com/jorgebucaran/hyperapp
function createClass(value) {
if (typeof value === 'string') {
return value;
}
let output = '';
if (Array.isArray(value)) {
for (let i = 0, len = value.length, tmp; i < len; i++) {
if ((tmp = createClass(value[i])) !== '') {
@ryanmorr
ryanmorr / touch-detection.js
Last active March 30, 2024 06:51
Determine if the user has a touch-enabled device
// An aggressive means to detect if the user's device is touch only
// Probably bad practice: https://css-tricks.com/interaction-media-features-and-their-potential-for-incorrect-assumptions/
function isTouch() {
return matchMedia('(hover: none) and (pointer: coarse)').matches;
}
// A more passive approach is to detect if the user's device is merely touch-enabled
function hasTouch() {
return matchMedia('(any-pointer:coarse)').matches;
}
@ryanmorr
ryanmorr / sort-array.js
Last active March 29, 2024 20:09
Sort an array by string, number, or date with support for ascending and descending order
function compareDefault(a, b) {
return a - b;
}
function compareStrings(a, b) {
a = String(a).toUpperCase();
b = String(b).toUpperCase();
if (a > b) {
return 1;
}
@ryanmorr
ryanmorr / get-class.js
Last active March 29, 2024 06:40
Get the class of an object for type detection
function getClass(obj) {
return {}.toString.call(obj).slice(8, -1);
}
// Usage:
getClass([]); //=> "Array"
getClass('foo'); //=> "String"
getClass(123); //=> "Number"
@ryanmorr
ryanmorr / port.js
Last active March 29, 2024 06:40
Port a method to be used standalone
function port(fn) {
return Function.prototype.bind.call(Function.call, fn);
}
// Usage:
// port the `forEach` method of the Array prototype
const each = port([].forEach);
// Use standalone by passing the contextual object as the first argument
each(document.querySelectorAll('div'), (el) => console.log(el));