Skip to content

Instantly share code, notes, and snippets.

@Floofies
Last active January 18, 2023 17:30
Show Gist options
  • Save Floofies/6e7a41f369a40e336d4f579911c74a7f to your computer and use it in GitHub Desktop.
Save Floofies/6e7a41f369a40e336d4f579911c74a7f to your computer and use it in GitHub Desktop.
A collection of small utility functions I have written over the years. Will receive updates.
/* Table Of Contents:
GeneratorFunction
The GeneratorFunction constructor, exposed.
isSetIterator
Returns true if the object is a bultin Set Iterator.
isMapIterator
Returns true if the object is a builtin Map Iterator.
iterableObject
Make a regular Object an iterable.
get
Sends an HTTP GET request to `url` with response type `type`.
head
Sends an HTTP HEAD request to `url`.
xhrException
Throws an error if the fetch request fails.
getHash
Returns the value of the URL hash parameter, or `null` if the value is empty.
scrollToHeading
Scrolls to the first Heading element which matches `title`.
scrollToHash
Scrolls to the first Heading element which matches the URL hash parameter.
loadScript
Dynamically loads a JavaScript script from a URL.
loadStyle
Dynamically loads a CSS Stylesheet from a URL.
createQueryString
Returns a URL Query String using the key/value pairs in `obj`.
setQueryString
Sets the URL Query String using the key/value pairs in `obj`.
getQueryString
Returns an object containing the URL Query String parameters, or `null` if there is none.
empty
Removes all child Nodes from a DOM Element.
newFragmentClone
Clones the child nodes of an element into a new Document Fragment.
newFragmentParse
Parses an HTML tagString into DOM nodes in a Document Fragment.
compose
Returns a new Function composed from an Array of Functions.
plotPath
(NodeJS fs module) Traverses a filesystem path, creating it along the way.
*/
// The GeneratorFunction constructor, exposed
const GeneratorFunction = (function* () { }).constructor;
// Returns true if the object is a bultin Set Iterator
const setIteratorProto = (new Set())[Symbol.iterator]().__proto__;
const isSetIterator = obj => obj.__proto__ === setIteratorProto;
// Returns true if the object is a builtin Map Iterator
const mapIteratorProto = (new Map())[Symbol.iterator]().__proto__;
const isMapIterator = obj => obj.__proto__ === mapIteratorProto;
// Make a regular Object an iterable
function IterableObject(obj) {
obj[Symbol.iterator] = this.wrapper;
return obj;
};
IterableObject.prototype.wrapper = function* () {
for (const prop of Object.keys(this)) yield this[prop];
};
// Sends an HTTP GET request to `url` with response type `type`.
function get(url = "/", type = "text") {
return fetch(url).then(xhrException).then(res => res[type]());
}
// Sends an HTTP HEAD request to `url`.
function head(url = "/") {
return fetch(url, { method: "HEAD" }).then(xhrException).then(res => res.headers);
}
// Throws an error if the fetch request fails.
function xhrException(res) {
if (!res.ok) throw new Error(res.statusText);
return res;
}
// Returns the value of the URL hash parameter, or `null` if the value is empty.
function getHash() {
if (window.location.hash.length < 2) return null;
return window.location.hash.slice(1, window.location.hash.length)
}
// Scrolls to the first Heading element which matches `title`.
const headingSelector = "h1, h2, h3, h4, h5, h6";
function scrollToHeading(title) {
const headings = document.querySelectorAll(headingSelector);
if (headings === null || headings.length === 0) return;
for (const heading of headings) {
const headingTitle = heading.textContent;
if (headingTitle.length === 0) continue;
if (headingTitle.trim() === title) heading.scrollIntoView();
}
}
// Scrolls to the first Heading element which matches the URL hash parameter.
function scrollToHash() {
const title = getHash();
if (title === null) return;
scrollToHeading(title);
}
// Dynamically loads a JavaScript script from a URL.
function loadScript(url) {
return new Promise(resolve => {
const script = document.createElement("script");
script.src = url;
script.type = "application/javascript";
script.addEventListener("load", _=> resolve());
document.head.appendChild(script);
});
}
// Dynamically loads a CSS Stylesheet from a URL.
function loadStyle(url) {
const link = document.createElement("link");
link.href = url;
link.type = "text/css";
link.rel = "stylesheet";
document.head.appendChild(link);
}
// Returns a URL Query String using the key/value pairs in `obj`.
function createQueryString(obj) {
var queryString = "";
for (const prop in obj) queryString += `${queryString.length > 1 ? "&" : "?"}${prop}${obj[prop] !== "" ? "=" + obj[prop] : ""}`;
return encodeURI(queryString);
}
// Sets the URL Query String using the key/value pairs in `obj`. Uses getQueryString from below.
function setQueryString(obj) {
const loc = window.location;
const url = `${loc.protocol}//${loc.host}${loc.pathname}${createQueryString(obj)}`;
history.pushState({ path: url }, "", url);
}
// Returns an object containing the URL Query String parameters, or `null` if there is none.
function getQueryString() {
if (window.location.search.length === 0) return null;
const paramsObj = {};
Array.from(new URLSearchParams(window.location.search).entries()).forEach(pair => paramsObj[pair[0]] = pair[1]);
return paramsObj;
}
// Removes all child Nodes from a DOM Element.
function empty(element) {
while (element.hasChildNodes()) element.removeChild(element.lastChild);
}
/// Clones the child nodes of an element into a new Document Fragment.
function newFragmentClone(sourceElem) {
const frag = document.createDocumentFragment();
for (var node of sourceElem.childNodes.values()) {
frag.appendChild(node.cloneNode(true));
}
return frag;
}
// Parses an HTML tagString into DOM nodes in a Document Fragment.
function newFragmentParse(tagString) {
return document.createRange().createContextualFragment(tagString);
}
// Returns a new Function composed from an Array of Functions.
function compose(...functions) {
return function(value) {
for (const curFunc of functions) value = curFunc(value);
return value;
}
}
// (NodeJS fs module) Traverses a filesystem path, creating it along the way.
function plotPath(path) {
path = path.split("/");
path.pop();
var curPath = path.shift();
for (const node of path) {
curPath = curPath + "/" + node;
try {
fs.statSync(curPath);
} catch (error) {
if (error.code === "ENOENT") fs.mkdirSync(curPath);
else throw error;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment