DEV Community

Eddie
Eddie

Posted on • Edited on

5 JavaScript functions to add to your utilities library

We all have our own utilities - dealing with date/time, validating common forms, etc, or maybe you use a third-party utility library like lodash or underscore. Either way, below is a collection of useful JavaScript functions that you can use to create or expand your utilities library! Enjoy and leave your own utility functions below in the comments.

1. Summarize Text w/ Ellipsis

/**
 * Accepts a string value and returns it back with an ellipsis if the string length 
 * is greater than the max length specified. Otherwise, return the original string.
 */
function summarize(str, max) {
  return str.length > max ? str.substring(0, max) + '...' : str;
}
Enter fullscreen mode Exit fullscreen mode

Example use case (from Medium):
Ellipsis example

Summarize an article / show preview text

2. Add/remove classes on a collection of DOM objects

Extends NodeList by using prototype. It allows us to have jQuery-like functionality for adding and removing classes to multiple objects that have been selected on the DOM using querySelectorAll().

Disclaimer: Generally speaking, extending the core JS API is not recommended, but may be useful and convenient in some isolated use-cases.

NodeList.prototype.addClass = function(className) {
  this.forEach(el => {
    el.classList.add(className);
  });
};

NodeList.prototype.removeClass = function(className) {
  this.forEach(el => {
    el.classList.remove(className);
  });
};
Enter fullscreen mode Exit fullscreen mode

You can then use these like so:

// our way
document.querySelectorAll('.menu-item').addClass('disabled');
document.querySelectorAll('.menu-item').removeClass('disabled');

// standard way
const menuItems = document.querySelectorAll('.menu-item');
menuItems.forEach(el => {
  el.addClass('disabled');
});

// jQuery way
$('.menu-item').addClass('disabled');
$('.menu-item').removeClass('disabled');
Enter fullscreen mode Exit fullscreen mode

3. Function Performance Tester

Test the performance of your functions using console.time(). Also works on async functions as long as you use async/await.

// outputs elapsed execution time of your method to your web console
function perfTest(name, method) {
  console.time(`Method - ${name}`);
  method.apply();
  console.timeEnd(`Method - ${name}`);
}

// usage

// function to test
function square() {
  for (let i = 0; i < 100000; i++) {
    let square = i ** 2;
  }
}

// test it
perfTest('square', square); // output -> Method - square: 3.966064453125ms
Enter fullscreen mode Exit fullscreen mode

4. Dynamic div Generator

If you prefer creating DOM elements dynamically, this may be useful to you. It's a way to create div elements by passing in attributes as an object.

// creates a div, sets provided attributes, returns the div for doing whatever you want with it 
function divMe(attr) {
  const div = document.createElement('div');
  for (let i in attr) {
    div.setAttribute(i, attr[i]);
  }
  return div;
}

// usage
const div = divMe({
  class : 'blue-button',
  'data-id' : 'abc123',
  'aria-label' : 'Close'
});

document.getElementById('container').appendChild(div);
}
Enter fullscreen mode Exit fullscreen mode

5. Group array by key

Returns a new array that is grouped by the key that you defined. Works similarly to GROUP BY operations in SQL.

function groupBy(arr, key) {
  return arr.reduce((acc, i) => {
    (acc[i[key]] = acc[i[key]] || []).push(i);
    return acc;
  }, {});
}

// raw data example
const roleModels = [
  {
    userId: 1,
    name: 'John Williams',
    type: 'Composer'
  },
  {
    userId: 2,
    name: 'Hans Zimmer',
    type: 'Composer'
  },
  {
    userId: 3,
    name: 'Michael Jordan',
    type: 'Athlete'
  },
  {
    userId: 4,
    name: 'J.K. Rowling',
    type: 'Author'
  }
];

const byType = groupBy(roleModels, 'type');

// results (derived):
{
  Athlete: [{...}],
  Author: [{...}],
  Composer: [
    {
      userId: 1,
      name: 'John Williams',
      type: 'Composer'
    },
    {
      userId: 2,
      name: 'Hans Zimmer',
      type: 'Composer'
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Utilities are an excellent way to reuse miscellaneous functions like the above. You may even organize them into modules if you wish. It's up to you! What are some utility functions that you use all the time? Please share in the comments below!

Top comments (7)

Collapse
 
yerac profile image
Rich

Nice. My only comment would be that the ellipsis cut-off should probably subtract the length of the ellipsis, as typically you may want to conform to a database field size. I.e varchar(100) you could end up with 103 chars including the ellipsis,

so like:

function summarize(str, max) {
  return str.length > max ? str.substring(0, max-3) + '...' : str;
}
Collapse
 
slowmove profile image
Erik Hoffman

Even better, it should split at the end of a word and not in the middle of one

function summarize(str, max) {
  if (str.length <= max) return str;
  const subString = str.substring(0, max - 1);
  return subString.substring(0, subString.lastIndexOf(" ")) + "...";
}
Collapse
 
mottie profile image
Rob Garrison

Even better, use the unicode ellipsis (; \u2026).

Collapse
 
vonheikemen profile image
Heiker

If you sprinkle a little "data last" with some partial application and you really got something on the groupBy.

- function groupBy(arr, key) {
+ function groupBy(key, arr) {
+  if(arguments.length === 1) {
+    return groupBy.bind(null, key);
+  }

  return arr.reduce(
   (acc, i) => {
      (acc[i[key]] = acc[i[key]] || []).push(i);
      return acc;
    }, {});
}

Now you can have a factory of functions:

const groupByType = groupBy('type');
const groupByName = groupBy('name');
// and many more

groupByType(roleModels) // stuff...

// or just call it like a normal person
groupBy('type', roleModels);
Collapse
 
orelkan profile image
Orel Kanditan

It's a neat trick, but it's a little YAGNI isn't it? I can't really think of a situation where I would use this

Collapse
 
vonheikemen profile image
Heiker

Is certainly not necessary. You can always wrap the thing in another function.

const groupByType = arr => groupBy(arr, 'type');

It does come handy when callbacks are involve.

// function composition in ramda style
const complexFunc = pipe(someFunc, groupBy('type'), otherFunc);

// when mapping
someArrWithStuff.map(groupBy('type'));

// a raw promise (if you are one of those)
ipromise.then(groupBy('type'));

Some comments may only be visible to logged-in visitors. Sign in to view all comments.