## Utility

#### castArray

Casts the provided value as an array if it's not one.

Use `Array.isArray()` to determine if `val` is an array and return it as-is or encapsulated in an array accordingly.

    const castArray = val => (Array.isArray(val) ? val : [val]);

examples

    castArray('foo'); // ['foo']
    castArray([1]); // [1]

#### cloneRegExp

Clones a regular expression.

Use `new RegExp()`, `RegExp.source` and `RegExp.flags` to clone the given regular expression.

    const cloneRegExp = regExp => new RegExp(regExp.source, regExp.flags);

examples

    const regExp = /lorem ipsum/gi;
    const regExp2 = cloneRegExp(regExp); // /lorem ipsum/gi

#### coalesce

Returns the first non-null/undefined argument.

Use `Array.find()` to return the first non `null`/`undefined` argument.

    const coalesce = (...args) => args.find(_ => ![undefined, null].includes(_));

examples

    coalesce(null, undefined, '', NaN, 'Waldo'); // ""

#### coalesceFactory

Returns a customized coalesce function that returns the first argument that returns `true` from the provided argument validation function.

Use `Array.find()` to return the first argument that returns `true` from the provided argument validation function.

    const coalesceFactory = valid => (...args) => args.find(valid);

examples

    const customCoalesce = coalesceFactory(_ => ![null, undefined, '', NaN].includes(_));
    customCoalesce(undefined, null, NaN, '', 'Waldo'); // "Waldo"

#### extendHex

Extends a 3-digit color code to a 6-digit color code.

Use `Array.map()`, `String.split()` and `Array.join()` to join the mapped array for converting a 3-digit RGB notated hexadecimal color-code to the 6-digit form. `Array.slice()` is used to remove `#` from string start since it's added once.

    const extendHex = shortHex =>
      '#' +
      shortHex
        .slice(shortHex.startsWith('#') ? 1 : 0)
        .split('')
        .map(x => x + x)
        .join('');

examples

    extendHex('#03f'); // '#0033ff'
    extendHex('05a'); // '#0055aa'

#### getURLParameters

Returns an object containing the parameters of the current URL.

Use `String.match()` with an appropriate regular expression to get all key-value pairs, `Array.reduce()` to map and combine them into a single object. Pass `location.search` as the argument to apply to the current `url`.

    const getURLParameters = url =>
      (url.match(/([^?=&]+)(=([^&]*))/g) || []).reduce(
        (a, v) => ((a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1)), a),
        {}
      );

examples

    getURLParameters('http://url.com/page?name=Adam&surname=Smith'); // {name: 'Adam', surname: 'Smith'}
    getURLParameters('google.com'); // {}

#### hexToRGB

Converts a color code to a `rgb()` or `rgba()` string if alpha value is provided.

Use bitwise right-shift operator and mask bits with `&` (and) operator to convert a hexadecimal color code (with or without prefixed with `#`) to a string with the RGB values. If it's 3-digit color code, first convert to 6-digit version. If an alpha value is provided alongside 6-digit hex, give `rgba()` string in return.

    const hexToRGB = hex => {
      let alpha = false,
        h = hex.slice(hex.startsWith('#') ? 1 : 0);
      if (h.length === 3) h = [...h].map(x => x + x).join('');
      else if (h.length === 8) alpha = true;
      h = parseInt(h, 16);
      return (
        'rgb' +
        (alpha ? 'a' : '') +
        '(' +
        (h >>> (alpha ? 24 : 16)) +
        ', ' +
        ((h & (alpha ? 0x00ff0000 : 0x00ff00)) >>> (alpha ? 16 : 8)) +
        ', ' +
        ((h & (alpha ? 0x0000ff00 : 0x0000ff)) >>> (alpha ? 8 : 0)) +
        (alpha ? `, ${h & 0x000000ff}` : '') +
        ')'
      );
    };

examples

    hexToRGB('#27ae60ff'); // 'rgba(39, 174, 96, 255)'
    hexToRGB('27ae60'); // 'rgb(39, 174, 96)'
    hexToRGB('#fff'); // 'rgb(255, 255, 255)'

#### httpGet

Makes a `GET` request to the passed URL.

Use `XMLHttpRequest` web api to make a `get` request to the given `url`. Handle the `onload` event, by calling the given `callback` the `responseText`. Handle the `onerror` event, by running the provided `err` function. Omit the third argument, `err`, to log errors to the console's `error` stream by default.

    const httpGet = (url, callback, err = console.error) => {
      const request = new XMLHttpRequest();
      request.open('GET', url, true);
      request.onload = () => callback(request.responseText);
      request.onerror = () => err(request);
      request.send();
    };

examples

    httpGet(
      'https://jsonplaceholder.typicode.com/posts/1',
      console.log
    ); /*
    Logs: {
      "userId": 1,
      "id": 1,
      "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
      "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
    }
    */

#### httpPost

Makes a `POST` request to the passed URL.

