npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

batarang

v2.3.3

Published

Tiny javascript functions to attack not-so-everyday problems

Downloads

981

Readme

A utility belt of tiny javascript functions to attack common business problems.

  • [x] Pure functions
  • [x] Lightweight
  • [x] Individual imports
yarn add batarang

OR

npm install batarang --save

Require individual functions from the library so you only load what you need e.g.

var getQueryString = require('batarang/getQueryString');

Running tests

yarn test

OR

npm run test

Array

  • pluckUniqueValues
  • swapArrayItems
  • excludeFromList
  • sortByField
  • arrayToMap
  • cycle
  • segregate
  • segregateBy
  • intersperseWith

URL

  • getQueryString
  • getQueryParams
  • getHostNameFromUrl
  • createUrl
  • createRouter
  • getYoutubeVideoId

MISC

  • retryPromise

  • delayPromise

  • getInitials

  • capitalizeFirstChar

  • getCSVWords

  • getRangeWindow

  • isEnterKey

  • slugify

  • reloadPage

  • getRandomBetween

  • getTotal

  • isBetween

  • percentOf


Array Utilities

pluckUniqueValues(array, [fieldName='id'])

Given an array of objects, gets all the unique values of a given key. The default key is id.

var items = [
  {id: 1, name: 'one'},
  {id: 2, name: 'two'},
  {id: 1, name: 'one'},
  {id: 2, name: 'two'}
];

pluckUniqueValues(items);
// [1, 2] All the unique values of id

pluckUniqueValues(items, 'name');
// ['one', 'two'] All the unique values of name
swapArrayItems(array, number, number)

Returns an new array with the items at the given indexes swapped.

var arr = [{a: 1}, {b: 2}, {c: 3}, {d: 4}];
swapArrayItems(arr, 1, 3);
// [{a: 1}, {d: 4} , {c: 3}, {b: 2}]
excludeFromList(array, array, [fieldName='id'])

Excludes items from the first array of objects if the value of an item's specific field name is present the second input array.

Returns a new array.

var idsToRemove = [2, 3];
var items = [
  {id: 1, name: 'a'},
  {id: 2, name: 'b'},
  {id: 3, name: 'c'}
];

excludeFromList(items, idsToRemove);
// [{id: 1, name: 'a'}]

var namesToRemove = ['b'];
excludeFromList(items, namesToRemove, 'name');
// [{id: 1, name: 'a'}, {id: 3, name: 'c'}]

sortByField(array, fieldName, [order='ASC'])

Given an array of objects, sort the objects in ascending or descending order based on the value of a key.

var items = [{id: 2}, {id: 4}, {id: 1}, {id: 3}];
sortByField(items, 'id');
// [{id: 1}, {id: 2}, {id: 3}, {id: 4}]

sortByField(items, 'id', 'DESC');
// [{id: 4}, {id: 3}, {id: 2}, {id: 1}]
arrayToMap(array, [fieldName='id'])

Converts an array of objects into a hash, where the key is one of the object properties. This is useful when you want convert an array of data you recieve from the server into a lookup hash to show on the UI based on the some field. The default key is 'id'.

var rows = [
  {id: 1, age: 10},
  {id: 2, age: 12}
];

arrayToMap(rows);
// { 1: {id: 1, age: 10}, 2: {id: 2, age: 12} }

// Using custom property as key
arrayToMap(rows, 'age');
// { 10: {id: 1, age: 10}, 12: {id: 2, age: 12} }

var composite = [
  {emp_id: 1, mgr_id: 11},
  {emp_id: 1, mgr_id: 12}
];

function selector(item) {
  return item.emp_id + '_' + item.mgr_id;
}

// Using a selector function
arrayToMap(rows, selector);
// { '1_11': {emp_id: 1, mgr_id: 11}, '1_12': {emp_id: 1, mgr_id: 12} }
cycle(Array)

Returns an object that has 4 functions - next(), nextVal(), prev() and prevVal() that lets you cycle through the items in an array. This next and previous function return values that are compatible with the ES6 iteratable protocal in mind. For regular usage, you are more likely to go with the nextVal and prevVal functions.

var items1 = ['a', 'b'];
var iter1 = cycle(items1);
iter1.next(); // { value: 'a', index: 0, done: false }
iter1.next(); // { value: 'b', index: 1, done: false }
iter1.next(); // { value: 'a', index: 0, done: false }

iter1.nextVal(); // 'b'

var items2 = ['x', 'y'];
var iter2 = cycle(items2);
iter2.prev(); // { value: 'y', index: 1, done: false }
iter2.prev(); // { value: 'x', index: 0, done: false }
iter2.prev(); // { value: 'y', index: 1, done: false }

iter2.prevVal(); // 'x'
segregate(groupingArray, itemArray)

Divides the item array into smaller arrays whose sizes are specified in the grouping array. Returns an array. E.g.

var items = ['a', 'b', 'c', 'd', 'e'];
var groups = [1, 2, 2]; // Intended size of each sub array

