npm package: @monogrid/js-utils
Description: Javascript utilities
Author: MONOGRID S.R.L.
Latest version: 1.1.0

# @monogrid/js-utils

> This is a collection of generic Javascript utilities to help develpment on MONOGRID sites.

## Installation

```bash
npm install --save @monogrid/js-utils
```

or

```bash
yarn add @monogrid/js-utils
```

## Modules

<dl>
<dt><a href="#module_FileUtils">FileUtils</a></dt>
<dd><p>A collection of File related utilities.</p>
</dd>
<dt><a href="#module_normalizeWheel">normalizeWheel</a></dt>
<dd><p>An utility function to normalize the mouseWheel input in the browser.</p>
</dd>
<dt><a href="#module_NumberUtils">NumberUtils</a></dt>
<dd><p>A collection of Number related utilities</p>
</dd>
<dt><a href="#module_ObjectUtils">ObjectUtils</a></dt>
<dd><p>A collection of Object related utilities</p>
</dd>
<dt><a href="#module_Platform">Platform</a></dt>
<dd><p>Holds information on the Platform where this code is run</p>
</dd>
<dt><a href="#module_VueUtils">VueUtils</a></dt>
<dd><p>A collection of Vue.js related utilities</p>
</dd>
</dl>

## Classes

<dl>
<dt><a href="#ElasticNumber">ElasticNumber</a></dt>
<dd></dd>
<dt><a href="#Gyroscope">Gyroscope</a></dt>
<dd></dd>
<dt><a href="#RAF">RAF</a></dt>
<dd></dd>
</dl>

<a name="module_FileUtils"></a>

## FileUtils
A collection of File related utilities.


