Docs

Everything You Need to Know

Utilities

Use

ChocolateChip-UI provides a number of utility functions for you to use. The first set are as follows:

  • $.noop()
  • $.uuid()
  • $.delay()
  • $.type()
  • $.escapeHTML()
  • $.capitalize()
  • $.mixin()
  • $.compare()
  • $.chunk()
  • $.flatten()
  • $.throttle()
  • $.debounce()
  • $.once()
  • $.before()
  • $.after()

ChocolateChip-UI also provides the following array utilities:

  • array1.difference(array2)
  • array1.intersection(array2)
  • array1.mixin(array2)
  • Array.pluck(property)
  • Array.unique()

$.noop()

$.noop() is a filler function for when you need to pass a callback, but don't want anything to happen. It stands for no operation performed. You can use it like this:

$('button').on('tap', $.noop)

$.uuid()

$.uuid() create a uuid. This is a string. You can use it to create a unique identifier for objects in a collection, or for ids of DOM elements. ChocolateChip-UI uses $.uuid internally for this purpose.

$.delay()

$.delay(milliseconds) allows you to execute a callback with a delay. It is like setTime, except that this returns a promise and you pass your callback to a then function:

// Delay execute by 2 seconds:
$.delay(2000)
  .then(() => {
    // Do whatever you want to here...
  })

If you are targetting older phones running Android 4.x, you will need to include a polyfill for promises for this to work correctly.

$.escapeHTML()

$.escapeHTML(data) escapes the html tags, parenthesis, etc.

Importing Utilities

The previous utilities are included by default in ChocolateChip-UI. To use any of the following utilities you'll need to import them into the app file inside your project's dev folder:

import './src/utils/chunk'
import './src/utils/array_flatten'
import './src/utils/debounce'

$.capitalize()

This method will capitalize a string. By default it capitalizes only the first word in the string. If you pass it a second truthy value, it will caplitalize all words in the string.

import './src/utils/capitalize'

// Capitalize first word:
const sentence = $.capitalize('this is some text.')
// returns: "This is some text."

// Capitalize all words in phrase, use second truthy parameter:
const expression = $.capitalize('another experiment with text', true)
// returns: "Another Experiment With Text"
          

$.mixin()

$.mixin(sourceObject, targetObject) allows you to "mixin" one object into another. If a property already exists on the target object, its property will not be replaced nor will its value be changed. Mixing in a object into another only adds properties from the one object to the target.

import './src/utils/mixin'

// Mixin two objects:
const myObj = {
  name: 'Sam',
  age: 32,
  address: '1234 Main Street'
}
const newObj = {
  job: 'Brain Surgeon',
  salary: '200000',
  age: 99,
  address: 'unknown'
}
$.mixin(newObj, myObj)
console.dir(myObj)
/*
{
  name: 'Sam',
  age: 32,
  address: '1234 Main Street',
  job: 'Brain Surgeon',
  salary: '200000'
}
*/

Notice in the above example that because age and address already existed on myObj that they were not affected by the mixin values. Only new properties were added from newObj to myObj.

$.compare()

$.compare(argument1, argument2) allows you to compare two things and get a boolean response. The items to compare may be simple values, such as strings or numbers, or objects or arrays. For objects and arrays, they must be identical for a match. If the two items match, this returns true, otherwise false.

import './src/utils/compare'

// Compare numbers:
$.compare(1, 1) // returns true
$.compare(1, 2) // returns false

// Compare strings:
const str1 = 'one'
const str2 = 'two'
const str3 = 'one'
$.compare(str1, str2) // returns false
$.compare(str1, str2) // returns true

// Compare objects:
const obj1 = {
  value: 1
}
const obj2 = {
  value: 'whatever'
}
const obj3 = {
  value: 1
}
$.compare(obj1, obj2) // returns false
$.compare(obj1, obj3) // returns true

// Compare arrays:
const array1 = [1,2,3]
const array2 = [4,5,6]
$.compare(array1, [1,2,3]) // returns true
$.compare(array1, array2) // returns false
$.compare([4,5,6], array2) // returns true
          

$.chunk()

$.chunk(data, itemsPerPage) allows you to get back chuncks of an array in a specified size. This is useful where you have a large array items and you want to show it in chunks, such as with the paging widget. It takes the array of data, and the number of items each page should hold. If an array had 100 items, you could break it down into five pages of 20 items each as follows:

import './src/utils/chunk'

// Break array of 100 items into 
// 5 arrays of 20 items each:
const paginatedData = $.chunk(arrayOf100Items, 20)
// paginatedData is an array of five arrays with 20 items each.
paginatedData.length // 5
paginatedData[0].length // 20
paginatedData[1].length // 20
paginatedData[2].length // 20
paginatedData[3].length // 20
paginatedData[4].length // 20

$.flatten(array)

This method takes and array of nested array and returns it flattened. The original array is left untouched. You use it like this:

import './src/utils/flatten'

// Flatten a nested array:
const nestedArray = [[[1], [2], 3, [[4, 5], 6], 7], 8]
const flattenedArray = $.flatten(nestedArray)
// returns [1,2,3,4,5,6,7,8]