var result = segregate(groups, items);

// result[0] = ['a']
// result[1] = ['b', 'c']
// result[2] = ['d', 'e']
segregateBy(function, itemArray)

Similar to segregate, but groups items based on an evaluation of the conditional function. Each item of the array is passed to the function for evaluation. Returns a hash. E.g.

var items = [
  {name: 'a', val: 1},
  {name: 'b', val: 2},
  {name: 'c', val: 3},
  {name: 'd', val: 4}
];

// Checks if a function is even or odd
function condition(item) { return item.val % 2 === 0 ? 'even' : 'odd'; };
var result = segregateBy(condition, items);

// result
// {
//    even: [{name: 'b', val: 2}, {name: 'd', val: 4}],
//    odd: [{name: 'a', val: 1}, {name: 'c', val: 3}]
// }
intersperseWith(function, itemArray)

Inserts the return value of a function into an array. This is very similar to Ramda's intersperse with the only difference being that it invokes a function for every index at which the separator will be insered e.g. This is especially handy if you have an array of dom nodes or react elements and want to insert some other dom nodes, like dom separators

var items = [
  "<span>FOO</span>",
  "<span>BAR</span>",
  "<span>BAZ</span>",
];

function getElement(idx) { return `<span key="separator-${idx}">--</span>` };

var result = getElement(getSeparator, items)

// result
// [
//    "<span>FOO</span>",
//    "<span key="separator-1">--</span>"
//    "<span>BAR</span>"
//    "<span key="separator-3">--</span>"
//    "<span>BAZ</span>"
// ]

URL Utilities

getQueryString(url)

Returns the query string of a URL

var url = 'https://www.youtube.com/results?search_query=the+dark+knight';
getQueryString(url);
// search_query=the+dark+knight
getQueryParams(url, [key])

Given a url, and a key, returns the values of the key if it is present as a query parameter. If no key is provided, it returns a hash of all the query parameters. Single values are returned as strings Multiple values are returned as arrays

This function handles the basic use case for processing the query params. If you need something more advanced, look at qs.

var url = 'https://www.youtube.com/watch?v=CqlNSVZpbAg';
var multiValues = ''https://www.example.com?x=1&x=11&y=2&z=3'';

getQueryParams(url, 'v'); // CqlNSVZpbAg
getQueryParams(multiValues, 'name'); // ['1', '11']
getQueryParams(multiValues); // { x: ['1', '11'] , y: '2', z: '3' }
getHostNameFromUrl(url)

Returns the hostname from a url. At the moment only works on the browser since it uses document to create an in-memory anchor tag to extract a url.

getHostNameFromUrl('https://www.youtube.com/watch?v=KFHccsaTakg');
// www.youtube.com
createUrl(urlPattern, [options], [config])

Constructs a url from a pattern. Optionally pass params and query in the options to be processed for generating the URL.

  • options.query: An object that will be converted to queryString
  • options.params: An object whose keys will be looked up in the ur pattern and replaced by its values.
  • config.query: Configuration for options.query processing. It uses the stringify function in the query-string. Useful when you want to parse different array formats etc.
  • config.params: Configuration for options.params processing. It uses the compile function from path-to-regexp
  • config.encode: A boolean that if set to false will disable encoding for both, query and params.
var params = {id: 'r$', team_id: 2};
var query = {page: 1, sort: 'name'};
var urlPattern = 'https://api.com/users/:id/teams/:team_id';

createUrl(urlPattern, {params, query});
// Output => 'https://api.com/users/r%24/teams/2?page=1&sort=name'

createUrl(urlPattern, {params, query}, {encode: false});
// Output => 'https://api.com/users/r$/teams/2?page=1&sort=name'
createRouter(routes)

Creates a router object from a hash of named routes i.e. your sitemap. Named routes let you access the url patterns of your application all throughout your code by simply using a name and offload the actual url construction with parameters and query strings to the router.get method.

router.get(pathName, [options], [config])

  • pathName: The name of the route you want to retrieve from the sitemap.
  • options: A hash of of the structure {params, query}. It uses createUrl as documented above to generate the final URL.
  • config: The optional configuration that will be passed to createUrl for transforming options.query and options.params. See createUrl for more details.
const router = createRouter({
  'products': '/products',
  'product': '/products/:p'
  'product_items': '/products/:p/items'
});

router.get('product_items')
//=> /products/:p/items

router.get('products', {query: {page: 1, sort: 'name'}});
//=> '/products?page=1&sort=name'

router.get('product_items', {query: {sort: 'name'}, params: p: 'boat'});
//=> '/products/boat/items&sort=name'
getYoutubeVideoId(url)

Given a youtube video URL, returns the its video id

