Last active
October 8, 2017 03:11
-
-
Save jodyheavener/0e6e453c00a99d3575b10f843daccc7a to your computer and use it in GitHub Desktop.
Various 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
// Use this to access process env vars in a React setup | |
export function env(key, fallback) { | |
return process.env[`REACT_APP_${key}`] || fallback; | |
} |
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
/** | |
* request - a single function to perform fetch-based requests with custom data, headers, and optional caching | |
* | |
* Requires storage and env (see below) | |
* | |
* @param {string} path - required - path to the resource you're attempting to access, to be used as storage key | |
* @param {object} options - {} - object containing all options for the request | |
* > @param {object} data - null - key value pairs to pass to your request | |
* > @param {string} method - "GET" - the verb to use for the request, defaults | |
* > @param {object} headers - {} - any headers to pass to perform the request with | |
* > @param {boolean} external - false - should the request use the base path, or is the path itself external? | |
* > @param {boolean} authed - false - should the request add the Authorization header with bearer value to the headers? | |
* > @param {boolean} cache - false - should the request be cached? If set to true, future calls will first check if the response exists in the cache | |
* > @param {integer} expiration - how many days should the cached response be valid? | |
* @return {Promise} a valid request will resolve with an object containing the data and response information | |
*/ | |
export const request = (path, { data, method="GET", headers={}, external=false, authed=false, cache=false, expiration }={}) => { | |
return new Promise((resolve, reject) => { | |
const basePath = path; | |
path = external ? path : `${env('API_BASE', '/api')}/${path}`; | |
if (expiration != null) cache = true; | |
if (cache) { | |
var cachedRequest = storage(basePath); | |
// Does the cached item exist and has it expired? | |
if (cachedRequest && !cachedRequest.expired) { | |
return resolve({ | |
data: cachedRequest.data, | |
response: cachedRequest.response | |
}); | |
}; | |
}; | |
let params = { method: method }; | |
let setHeaders = Object.assign({ | |
'Content-Type': 'application/json', | |
'Accept': 'application/json' | |
}, headers); | |
if (authed) { | |
setHeaders['Authorization'] = `Bearer ${auth.getToken()}`; | |
}; | |
if (data) { | |
if (method === 'GET') { | |
path = `${path}?${objectToURLParams(data)}`; | |
} else { | |
params.body = JSON.stringify(data); | |
} | |
}; | |
params.headers = new Headers(setHeaders); | |
fetch(path, params).then((response) => { | |
response.json().then((data) => { | |
if (cache) { | |
storage(basePath, { | |
expiration: expiration, | |
value: { | |
data: data, | |
response: { | |
status: response.status | |
} | |
} | |
}) | |
}; | |
resolve({ | |
data: data, | |
response: response | |
}); | |
}).catch((error) => { | |
// Response returned no data, so | |
// send a blank object | |
resolve({ | |
data: {}, | |
response: response | |
}); | |
}) | |
}).catch((error) => { | |
reject({ | |
data: {}, | |
error: error | |
}); | |
}); | |
}); | |
} |
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
// This is pretty straighforward. Scroll an element (or the page) to a given position, at a certain speed, and with a certain easing. | |
// When scrolling the body, for best results use (document.scrollingElement || document.documentElement) | |
const easingEquations = { | |
easeOutSine: function (pos) { | |
return Math.sin(pos * (Math.PI / 2)) | |
}, | |
easeInOutSine: function (pos) { | |
return (-0.5 * (Math.cos(Math.PI * pos) - 1)) | |
}, | |
easeInOutQuint: function (pos) { | |
if ((pos /= 0.5) < 1) { | |
return 0.5 * Math.pow(pos, 5) | |
} | |
return 0.5 * (Math.pow((pos - 2), 5) + 2) | |
} | |
} | |
export function scrollX(el, targetX, speed=10, easing='easeOutSine') { | |
let scrollX = el.scrollLeft | |
let currentTime = 0 | |
const time = Math.max(.1, Math.min(Math.abs(scrollX - targetX) / speed, .8)) | |
function tick() { | |
currentTime += 1 / 60 | |
var p = currentTime / time | |
var t = easingEquations[easing](p) | |
if (p < 1) { | |
window.requestAnimationFrame(tick) | |
el.scrollLeft = scrollX + ((targetX - scrollX) * t) | |
} else { | |
el.scrollLeft = targetX | |
} | |
} | |
tick() | |
} | |
export function scrollY(el, targetY, speed=2000, easing='easeOutSine') { | |
let scrollY = el.scrollTop | |
let currentTime = 0 | |
const time = Math.max(.1, Math.min(Math.abs(scrollY - targetY) / speed, .8)) | |
function tick() { | |
currentTime += 1 / 60 | |
var p = currentTime / time | |
var t = easingEquations[easing](p) | |
if (p < 1) { | |
window.requestAnimationFrame(tick) | |
el.scrollTop = scrollY + ((targetY - scrollY) * t) | |
} else { | |
el.scrollTop = targetY | |
} | |
} | |
tick() | |
} |
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
/** | |
* storage - basically a wrapper around localStorage to allow storage of objects, and expiring data | |
* | |
* @param {string} key - required - the key used to retrieve or store data from storage | |
* @param {object} options - {} - object containing all options for the action | |
* > @param {any} value - null - the value of the item you would like to store | |
* > @param {integer} expiration - 7 - the expiration of the data, in number of days | |
* > @param {integer} fallback - null - the fallback value, in case the lookup fails | |
* > @param {integer} remove - false - set to true to remove the storage item | |
* @return {any} | |
*/ | |
export const storage = (key, { value, expiration=7, fallback=null, remove=false } = {}) => { | |
const cacheName = `${config.cacheVersion}Cache`; | |
const nowSeconds = new Date().getTime() / 1000; | |
let cacheStore = {}; | |
if (window.localStorage[cacheName]) { | |
cacheStore = JSON.parse(window.localStorage[cacheName]); | |
}; | |
if (remove) { | |
delete cacheStore[key]; | |
window.localStorage[cacheName] = JSON.stringify(cacheStore); | |
return true; | |
}; | |
if (value) { | |
const cacheExpiration = expiration * 86400; | |
const assignedValue = typeof value === 'string' ? { data: value } : value; | |
cacheStore[key] = Object.assign({ | |
expires: nowSeconds + cacheExpiration | |
}, assignedValue); | |
window.localStorage[cacheName] = JSON.stringify(cacheStore); | |
return cacheStore[key]; | |
}; | |
return cacheStore[key] | |
? Object.assign(cacheStore[key], { expired: nowSeconds > cacheStore[key].expires }) | |
: fallback; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment