Last active
August 2, 2022 13:59
-
-
Save reynotekoppele/febdfb22fc180d7025862715c9c2f8fb to your computer and use it in GitHub Desktop.
Javascript utilities
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
/* global ajax_object */ | |
/** | |
* Make AJAX request to WordPress. | |
* | |
* @param {RequestInit} [options] Fetch options. | |
* @param {AbortController} [controller] Controller for current request. | |
* | |
* @throws Will throw an error if the status code is not 2xx. | |
* @throws Will throw data if the WordPress success status is false. | |
* | |
* @return {Promise<any>} Resolved data. | |
*/ | |
export const doRequest = async ( options = {}, controller = null ) => { | |
const response = await fetch( ajax_object.ajax_url, { // eslint-disable-line camelcase | |
method: 'POST', | |
controller, | |
...options, | |
} ); | |
// Make sure we have a 2xx status code. | |
if ( ! response.ok ) { | |
throw new Error( 'Response is not ok!' ); | |
} | |
// Get JSON response. | |
const { success, data } = await response.json(); | |
// Make sure the response is successful. | |
if ( ! success ) { | |
throw data; | |
} | |
// Return data. | |
return data; | |
}; | |
/* ========================= */ | |
/** | |
* Wait for a given amount of time. | |
* | |
* @param {number} ms Number of milliseconds to wait. | |
* | |
* @return {Promise<void>} | |
*/ | |
export const sleep = ( ms ) => { | |
return new Promise( ( res ) => setTimeout( res, ms ) ) | |
}; | |
/* ========================= */ | |
/** | |
* Execute function after given delay, defaults to 500ms. | |
* Reset delay when called within the given timeframe. | |
* | |
* @param {Function} cb Callback function to execute. | |
* @param {number} ms Number of milliseconds to wait. | |
*/ | |
export const debounce = ( cb, ms = 500 ) => { | |
let timerId; | |
return ( ...args ) => { | |
clearTimeout( timerId ); | |
timerId = setTimeout( () => { | |
cb( ...args ); | |
}, ms ); | |
}; | |
}; | |
/* ========================= */ | |
/** | |
* Execute function once every given timeframe, defaults to 500ms. | |
* Can be used as a rate limiter. | |
* | |
* @param {Function} cb Callback function to execute. | |
* @param {number} ms Number of milliseconds to wait. | |
*/ | |
export const throttle = ( cb, ms = 500 ) => { | |
let timerId; | |
let lastRun; | |
const runCallback = ( ...args ) => { | |
cb( ...args ); | |
lastRun = Date.now(); | |
}; | |
return ( ...args ) => { | |
if ( ! lastRun ) { | |
runCallback( ...args ); | |
return; | |
} | |
clearTimeout( timerId ); | |
timerId = setTimeout( () => { | |
if ( ( Date.now() - lastRun ) >= ms ) { | |
runCallback( ...args ); | |
} | |
}, ms - ( Date.now() - lastRun ) ); | |
}; | |
}; | |
/* ========================= */ | |
/** | |
* Observe property changes on external properties. | |
* | |
* WARNING: Only use this when you can't wrap the object in a Proxy (see {@link observeInternalProperty}). | |
* | |
* @param {Object} obj Object to observe. | |
* @param {string} property Key of property to observe. | |
* @param {Function} onChanged Callback to fire when the property changes. | |
*/ | |
export const observeExternalProperty = ( obj, property, onChanged ) => { | |
// Get descriptor settings. | |
const oldDescriptor = Object.getOwnPropertyDescriptor( obj, property ); | |
// Make a copy of the value. | |
let val = obj[ property ]; | |
Object.defineProperty( obj, property, { | |
get() { | |
return val; | |
}, | |
set( value ) { | |
val = value; | |
onChanged( value ); | |
}, | |
enumerable: oldDescriptor?.enumerable, | |
configurable: oldDescriptor?.configurable, | |
} ); | |
}; | |
/* ========================= */ | |
/** | |
* Observe property changes on internal object. | |
* | |
* @param {Object} obj Object to observe. | |
* @param {string} property Key of property to observe. | |
* @param {Function} onChanged Callback to fire when the property changes. | |
* | |
* @return {Proxy} Proxied object. | |
*/ | |
export const observeInternalProperty = ( obj, property, onChanged ) => { | |
const handler = { | |
get() { | |
return Reflect.get( ...arguments ); | |
}, | |
set( target, prop, value ) { | |
Reflect.set( ...arguments ); | |
if ( prop === property ) { | |
return onChanged( value ); | |
} | |
}, | |
}; | |
return new Proxy( obj, handler ); | |
}; | |
/* ========================= */ | |
/** | |
* Track multiple instances of a class. | |
*/ | |
export class InstanceTracker { | |
/** @type {WeakMap<HTMLElement, InstanceTracker>} */ | |
static #instances = new WeakMap(); | |
/** | |
* Initialize and store class instance. | |
* | |
* @param {HTMLElement} element - Element associated with instance. | |
*/ | |
constructor( element ) { | |
InstanceTracker.#instances.set( element, this ); | |
} | |
/** | |
* Get class instance of given element | |
* | |
* @param {HTMLElement} element - Element associated with instance. | |
* | |
* @return {InstanceTracker} instance of our class. | |
*/ | |
static getInstance( element ) { | |
return InstanceTracker.#instances.get( element ); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment