Skip to content

Javascript (JS) Snippets

A place for me to pop useful or interesting JS snippets.

Debouncing

Debouncing in javascript, really useful when you wan't to stop and event firing too often. E.g. listening to key inputs.

js
// Debounce function
const debounce = (fn, delay = 300) => {
    let timerId = null;
    return (...args) => {
        clearTimeout(timerId);
        timerId = setTimeout(() => fn(...args), delay);
    };
};

Pick Random From and Array

Modelled on the {array}.pick() function in gdscript.

js
// Picks a random item from array
function pickArrayRandom(arr) {
  return arr[Math.floor(Math.random() * arr.length)];
}

Pick Random From and Object

Modelled on the {array}.pick() function in gdscript.

js
// Picks a random item from array
function pickObjectRandom(obj) {
  const keys = Object.keys(obj);
  return keys[Math.floor(Math.random() * keys.length)];
}

Get a random sub array from parent array

js
// Get a random array of n length from the parent array
function randomSubset(n, arr) {
  const shuffled = array.sort(() => 0.5 - Math.random());
  return shuffled.slice(0, n);
}

Random integer

js
const randomInt = (low = 1, high = 6) => {
  return Math.floor(Math.random() * (high - low + 1) + low);
};

Random float

js
const randomFloat = (low = 0, high = 1, digits = 1) => {
  let val = Math.random() * (high - low) + low; // this will get a number between low and high;
  return +val.toFixed(digits);
};

Random between

JS
// Inclusive
function randomBetween(min = 0, max = min, digits = 0) {
  const result = min + (max - min) * Math.random();
  return result.toFixed(digits);
}

Rolling a dice

JS
function rollDice(sides, modifier = 0) {
  return Math.floor(Math.random() * sides) + 1 + modifier;
}

Is even

Yeah I know this is basic...shut up.

JS
export function isEven(number) {
  return number % 2 === 0; //returns true or false!
}

Ordinal

Function to get the ordinal description of an integer.

JS
export function ordinal(number) {
  const rule = new Intl.PluralRules("en-gb", { type: "ordinal" });
  // rule.select returns one of the following
  const ordinals = {
    one: "st",
    two: "nd",
    few: "rd",
    many: "th",
    zero: "th",
    other: "th",
  };

  return `${number}${ordinals[rule.select(number)]}`;
}

Roll20 Style roll parsing

This assumes you've also got the rollDice function.

JS
// function to parse roll strings a la roll20
export function parseRollString(inputStr) {
  const str = inputStr.toLowerCase();
  const keepTypes = ["kl", "kh"];
  const operators = ["+", "-"];
  let result = 0;

  // check the string is valid
  const regTest = /([\d]+d[\d]+)([-+*/]{1}[\d]+)?((kl|kh){1}\d+)?/i;
  if (regTest.test(str) == false) {
    console.warn("Invalid string");
    return false;
  }

  // split the string
  const reg = /(\d)+|d|(kl)|(kh)|[+\-*/]/gi;
  const match = str.match(reg);

  const data = {
    str,
    rollCount: Number(match[0]),
    dice: Number(match[2]),
    rolls: [],
  };

  // if there is a modifer
  if (operators.includes(match[3])) {
    data.operator = match[3];
    data.operatorValue = Number(match[4]);
  }

  // if there is a modifier and keepType
  if (keepTypes.includes(match[5])) {
    data.keepType = match[5];
    data.keep = Number(match[6]);
  }

  // if there is no modifer but a keepType
  if (keepTypes.includes(match[3])) {
    data.keepType = match[3];
    data.keep = Number(match[4]);
  }

  // roll the dice & apply modifier
  for (let i = 1; i <= data.rollCount; i++) {
    const initial = rollDice(data.dice); // don't add modifer here!!! 😱😱
    const roll = { initial, value: initial };
    if ("operator" in data) {
      roll.value = roll.initial + Number(data.operator + data.operatorValue);
    }
    data.rolls.push(roll);
  }

  // may as well calc the result for basic rolls
  result = data.rolls.reduce((a, c) => a + c.value, 0);

  // create an ordered copy of rolls in desc order
  const sortedRolls = data.rolls.toSorted((a, b) => b.value - a.value);
  data.rolls = sortedRolls
  console.log(sortedRolls)

  if (data.keepType == "kl") {
    data.kept = sortedRolls.slice(-data.keep);
    result = data.kept.reduce((a, c) => a + c.value, 0);
  }

  if (data.keepType == "kh") {
    data.kept = sortedRolls.slice(0, data.keep);
    result = data.kept.reduce((a, c) => a + c.value, 0);
  }

  return { value: result, data };

Object key by weight

js
// Selects a key from an object assuming the value is it's weight.
export function keyByWeight(obj) {
  const totalWeight = Object.values().reduce((a, val) => a + val, 0);
  const randomChance = Math.floor(Math.random() * totalWeight);
  let currentMax = 0;
  let result;

  for (const d of Object.keys(obj)) {
    currentMax += obj[d];
    if (randomChance <= currentMax) {
      result = d;
      break;
    }
  }

  return result;
}

Convert string into HTML

Really useful, but be aware of Cross Site Scripting. Ref: Wesbos: HTML from Strings and XSS

js
const myHTML = `<div>Magic beans!<div>`;
const myFragment = document.createRange().createContextualFragment(myHTML);

Basic numerical IDs

This will make a JS generator function (thats what the function* does), the function will keep track of it's last yield and increment the number each time the function runs. Closer to DB ids than anything else.

JS
function* idGenerator(start = 0) {
  let index = start;
  while (true) {
    yield index++;
  }
}

const gen = idGenerator();
console.log(gen.next().value); // 0
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
console.log(gen.next().value); // 3