Skip to content

Instantly share code, notes, and snippets.

@crazy4groovy
crazy4groovy / commonjs-amd-browser-support.js
Created January 11, 2016 15:39
ifandelse.com/its-not-hard-making-your-library-support-amd-and-commonjs
(function (root, factory) {
if(typeof define === "function" && define.amd) {
// Now we're wrapping the factory and assigning the return
// value to the root (window) and returning it as well to
// the AMD loader.
define(["postal"], function(postal){
return (root.myModule = factory(postal));
});
} else if(typeof module === "object" && module.exports) {
// I've not encountered a need for this yet, since I haven't
@crazy4groovy
crazy4groovy / layout.css
Created December 13, 2023 17:10
CSS grid page layout "holy grail" for optional header, footer, sidebar; required content is scrollable (CSS)
body, .grid-wrapper {
height: 100vh;
padding: 0;
margin: 0;
}
.grid-wrapper {
display: grid;
grid-template-columns: minmax(0, 200px) minmax(80vw, 1fr);
grid-template-rows: auto 1fr auto;
@crazy4groovy
crazy4groovy / cacher.ts
Last active December 1, 2023 17:24
simple TTL cache, and cache repo; excellent Promise/async deduper (JavaScript, TypeScript)
export function cacher<T>(thunk: () => Promise<T>, ttlSeconds = 60) {
const noCache: unique symbol = Symbol("cache");
let cache: Promise<T> | symbol = noCache;
return function execThunk(): Promise<T> {
if (typeof cache !== "symbol") {
return cache;
}
cache = thunk();
@crazy4groovy
crazy4groovy / useScrollTracker.ts
Created December 1, 2023 17:16
A React hook for scroll position tracking (JavaScript)
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
interface ScrollTrackerResult {
isScrollable: boolean;
isAtTop: boolean;
isAtBottom: boolean;
}
function useScrollTracker(ref: React.RefObject<HTMLElement>): ScrollTrackerResult {
const [isScrollable, setIsScrollable] = useState(false);
@crazy4groovy
crazy4groovy / muiCustomToolTip.tsx
Created December 1, 2023 17:13
A custom styled MUI tooltip component with body (JavaScript)
import React from "react";
import ReactDOM from "react-dom";
import { Tooltip, Popper, TooltipProps } from "@mui/material";
import { styled } from "@mui/material/styles";
const StyledPopper = styled(Popper)({
padding: "1rem", // offset for larger arrow size
"& .MuiTooltip-tooltip": {
backgroundColor: "white",
@crazy4groovy
crazy4groovy / dl.deno.ts
Last active November 14, 2023 22:56
scrape midjourney "recent showcase" images (into folder, per hour) (JavaScript, Deno)
import { Timeout, TimeoutError } from "https://deno.land/x/timeout/mod.ts"
const delay = (ms) => new Promise((res) => setTimeout(res, ms));
function newThrottler({ isBusy, lock, unlock, waitMs, size }) {
async function throttler(cb, ...args) {
size(1);
await Promise.resolve();
while (!!isBusy()) {
await delay(waitMs()); // waits in event loop queue, until it interrupts for another attempt!
@crazy4groovy
crazy4groovy / lazyMergeSort.js
Last active November 3, 2023 21:30
sort large arrays using the event loop (JavaScript)
function chunkedMergeSort(arr, callback) {
function merge(left, right, arr, callback) {
let i = 0;
let j = 0;
let k = 0;
function mergeStep() {
while (i < left.length && j < right.length) {
if (left[i] <= right[j]) {
arr[k++] = left[i++];
@crazy4groovy
crazy4groovy / onDeploy.js
Created October 31, 2023 22:35
client side script that detects deployment changes, callback (JavaScript)
export default function detectDeployment(
onDeployDetected: () => void,
timeoutSec = 60 * 60 // default 1 hour
) {
const scriptFiles = { cache: "" }; // as object for pointer reference
const profit$ = () =>
handleDetectScriptFileChanges(onDeployDetected, scriptFiles);
setInterval(profit$, timeoutSec * 1000);
@crazy4groovy
crazy4groovy / export-bookmarklet.href
Last active September 27, 2023 16:35
export your Diigo bookmarks from a logged-in account page in browser console (JavaScript)
javascript:'use%20strict';void%20function(){(async%20function(){async%20function%20a(a){return%20fetch(%22https://www.diigo.com/interact_api/load_user_items%3Fpage_num=%22+a+%22%26sort=updated%26count=96%22).then(function(a){return%20a.json()})}function%20b(b,c){var%20d=2%3Carguments.length%26%26arguments[2]!==void%200%3Farguments[2]:%22text/plain%22,e=new%20Blob([b],{type:d}),f=document.createElement(%22a%22);f.href=URL.createObjectURL(e),f.download=c,f.click(),URL.revokeObjectURL(f.href)}if(confirm(%22Begin%20export%20to%20diigo-bookmarks.json%3F%20(please%20be%20patient!!)%22)){for(var%20c=-1,d=[];;){var%20e=await%20a(++c),f=e.items;if(f=f.map(function(a){return{description:a.description,tags:a.tags.split(%22,%22),title:a.title,type_name:a.type_name,url:a.url}}),d=d.concat(f),96%3Ef.length)break}console.log({l:d.length});var%20g=JSON.stringify(d,null,2);b(g,%22diigo-bookmarks.json%22)}})()}();
// Create store accepts reducers map and initial state
function* createStore(reducers, initialState = {}) {
// Initialize state
let state = initialState;
// Extract the reducer keys upfront
const reducerKeys = Object.keys(reducers);
// Combine all reducers into one reducing function
const combinedReducer = (state, action) => {
return reducerKeys.reduce((newState, key) => {
// Pass slice of state into corresponding reducer