* [FileUtils](#module_FileUtils)
    * [~downloadFile(content, fileName, contentType)](#module_FileUtils..downloadFile)
    * [~loadFile([accept])](#module_FileUtils..loadFile) ⇒ <code>Promise.&lt;Array&gt;</code>
    * [~loadJSON()](#module_FileUtils..loadJSON) ⇒ <code>Promise.&lt;String&gt;</code>
    * [~loadImage()](#module_FileUtils..loadImage) ⇒ <code>Promise.&lt;Image&gt;</code>

<a name="module_FileUtils..downloadFile"></a>

### FileUtils~downloadFile(content, fileName, contentType)
Downloads a file to the user's machine.

**Kind**: inner method of [<code>FileUtils</code>](#module_FileUtils)  

| Param | Type | Description |
| --- | --- | --- |
| content | <code>String</code> | The content to be downloaded. |
| fileName | <code>String</code> | The name of the file downloaded into the user's PC. |
| contentType | <code>String</code> | The file type. |

<a name="module_FileUtils..loadFile"></a>

### FileUtils~loadFile([accept]) ⇒ <code>Promise.&lt;Array&gt;</code>
Prompts the user to select a single file from his harddrive.

**Kind**: inner method of [<code>FileUtils</code>](#module_FileUtils)  
**Returns**: <code>Promise.&lt;Array&gt;</code> - Array of files selected by the user.  

| Param | Type | Description |
| --- | --- | --- |
| [accept] | <code>String</code> | Accept string to restrict file selection to certain file types. |

<a name="module_FileUtils..loadJSON"></a>

### FileUtils~loadJSON() ⇒ <code>Promise.&lt;String&gt;</code>
Prompts the user to select a single JSON file from his harddrive
and returns the result of his selection.

**Kind**: inner method of [<code>FileUtils</code>](#module_FileUtils)  
**Returns**: <code>Promise.&lt;String&gt;</code> - The parsed JSON file.  
<a name="module_FileUtils..loadImage"></a>

### FileUtils~loadImage() ⇒ <code>Promise.&lt;Image&gt;</code>
Prompts the user to select a single JSON file from his harddrive
and returns the result of his selection

**Kind**: inner method of [<code>FileUtils</code>](#module_FileUtils)  
**Returns**: <code>Promise.&lt;Image&gt;</code> - The selected image object.  
<a name="module_normalizeWheel"></a>

## normalizeWheel
An utility function to normalize the mouseWheel input in the browser.

**Typechecks**:   
<a name="module_normalizeWheel..normalizeWheel"></a>

### normalizeWheel~normalizeWheel()
Mouse wheel (and 2-finger trackpad) support on the web sucks.  It is
complicated, thus this doc is long and (hopefully) detailed enough to answer
your questions.

If you need to react to the mouse wheel in a predictable way, this code is
like your bestest friend. * hugs *

As of today, there are 4 DOM event types you can listen to:

  'wheel'                -- Chrome(31+), FF(17+), IE(9+)
  'mousewheel'           -- Chrome, IE(6+), Opera, Safari
  'MozMousePixelScroll'  -- FF(3.5 only!) (2010-2013) -- don't bother!
  'DOMMouseScroll'       -- FF(0.9.7+) since 2003

So what to do?  The is the best:

  normalizeWheel.getEventType()

In your event callback, use this code to get sane interpretation of the
deltas.  This code will return an object with properties:

  spinX   -- normalized spin speed (use for zoom) - x plane
  spinY   -- " - y plane
  pixelX  -- normalized distance (to pixels) - x plane
  pixelY  -- " - y plane

Wheel values are provided by the browser assuming you are using the wheel to
scroll a web page by a number of lines or pixels (or pages).  Values can lety
significantly on different platforms and browsers, forgetting that you can
scroll at different speeds.  Some devices (like trackpads) emit more events
at smaller increments with fine granularity, and some emit massive jumps with
linear speed or acceleration.

This code does its best to normalize the deltas for you:

  - spin is trying to normalize how far the wheel was spun (or trackpad
    dragged).  This is super useful for zoom support where you want to
    throw away the chunky scroll steps on the PC and make those equal to
    the slow and smooth tiny steps on the Mac. Key data: This code tries to
    resolve a single slow step on a wheel to 1.

  - pixel is normalizing the desired scroll delta in pixel units.  You'll
    get the crazy differences between browsers, but at least it'll be in
    pixels!

  - positive value indicates scrolling DOWN/RIGHT, negative UP/LEFT.  This
    should translate to positive value zooming IN, negative zooming OUT.
    This matches the newer 'wheel' event.

Why are there spinX, spinY (or pixels)?

  - spinX is a 2-finger side drag on the trackpad, and a shift + wheel turn
    with a mouse.  It results in side-scrolling in the browser by default.

  - spinY is what you expect -- it's the classic axis of a mouse wheel.

  - I dropped spinZ/pixelZ.  It is supported by the DOM 3 'wheel' event and
    probably is by browsers in conjunction with fancy 3D controllers .. but
    you know.

Implementation info:

Examples of 'wheel' event if you scroll slowly (down) by one step with an
average mouse:

  OS X + Chrome  (mouse)     -    4   pixel delta  (wheelDelta -120)
  OS X + Safari  (mouse)     -  N/A   pixel delta  (wheelDelta  -12)
  OS X + Firefox (mouse)     -    0.1 line  delta  (wheelDelta  N/A)
  Win8 + Chrome  (mouse)     -  100   pixel delta  (wheelDelta -120)
  Win8 + Firefox (mouse)     -    3   line  delta  (wheelDelta -120)

On the trackpad:

  OS X + Chrome  (trackpad)  -    2   pixel delta  (wheelDelta   -6)
  OS X + Firefox (trackpad)  -    1   pixel delta  (wheelDelta  N/A)

On other/older browsers.. it's more complicated as there can be multiple and
also missing delta values.

The 'wheel' event is more standard:

http://www.w3.org/TR/DOM-Level-3-Events/#events-wheelevents

The basics is that it includes a unit, deltaMode (pixels, lines, pages), and
deltaX, deltaY and deltaZ.  Some browsers provide other values to maintain
backward compatibility with older events.  Those other values help us
better normalize spin speed.  Example of what the browsers provide:

                         | event.wheelDelta | event.detail
       ------------------+------------------+--------------
         Safari v5/OS X  |       -120       |       0
         Safari v5/Win7  |       -120       |       0
        Chrome v17/OS X  |       -120       |       0
        Chrome v17/Win7  |       -120       |       0
               IE9/Win7  |       -120       |   undefined
        Firefox v4/OS X  |     undefined    |       1
        Firefox v4/Win7  |     undefined    |       3

**Kind**: inner method of [<code>normalizeWheel</code>](#module_normalizeWheel)  
<a name="module_NumberUtils"></a>

## NumberUtils
A collection of Number related utilities


* [NumberUtils](#module_NumberUtils)
    * [~lerpNumber(v0, v1, t)](#module_NumberUtils..lerpNumber) ⇒ <code>Number</code>
    * [~range(oldValue, oldMin, oldMax, newMin, newMax, clamped)](#module_NumberUtils..range)
    * [~clamp(value, min, max)](#module_NumberUtils..clamp) ⇒ <code>Number</code>
    * [~map(value, min, max)](#module_NumberUtils..map)
    * [~angleDistance(alpha, beta)](#module_NumberUtils..angleDistance)
    * [~angleDistanceSign(alpha, beta)](#module_NumberUtils..angleDistanceSign)
    * [~smoothstep(min, max, value)](#module_NumberUtils..smoothstep) ⇒ <code>Number</code>
    * [~mix(value1, value2, percent)](#module_NumberUtils..mix)
    * [~sign(value)](#module_NumberUtils..sign) ⇒ <code>Number</code>
    * [~randByPower(min, max, power, [rd])](#module_NumberUtils..randByPower)
    * [~mapToPower(value, min, max, power)](#module_NumberUtils..mapToPower)
    * [~distance(x1, y1, x2, y2)](#module_NumberUtils..distance) ⇒ <code>Number</code>
    * [~distanceCompare(x1, y1, x2, y2)](#module_NumberUtils..distanceCompare) ⇒ <code>Number</code>

<a name="module_NumberUtils..lerpNumber"></a>

### NumberUtils~lerpNumber(v0, v1, t) ⇒ <code>Number</code>
Linearly interpolates a Number

**Kind**: inner method of [<code>NumberUtils</code>](#module_NumberUtils)  
**Returns**: <code>Number</code> - Interpolation between v0 and v1 based on t  

| Param | Type | Description |
| --- | --- | --- |
| v0 | <code>Number</code> | Initial value |
| v1 | <code>Number</code> | Final value |
| t | <code>Number</code> | zero to one |

<a name="module_NumberUtils..range"></a>

### NumberUtils~range(oldValue, oldMin, oldMax, newMin, newMax, clamped)
TODO: Documentation

**Kind**: inner method of [<code>NumberUtils</code>](#module_NumberUtils)  

| Param | Type |
| --- | --- |
| oldValue | <code>\*</code> | 
| oldMin | <code>\*</code> | 
| oldMax | <code>\*</code> | 
| newMin | <code>\*</code> | 
| newMax | <code>\*</code> | 
| clamped | <code>\*</code> | 

<a name="module_NumberUtils..clamp"></a>

### NumberUtils~clamp(value, min, max) ⇒ <code>Number</code>
Clamps a value between min and max values

**Kind**: inner method of [<code>NumberUtils</code>](#module_NumberUtils)  
**Returns**: <code>Number</code> - A number clamped between min and max  

| Param | Type | Default | Description |
| --- | --- | --- | --- |
| value | <code>Number</code> |  | The value to be clamped. |
| min | <code>Number</code> | <code>0</code> | Minimum value. |
| max | <code>Number</code> | <code>1</code> | Maximum value. |

<a name="module_NumberUtils..map"></a>

### NumberUtils~map(value, min, max)
TODO: Documentation

**Kind**: inner method of [<code>NumberUtils</code>](#module_NumberUtils)  

| Param | Type |
| --- | --- |
| value | <code>Number</code> | 
| min | <code>Number</code> | 
| max | <code>Number</code> | 

<a name="module_NumberUtils..angleDistance"></a>

### NumberUtils~angleDistance(alpha, beta)
TODO: Documentation

**Kind**: inner method of [<code>NumberUtils</code>](#module_NumberUtils)  

| Param | Type |
| --- | --- |
| alpha | <code>Number</code> | 
| beta | <code>Number</code> | 

<a name="module_NumberUtils..angleDistanceSign"></a>

### NumberUtils~angleDistanceSign(alpha, beta)
TODO: Documentation

**Kind**: inner method of [<code>NumberUtils</code>](#module_NumberUtils)  

| Param | Type |
| --- | --- |
| alpha | <code>Number</code> | 
| beta | <code>Number</code> | 

<a name="module_NumberUtils..smoothstep"></a>

### NumberUtils~smoothstep(min, max, value) ⇒ <code>Number</code>
Smoothstep implementation.
https://en.wikipedia.org/wiki/Smoothstep

**Kind**: inner method of [<code>NumberUtils</code>](#module_NumberUtils)  
**Returns**: <code>Number</code> - Value of the interpolation  

| Param | Type | Description |
| --- | --- | --- |
| min | <code>Number</code> | Initial value |
| max | <code>Number</code> | Final Value |
| value | <code>Number</code> | - |

<a name="module_NumberUtils..mix"></a>

### NumberUtils~mix(value1, value2, percent)
Similar to linear interpolation.

**Kind**: inner method of [<code>NumberUtils</code>](#module_NumberUtils)  

| Param | Type | Description |
| --- | --- | --- |
| value1 | <code>Number</code> | Minimum value. |
| value2 | <code>Number</code> | Maximum value. |
| percent | <code>Number</code> | zero to one value percent |

<a name="module_NumberUtils..sign"></a>

### NumberUtils~sign(value) ⇒ <code>Number</code>
Returns the sign of a number in -1,0,1 form.

**Kind**: inner method of [<code>NumberUtils</code>](#module_NumberUtils)  
**Returns**: <code>Number</code> - 0 if value is zero, -1 if value is less than 0, 1 otherwise  

| Param | Type | Description |
| --- | --- | --- |
| value | <code>Number</code> | a number to be tested |

<a name="module_NumberUtils..randByPower"></a>

### NumberUtils~randByPower(min, max, power, [rd])
TODO: Documentation

**Kind**: inner method of [<code>NumberUtils</code>](#module_NumberUtils)  

| Param | Type | Default | Description |
| --- | --- | --- | --- |
| min | <code>Number</code> |  |  |
| max | <code>Number</code> |  |  |
| power | <code>Number</code> |  |  |
| [rd] | <code>Number</code> | <code>Math.random</code> | Optional Random number generator |

<a name="module_NumberUtils..mapToPower"></a>

### NumberUtils~mapToPower(value, min, max, power)
TODO: Documentation

**Kind**: inner method of [<code>NumberUtils</code>](#module_NumberUtils)  

| Param | Type |
| --- | --- |
| value | <code>Number</code> | 
| min | <code>Number</code> | 
| max | <code>Number</code> | 
| power | <code>Number</code> | 

<a name="module_NumberUtils..distance"></a>

### NumberUtils~distance(x1, y1, x2, y2) ⇒ <code>Number</code>
Computes distance between two points in 2D space.

**Kind**: inner method of [<code>NumberUtils</code>](#module_NumberUtils)  
**Returns**: <code>Number</code> - Distance between x1,y1 and x2,y2  

| Param | Type | Description |
| --- | --- | --- |
| x1 | <code>Number</code> | x coordinate of first point |
| y1 | <code>Number</code> | y coordinate of first point |
| x2 | <code>Number</code> | x coordinate of second point |
| y2 | <code>Number</code> | y coordinate of second point |

<a name="module_NumberUtils..distanceCompare"></a>

### NumberUtils~distanceCompare(x1, y1, x2, y2) ⇒ <code>Number</code>
Not a real distance calculation.
Useful to sort objects by distance ( much faster because no sqrt )

**Kind**: inner method of [<code>NumberUtils</code>](#module_NumberUtils)  
**Returns**: <code>Number</code> - bogus distance between x1,y1 and x2,y2. DO NOT USE WHEN A REAL DISTANCE IS NEEDED  

| Param | Type | Description |
| --- | --- | --- |
| x1 | <code>Number</code> | x coordinate of first point |
| y1 | <code>Number</code> | y coordinate of first point |
| x2 | <code>Number</code> | x coordinate of second point |
| y2 | <code>Number</code> | y coordinate of second point |

<a name="module_ObjectUtils"></a>

## ObjectUtils
A collection of Object related utilities

<a name="module_ObjectUtils..isPlainObject"></a>

### ObjectUtils~isPlainObject(o) ⇒ <code>Boolean</code>
Determines if the object has been constructed using
javascript generic {} syntax

**Kind**: inner method of [<code>ObjectUtils</code>](#module_ObjectUtils)  
**Returns**: <code>Boolean</code> - true if the object is a plain object, false otherwise.  

| Param | Type | Description |
| --- | --- | --- |
| o | <code>\*</code> | The object to be tested. |

<a name="module_Platform"></a>

## Platform
Holds information on the Platform where this code is run

**Properties**

| Name | Type | Description |
| --- | --- | --- |
| mobile | <code>Boolean</code> | Device is a mobile (includes tablets and phones) |
| phone | <code>Boolean</code> | Device is a phone (excludes tablets) |
| tablet | <code>Boolean</code> | Device is a tablet (excludes phones) |
| android | <code>Boolean</code> | Device is Android based |
| ios | <code>Boolean</code> | Device is iOS based |
| ipad | <code>Boolean</code> | Device is an iPad |
| iphone | <code>Boolean</code> | Device is an iPhone |
| wphone | <code>Boolean</code> | Device is an Windows Phone |
| edge | <code>Boolean</code> | Browser is Microsoft Edge |
| firefox | <code>Boolean</code> | Browser is Mozilla Firefox |
| ie11 | <code>Boolean</code> | Browser is Microsoft Internet Explorer 11 |
| safari | <code>Boolean</code> | Browser is Safari |
| prerenderer | <code>Boolean</code> | Page is visited by a prerenderer (like Phantom JS) |
| volume | <code>Boolean</code> | Device supports volume setting via js (iOS doesn't support this) |

<a name="module_VueUtils"></a>

## VueUtils
A collection of Vue.js related utilities

<a name="module_VueUtils..defineReactive"></a>

### VueUtils~defineReactive(value, model)
Allows to define a set of reactive properties of "value" (Object)
by looking into "model" (Object) and comparing the two

**Kind**: inner method of [<code>VueUtils</code>](#module_VueUtils)  

| Param | Type |
| --- | --- |
| value | <code>Object</code> | 
| model | <code>Object</code> | 

<a name="ElasticNumber"></a>

## ElasticNumber
**Kind**: global class  
**Properties**

| Name | Type | Description |
| --- | --- | --- |
| value | <code>Number</code> | The real value of the number. |
| target | <code>Number</code> | The desired value of the number. |
| speed | <code>Number</code> | The speed at which the ElasticNumber will make value reach target. |


* [ElasticNumber](#ElasticNumber)
    * [new ElasticNumber()](#new_ElasticNumber_new)
    * [.update(delta)](#ElasticNumber.update)

<a name="new_ElasticNumber_new"></a>

### new ElasticNumber()
An Utility class that allows to tween a numeric value (_target_) into a smoothed value (_value_)

**Example**  
```js
constructor () {
 this.myNumber = new ElasticNumber();
 this.time = new Date().getTime()
}

onUpdate () {
 const now = new Date().getTime()
 const delta = now - this.time
 this.myNumber.target = Math.random() * 100
 this.myNumber.update(delta);

 this.mySprite.x = this.myNumber.value
 this.time = now
}
```
<a name="ElasticNumber.update"></a>

### ElasticNumber.update(delta)
Updates the ElasticNumber on tick.
Value will be updated from target.

**Kind**: static method of [<code>ElasticNumber</code>](#ElasticNumber)  

| Param | Type | Description |
| --- | --- | --- |
| delta | <code>Number</code> | delta time in milliseconds |

<a name="Gyroscope"></a>

## Gyroscope
**Kind**: global class  
**Properties**

| Name | Type |
| --- | --- |
| orientationX | <code>Number</code> | 
| orientationY | <code>Number</code> | 
| enabled | <code>Boolean</code> | 

<a name="new_Gyroscope_new"></a>

### new Gyroscope()
An utility singleton that returns a device's Gyroscope
data in the form of orientationX and orientationY.

The values are updated every frame and the system stops updating
if it determines that the device does not have gyroscope capabilities.

<a name="RAF"></a>

## RAF
**Kind**: global class  

* [RAF](#RAF)
    * [new RAF()](#new_RAF_new)
    * [.add(listener)](#RAF+add)
    * [.remove(listener)](#RAF+remove)

<a name="new_RAF_new"></a>

### new RAF()
An utility singleton that holds all requestAnimationFrame subscribers
and calls them in sequence each frame.

**Example**  
```js
import RAF from 'js-utils'

constructor () {
 RAF.add(this.onUpdate)
}

onUpdate () {
 // do stuff
}

onDestroy () {
 RAF.remove(this.onUpdate)
}
```
<a name="RAF+add"></a>

### raF.add(listener)
Adds a subscriber to be called at each requestAnimationFrame

**Kind**: instance method of [<code>RAF</code>](#RAF)  

| Param | Type | Description |
| --- | --- | --- |
| listener | <code>function</code> | A subscriber function |

<a name="RAF+remove"></a>

### raF.remove(listener)
Removes a subscriber from requestAnimationFrame

**Kind**: instance method of [<code>RAF</code>](#RAF)  

| Param | Type | Description |
| --- | --- | --- |
| listener | <code>function</code> | A subscriber function |


## LICENSE
Copyright (c) 2020, MONOGRID S.R.L.

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.