var url = 'https://www.youtube.com/watch?v=EXeTwQWrcwY';
var playlistUrl = 'https://www.youtube.com/watch?v=ZRG1tWQN6e8&list=PLatdFpOvGjYGM6SMVXz1jpJMJdeHLKJun';
var shortUrl = 'https://youtu.be/VLXyMzCi7Mo';
var embedUrl = 'https://www.youtube.com/embed/VLXyMzCi7Mo';

getYoutubeVideoId(url); // EXeTwQWrcwY
getYoutubeVideoId(playlistUrl); // ZRG1tWQN6e8
getYoutubeVideoId(shortUrl); // ZRG1tWQN6e8
getYoutubeVideoId(embedUrl); // ZRG1tWQN6e8

Misc Utilities

retryPromise(method, options)

Given a method that returns a promise that resolves or rejects, this function returns a retryable method, which will automatically retry the method when the promise is rejected. Its very similar to a debounce/throttle. The retryable method returned can be use as a drop in replacement of the original method.

  • method:(Required) The method that needs to be retried. The method must return a promise.
  • options.retries:(Optional, default: 1) Number of times method will be invoked after first failure.
  • options.retryArgs:(Optional) If you want to pass a different set of arguments when the function is being retried, pass an array of arguments here. By default all retries are invoked with the same arguments as the original invocation.
  • options.validator: (Optional) Function that is invoked on promise resolution with the promise result, to which you can apply custom logic to determine if the result was a success or failure. Return false from this function if you want to continue retrying, return true to exit.
function alwaysReject() {
  console.log('return rejection');
  return Promise.reject();
}
var retryableAlwaysReject = retryPromise(alwaysReject, {
  retry: 2
});
retryableAlwaysReject(); // Prints 'return rejection' 3 times in total

function badValue() {
  console.log('returns bad value');
  return Promise.resolve(400);
}
var retryableBadValue = retryPromise(badValue, {
  validator: function () { return value !== 400; }
});
retryableBadValue(); // Prints 'returns bad value' 2 times in total
delayPromise(time, value)

Returns a promise that is delayed by the specified time.

  • If 'value' is provided, it is the resolved value of the promise
delayPromise(500).then(() => console.log('done'));
delayPromise(500, 'val').then((val) => console.log(val === 'val'));
getInitials(string)

Returns the initials for a name. The name can have multiple words, or spaces. It only selects the first and last words to deterime the first and last name and extracts the first character from them to generate initials.

getInitials("barack Hussein obama") // "BO"
getInitials("barack Hussein Obama") // "BO"
getInitials("Barack") // "B"
getInitials(" Barack Hussein with extra words and spaces    obama    ") // BO
capitalizeFirstChar(string)

Capitalize the first character of a string. Keeps the rest of the string the same.

capitalizeFirstChar('exampLestRing');
// ExampLestRing
getCSVWords(string)

For a given comma separated string, returns and array of words split by comma. Trims blank spaces and omits empty characters.

getCSVWords(',  hello,, ,    ,world, ,');
// ['hello', 'world']
getRangeWindow(index, maxIndex, size)

Given index, return an array of maximum length size, such that

  • index is present in the array.
  • items to the right of the index are larger than index.
  • items on the left of the index are smaller than index.

This is useful for creating buttons that represent page numbers in a pagination toolbar.

getRangeWindow(0, 10, 4) // [0, 1, 2, 3]
getRangeWindow(0, 2, 4) // [0, 1, 2]
getRangeWindow(2, 3, 4) // [0, 1, 2, 3]
getRangeWindow(3, 3, 2) // [2, 3]
isEnterKey(event)

Given an event object, returns true if it represents the enter key.

var event = {keyCode: 13};
isEnterKey(event); // true

event = {keyCode: 1000};
isEnterKey(event) // false
slugify(text)

Generates a hyphenated (url safe) form of a string

slugify('my slug string'); // my-slug-string


reloadPage([boolean=false])

Reloads the page. This is just a wrapper around window.location.reload so it will only work on the client. A boolean argument of true forces it to reload from the server - and you thereby lose the scroll positioning. Read more at MDN

reloadPage(); // Attempts to reload page from the cache

reloadPage(true); // Attempts to reload page from the server

getRandomBetween(min, max)

Returns a random number between min and max

getRandomBetween(10, 20);

getTotal(key, array)

Given an array of objects, return a sum of values for the specified key for each item. This is a curried function.

var items = [
  {wins: 1, games: 4},
  {wins: 2, games: 2},
  {wins: 3, games: 5}
];
getTotal('wins', items) // 5
getTotal('games', items) // 11

isBetween({min, max}, number)

Returns true if the number is within range. This is a curried function.

var range = {min: 10, max: 20};
isBetween(range, 11) // true
isBetween(range, 100) // false

percentOf(total, percent)

Returns value from the total that represents the percentage. This is a curried function.

percentOf(25, 20) // 5 is 20 percent of 25

// The curried form makes it more obvious
var twentyFivePercentOf = percentOf(25);
twentyFivePercentOf(20) // 5

Some additional notes and legacy functions are documented in the wiki

License

MIT