Use `XMLHttpRequest` web api to make a `post` request to the given `url`. Set the value of an `HTTP` request header with `setRequestHeader` method. Handle the `onload` event, by calling the given `callback` the `responseText`. Handle the `onerror` event, by running the provided `err` function. Omit the third argument, `data`, to send no data to the provided `url`. Omit the fourth argument, `err`, to log errors to the console's `error` stream by default.

    const httpPost = (url, data, callback, err = console.error) => {
      const request = new XMLHttpRequest();
      request.open('POST', url, true);
      request.setRequestHeader('Content-type', 'application/json; charset=utf-8');
      request.onload = () => callback(request.responseText);
      request.onerror = () => err(request);
      request.send(data);
    };

examples

    const newPost = {
      userId: 1,
      id: 1337,
      title: 'Foo',
      body: 'bar bar bar'
    };
    const data = JSON.stringify(newPost);
    httpPost(
      'https://jsonplaceholder.typicode.com/posts',
      data,
      console.log
    ); /*
    Logs: {
      "userId": 1,
      "id": 1337,
      "title": "Foo",
      "body": "bar bar bar"
    }
    */
    httpPost(
      'https://jsonplaceholder.typicode.com/posts',
      null, //does not send a body
      console.log
    ); /*
    Logs: {
      "id": 101
    }
    */

#### isBrowser

Determines if the current runtime environment is a browser so that front-end modules can run on the server (Node) without throwing errors.

Use `Array.includes()` on the `typeof` values of both `window` and `document` (globals usually only available in a browser environment unless they were explicitly defined), which will return `true` if one of them is `undefined`. `typeof` allows globals to be checked for existence without throwing a `ReferenceError`. If both of them are not `undefined`, then the current environment is assumed to be a browser.

    const isBrowser = () => ![typeof window, typeof document].includes('undefined');

examples

    isBrowser(); // true (browser)
    isBrowser(); // false (Node)

#### mostPerformant

Returns the index of the function in an array of functions which executed the fastest.

Use `Array.map()` to generate an array where each value is the total time taken to execute the function after `iterations` times. Use the difference in `performance.now()` values before and after to get the total time in milliseconds to a high degree of accuracy. Use `Math.min()` to find the minimum execution time, and return the index of that shortest time which corresponds to the index of the most performant function. Omit the second argument, `iterations`, to use a default of 10,000 iterations. The more iterations, the more reliable the result but the longer it will take.

    const mostPerformant = (fns, iterations = 10000) => {
      const times = fns.map(fn => {
        const before = performance.now();
        for (let i = 0; i < iterations; i++) fn();
        return performance.now() - before;
      });
      return times.indexOf(Math.min(...times));
    };

examples

    mostPerformant([
      () => {
        // Loops through the entire array before returning `false`
        [1, 2, 3, 4, 5, 6, 7, 8, 9, '10'].every(el => typeof el === 'number');
      },
      () => {
        // Only needs to reach index `1` before returning false
        [1, '2', 3, 4, 5, 6, 7, 8, 9, 10].every(el => typeof el === 'number');
      }
    ]); // 1

#### nthArg

Creates a function that gets the argument at index `n`. If `n` is negative, the nth argument from the end is returned.

Use `Array.slice()` to get the desired argument at index `n`.

    const nthArg = n => (...args) => args.slice(n)[0];

examples

    const third = nthArg(2);
    third(1, 2, 3); // 3
    third(1, 2); // undefined
    const last = nthArg(-1);
    last(1, 2, 3, 4, 5); // 5

#### parseCookie

Parse an HTTP Cookie header string and return an object of all cookie name-value pairs.

Use `String.split(';')` to separate key-value pairs from each other. Use `Array.map()` and `String.split('=')` to separate keys from values in each pair. Use `Array.reduce()` and `decodeURIComponent()` to create an object with all key-value pairs.

    const parseCookie = str =>
      str
        .split(';')
        .map(v => v.split('='))
        .reduce((acc, v) => {
          acc[decodeURIComponent(v[0].trim())] = decodeURIComponent(v[1].trim());
          return acc;
        }, {});

examples

    parseCookie('foo=bar; equation=E%3Dmc%5E2'); // { foo: 'bar', equation: 'E=mc^2' }

#### prettyBytes

Converts a number in bytes to a human-readable string.

Use an array dictionary of units to be accessed based on the exponent. Use `Number.toPrecision()` to truncate the number to a certain number of digits. Return the prettified string by building it up, taking into account the supplied options and whether it is negative or not. Omit the second argument, `precision`, to use a default precision of `3` digits. Omit the third argument, `addSpace`, to add space between the number and unit by default.

    const prettyBytes = (num, precision = 3, addSpace = true) => {
      const UNITS = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
      if (Math.abs(num) < 1) return num + (addSpace ? ' ' : '') + UNITS[0];
      const exponent = Math.min(Math.floor(Math.log10(num < 0 ? -num : num) / 3), UNITS.length - 1);
      const n = Number(((num < 0 ? -num : num) / 1000 ** exponent).toPrecision(precision));
      return (num < 0 ? '-' : '') + n + (addSpace ? ' ' : '') + UNITS[exponent];
    };