Notice:

When using the following utilities that take a function as an argument, be aware of gotchas with arrow functions. If you need the keyword "this" to refer to an element that received an event, use normal functions. Otherwise you can use arrow functions. Or you can use arrow function and access the element through the event.target object in your callback. Notice the difference in how we access the element from these two callback, normal and arrow:

$('li').on('tap', function() {
  // Normal function exposes the list item in "this" keyword:
  alert($(this).text())
})
// Now, using arrow function, 
// we have to access the event object to get the element:
// Use "e.target" to access the tapped list item:
$('li').on('tap', (e) => alert($(e.target).text()))
          

$.throttle()

$.throttle() allows you to control how often a set of events fire. If you are listening for keystokes in an input, you can capture the event a designated amount of time. This helps you avoid a flood of events. This method takes two arguments, a callback to execute and the time in milliseconds to wait before the next execution.

import './src/utils/throttle'

$('input').on('input', $.throttle(function(e) {
  // If only a few letters, exit:
  if (this.value.length < 2) return

  // Output current value of input:
  console.log(this.value)
}, 1000)

You can pass $.throttle a third argument to control when it fires. This third argument is an object of options. By default, $.throttle fires on the leading-edge. You can disable this by passing the object {leading: false}:

$('input').on('input', $.throttle(function(e) {
  // do something here
}, 1000, {leading: false})

By default $.throttle also fires on the trailing-edge. You can disable this by passing the object {trailing: false} as the last argument:

$('input').on('input', $.throttle(function(e) {
  // do something here
}, 1000, {trailing: false})

And of course you can combine both options together:

$('input').on('input', $.throttle(function(e) {
  // do something here
}, 1000, {leading: false, trailing: false})

$.debounce() differs from $.throttle() in that it waits the designated time before firing the event. Given a stream of events, only the last will be executed.

Debounce takes two arguments: a callback and the amount of time in milliseconds before firing.

$.debounce()

import './src/utils/debounce'

$('input').on('input', $.debounce(function(e) {
  // do something here
}, 1000)

In the above example, regardless of how many keystrokes are executed, the callback won't fire until one second after the user stops typing. By default $.debounce fires on the trailing-edge of the wait period. You can force it to fire on the leading-edge by passing a truthy third argument. You might want to do this to avoid an accidental double tap on a submit button:

$('input').on('input', $.debounce(function(e) {
  // do something here
}, 1000, true)

$.once()

There may be times where you only want a function to execute once, no matter how many times the user tries to run it. A submit button is a good example. Using $.once() you can do this. You pass it the function you want to execute, and it returns wrapped so that it will only execute once:

import './src/utils/once'

// Execute function only once:
const alertUser = function(message) {
  alert(message)
}
const newAlert = alertUser('A message from your sponsors!')
$('#alertButton').on('tap', $.once(newAlert)

In the above code, the callback will only execute one time, even if the user taps more times.

NOTICE:

You should not define your callback nor pass it any arguments inside the $.once method. Doing so will cause the callback to be executed as soon as the page loads. Instead take care to define your callback separately and pass it as a simple argument to $.once as done in the example above.

The following code will fail to work properly because we are passing an argument to the callback inside the $.once method:

// Execute function only once:
const alertUser = function(message) {
  alert(message)
}
$('#alertButton').on('tap', $.once(alertUser('A message from your sponsors!'))

$.before(times, callback)

This function takes the number of times and wraps the callback so that it will only execute x times before the times argument is reached. For example, if you pass a times of 4, the callback will execute only the first 3 times. After that it will not execute. Use this method to limit a callback to only execute a specific number of times.

import './src/utils/before'

// Execute the callback only 3 times:
const alertUser = function(message) {
  alert(message)
}
const newAlert = alertUser('A message from your sponsors!')
// Pass 4 so that the callback only executes 3 times:
$('#alertButton').on('tap', $.before(4, newAlert)

NOTICE:

You should not define your callback nor pass it any arguments inside the $.before method. Doing so will cause the callback to be executed as soon as the page loads. Instead take care to define your callback separately and pass it as a simple argument to $.before as done in the example above.

The following code will fail to work properly because we are passing an argument to the callback inside the $.before method:

// Execute the callback only 3 times:
const alertUser = function(message) {
  alert(message)
}
$('#alertButton').on('tap', $.before(4, alertUser('A message from your sponsors!'))

$.after(times, callback)

This function takes the number of times and wraps the callback so that it will only execute on the times attempt. For example, if you pass a times of 4, the callback will not execute until after the fourth attempt. After that the callback will execute on every attempt. Use this method to prevent a callback from being executed until after the specified number of attempts.

import './src/utils/after'

// Execute the callback only on and after 3 attempts:
const alertUser = function(message) {
  alert(message)
}
// Pass 3 so that the callback only executes on and after the third attempt:
const newAlert = alertUser('A message from your sponsors!')
$('#alertButton').on('tap', $.after(3, newAlert)

NOTICE:

You should not define your callback nor pass it any arguments inside the $.after method. Doing so will cause the callback to be executed as soon as the page loads. Instead take care to define your callback separately and pass it as a simple argument to $.after as done in the example above.

The following code will fail to work properly because we are passing an argument to the callback inside the $.after method:

// Execute the callback only on and after 3 attempts:
const alertUser = function(message) {
  alert(message)
}
$('#alertButton').on('tap', $.after(3, alertUser('A message from your sponsors!'))

ChocolateChip-UI provides two functions to enable and dispable form elements:

  • $(input).enable()
  • $(input).disable()

Array Extras

ChocolateChip-UI provides the following array extras. These are polyfills and will not overwrite any existing array methods.

Array.pluck(property)

This method allows you to pluck all objects in the array with that property. It returns a new array of just those property values.

import './src/utils/array_pluck'

// Pluck first names:
const people = [
  {firstName: 'Anne', lastName: 'Kimble'},
  {firstName: 'Howard', lastName: 'Nelson'},
  {firstName: 'Joe', lastName: 'Bodoni'},
  {firstName: 'Sam', lastName: 'Daniels'},
  {firstName: 'Tom', lastName: 'Johnson'}
]
const firstNames = people.pluck('firstName')
// firstNames is: ['Anne', 'Howard', 'Joe', 'Sam', 'Tom']
          

array1.difference(array2)

This method allows you to compare one array against another. It returns all objects in the first array that are not in the second.

import './src/utils/array_difference'

// Find difference:
const people1 = [
  {firstName: 'Sam', lastName: 'Daniels'},
  {firstName: 'Howard', lastName: 'Nelson'},
  {firstName: 'Joe', lastName: 'Bodoni'}
]
const people2 = [
  {firstName: 'Sam', lastName: 'Daniels'},
  {firstName: 'Joe', lastName: 'Bodoni'}
]
const difference = people1.difference(people2)
// difference is [{firstName: 'Howard', lastName: 'Nelson'}]
          

array1.intersection(array2)

This method lets you find all objects or values shared between two arrays.

import './src/utils/array_intersection'

// Find the intersection:
const people1 = [
  {firstName: 'Sam', lastName: 'Daniels'},
  {firstName: 'Howard', lastName: 'Nelson'},
  {firstName: 'Joe', lastName: 'Bodoni'},
  {firstName: 'Anne', lastName: 'Kimble'}
]
const people2 = [
  {firstName: 'Sam', lastName: 'Daniels'},
  {firstName: 'Tom', lastName: 'Johnson'},
  {firstName: 'Joe', lastName: 'Bodoni'}
]
const shared = people1.difference(people2)
/* shared is: [
  {firstName: 'Sam', lastName: 'Daniels'},
  {firstName: 'Joe', lastName: 'Bodoni'}
] */
          

array1.mixin(array2)

This method lets you mixin the objects of one array to another. If the objects already exist in the target, they will not be added.

import './src/utils/array_mixin'

// Mixin in array:
const people1 = [
  {firstName: 'Sam', lastName: 'Daniels'},
  {firstName: 'Howard', lastName: 'Nelson'},
  {firstName: 'Joe', lastName: 'Bodoni'},
  {firstName: 'Anne', lastName: 'Kimble'}
]
const people2 = [
  {firstName: 'Sam', lastName: 'Daniels'},
  {firstName: 'Tom', lastName: 'Johnson'},
  {firstName: 'Joe', lastName: 'Bodoni'}
]
people1.mixin(people2)
/* result:
[
  {firstName: 'Sam', lastName: 'Daniels'},
  {firstName: 'Howard', lastName: 'Nelson'},
  {firstName: 'Joe', lastName: 'Bodoni'},
  {firstName: 'Anne', lastName: 'Kimble'},
  {firstName: 'Tom', lastName: 'Johnson'}
]
*/
          

Array.unique()

[].unique() operates directly on an array. It removes all duplicates from the array upon which it operates.

import './src/utils/array_unique'

const people = [
  {firstName: 'Anne', lastName: 'Kimble'},
  {firstName: 'Anne', lastName: 'Kimble'},
  {firstName: 'Anne', lastName: 'Kimble'},
  {firstName: 'Anne', lastName: 'Kimble'},
  {firstName: 'Howard', lastName: 'Nelson'},
  {firstName: 'Howard', lastName: 'Nelson'},
  {firstName: 'Joe', lastName: 'Bodoni'},
  {firstName: 'Joe', lastName: 'Bodoni'},
  {firstName: 'Joe', lastName: 'Bodoni'},
  {firstName: 'Joe', lastName: 'Bodoni'},
  {firstName: 'Sam', lastName: 'Daniels'},
  {firstName: 'Sam', lastName: 'Daniels'},
  {firstName: 'Tom', lastName: 'Johnson'},
  {firstName: 'Tom', lastName: 'Johnson'},
  {firstName: 'Tom', lastName: 'Johnson'}
]
people.unique()
/* result:
[
  {firstName: 'Anne', lastName: 'Kimble'},
  {firstName: 'Howard', lastName: 'Nelson'},
  {firstName: 'Joe', lastName: 'Bodoni'},
  {firstName: 'Sam', lastName: 'Daniels'},
  {firstName: 'Tom', lastName: 'Johnson'}
]
*/