examples

    prettyBytes(1000); // "1 KB"
    prettyBytes(-27145424323.5821, 5); // "-27.145 GB"
    prettyBytes(123456789, 3, false); // "123MB"

#### randomHexColorCode

Generates a random hexadecimal color code.

Use `Math.random` to generate a random 24-bit(6x4bits) hexadecimal number. Use bit shifting and then convert it to an hexadecimal String using `toString(16)`.

    const randomHexColorCode = () => {
      let n = (Math.random() * 0xfffff * 1000000).toString(16);
      return '#' + n.slice(0, 6);
    };

examples

    randomHexColorCode(); // "#e34155"

#### RGBToHex

Converts the values of RGB components to a color code.

Convert given RGB parameters to hexadecimal string using bitwise left-shift operator (`<<`) and `toString(16)`, then `String.padStart(6,'0')` to get a 6-digit hexadecimal value.

    const RGBToHex = (r, g, b) => ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0');

examples

    RGBToHex(255, 165, 1); // 'ffa501'

#### serializeCookie

Serialize a cookie name-value pair into a Set-Cookie header string.

Use template literals and `encodeURIComponent()` to create the appropriate string.

    const serializeCookie = (name, val) => `${encodeURIComponent(name)}=${encodeURIComponent(val)}`;

examples

    serializeCookie('foo', 'bar'); // 'foo=bar'

#### timeTaken

Measures the time taken by a function to execute.

Use `console.time()` and `console.timeEnd()` to measure the difference between the start and end times to determine how long the callback took to execute.

    const timeTaken = callback => {
      console.time('timeTaken');
      const r = callback();
      console.timeEnd('timeTaken');
      return r;
    };

examples

    timeTaken(() => Math.pow(2, 10)); // 1024, (logged): timeTaken: 0.02099609375ms

#### toCurrency

Take a number and return specified currency formatting.

Use `Intl.NumberFormat` to enable country / currency sensitive formatting.

    const toCurrency = (n, curr, LanguageFormat = undefined) =>
      Intl.NumberFormat(LanguageFormat, { style: 'currency', currency: curr }).format(n);

examples

    toCurrency(123456.789, 'EUR'); // €123,456.79  | currency: Euro | currencyLangFormat: Local
    toCurrency(123456.789, 'USD', 'en-us'); // $123,456.79  | currency: US Dollar | currencyLangFormat: English (United States)
    toCurrency(123456.789, 'USD', 'fa'); // ۱۲۳٬۴۵۶٫۷۹ ؜$ | currency: US Dollar | currencyLangFormat: Farsi
    toCurrency(322342436423.2435, 'JPY'); // ¥322,342,436,423 | currency: Japanese Yen | currencyLangFormat: Local
    toCurrency(322342436423.2435, 'JPY', 'fi'); // 322 342 436 423 ¥ | currency: Japanese Yen | currencyLangFormat: Finnish

#### toDecimalMark

Use `toLocaleString()` to convert a float-point arithmetic to the Decimal mark form. It makes a comma separated string from a number.

    const toDecimalMark = num => num.toLocaleString('en-US');

examples

    toDecimalMark(12305030388.9087); // "12,305,030,388.909"

#### toOrdinalSuffix

Adds an ordinal suffix to a number.

Use the modulo operator (`%`) to find values of single and tens digits. Find which ordinal pattern digits match. If digit is found in teens pattern, use teens ordinal.

    const toOrdinalSuffix = num => {
      const int = parseInt(num),
        digits = [int % 10, int % 100],
        ordinals = ['st', 'nd', 'rd', 'th'],
        oPattern = [1, 2, 3, 4],
        tPattern = [11, 12, 13, 14, 15, 16, 17, 18, 19];
      return oPattern.includes(digits[0]) && !tPattern.includes(digits[1])
        ? int + ordinals[digits[0] - 1]
        : int + ordinals[3];
    };

examples

    toOrdinalSuffix('123'); // "123rd"

#### validateNumber

Returns `true` if the given value is a number, `false` otherwise.

Use `!isNaN()` in combination with `parseFloat()` to check if the argument is a number. Use `isFinite()` to check if the number is finite. Use `Number()` to check if the coercion holds.

    const validateNumber = n => !isNaN(parseFloat(n)) && isFinite(n) && Number(n) == n;

examples

    validateNumber('10'); // true

#### yesNo

Returns `true` if the string is `y`/`yes` or `false` if the string is `n`/`no`.

Use `RegExp.test()` to check if the string evaluates to `y/yes` or `n/no`. Omit the second argument, `def` to set the default answer as `no`.

    const yesNo = (val, def = false) =>
      /^(y|yes)$/i.test(val) ? true : /^(n|no)$/i.test(val) ? false : def;

examples

    yesNo('Y'); // true
    yesNo('yes'); // true
    yesNo('No'); // false
    yesNo('Foo', true); // true