Move to 2 space indentation + editorconfig

This commit is contained in:
Josh Johnson 2016-09-05 22:04:15 +01:00
parent 9bb9e0b4c2
commit d40841d8dd
11 changed files with 2659 additions and 2645 deletions

9
.editorconfig Normal file
View file

@ -0,0 +1,9 @@
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true

View file

@ -10,7 +10,7 @@
"rules": { "rules": {
"quotes": [2, "single"], "quotes": [2, "single"],
"strict": [2, "never"], "strict": [2, "never"],
"indent": ["error", 4, {"SwitchCase": 1}], "indent": ["error", 2, {"SwitchCase": 1}],
"eol-last": "off", "eol-last": "off",
"arrow-body-style": "off", "arrow-body-style": "off",
"no-underscore-dangle": "off", "no-underscore-dangle": "off",

View file

@ -1,67 +1,67 @@
export const addItem = (value, label, id, choiceId, activateOptions) => { export const addItem = (value, label, id, choiceId, activateOptions) => {
return { return {
type: 'ADD_ITEM', type: 'ADD_ITEM',
value, value,
label, label,
id, id,
choiceId, choiceId,
activateOptions, activateOptions,
}; };
}; };
export const removeItem = (id, choiceId) => { export const removeItem = (id, choiceId) => {
return { return {
type: 'REMOVE_ITEM', type: 'REMOVE_ITEM',
id, id,
choiceId, choiceId,
}; };
}; };
export const highlightItem = (id, highlighted) => { export const highlightItem = (id, highlighted) => {
return { return {
type: 'HIGHLIGHT_ITEM', type: 'HIGHLIGHT_ITEM',
id, id,
highlighted, highlighted,
}; };
}; };
export const addChoice = (value, label, id, groupId, disabled) => { export const addChoice = (value, label, id, groupId, disabled) => {
return { return {
type: 'ADD_CHOICE', type: 'ADD_CHOICE',
value, value,
label, label,
id, id,
groupId, groupId,
disabled, disabled,
}; };
}; };
export const filterChoices = (results) => { export const filterChoices = (results) => {
return { return {
type: 'FILTER_CHOICES', type: 'FILTER_CHOICES',
results, results,
}; };
}; };
export const activateChoices = (active = true) => { export const activateChoices = (active = true) => {
return { return {
type: 'ACTIVATE_CHOICES', type: 'ACTIVATE_CHOICES',
active, active,
}; };
}; };
export const addGroup = (value, id, active, disabled) => { export const addGroup = (value, id, active, disabled) => {
return { return {
type: 'ADD_GROUP', type: 'ADD_GROUP',
value, value,
id, id,
active, active,
disabled, disabled,
}; };
}; };
export const clearAll = () => { export const clearAll = () => {
return { return {
type: 'CLEAR_ALL', type: 'CLEAR_ALL',
}; };
}; };

File diff suppressed because it is too large Load diff

View file

@ -1,113 +1,112 @@
/* eslint-disable */ /* eslint-disable */
// Production steps of ECMA-262, Edition 6, 22.1.2.1 // Production steps of ECMA-262, Edition 6, 22.1.2.1
// Reference: https://people.mozilla.org/~jorendorff/es6-draft.html#sec-array.from // Reference: https://people.mozilla.org/~jorendorff/es6-draft.html#sec-array.from
if (!Array.from) { if (!Array.from) {
Array.from = (function() { Array.from = (function() {
var toStr = Object.prototype.toString; var toStr = Object.prototype.toString;
var isCallable = function(fn) { var isCallable = function(fn) {
return typeof fn === 'function' || toStr.call(fn) === '[object Function]'; return typeof fn === 'function' || toStr.call(fn) === '[object Function]';
}; };
var toInteger = function(value) { var toInteger = function(value) {
var number = Number(value); var number = Number(value);
if (isNaN(number)) { if (isNaN(number)) {
return 0; return 0;
} }
if (number === 0 || !isFinite(number)) { if (number === 0 || !isFinite(number)) {
return number; return number;
} }
return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number)); return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));
}; };
var maxSafeInteger = Math.pow(2, 53) - 1; var maxSafeInteger = Math.pow(2, 53) - 1;
var toLength = function(value) { var toLength = function(value) {
var len = toInteger(value); var len = toInteger(value);
return Math.min(Math.max(len, 0), maxSafeInteger); return Math.min(Math.max(len, 0), maxSafeInteger);
}; };
// The length property of the from method is 1. // The length property of the from method is 1.
return function from(arrayLike /*, mapFn, thisArg */ ) { return function from(arrayLike /*, mapFn, thisArg */ ) {
// 1. Let C be the this value. // 1. Let C be the this value.
var C = this; var C = this;
// 2. Let items be ToObject(arrayLike). // 2. Let items be ToObject(arrayLike).
var items = Object(arrayLike); var items = Object(arrayLike);
// 3. ReturnIfAbrupt(items). // 3. ReturnIfAbrupt(items).
if (arrayLike == null) { if (arrayLike == null) {
throw new TypeError("Array.from requires an array-like object - not null or undefined"); throw new TypeError("Array.from requires an array-like object - not null or undefined");
} }
// 4. If mapfn is undefined, then let mapping be false. // 4. If mapfn is undefined, then let mapping be false.
var mapFn = arguments.length > 1 ? arguments[1] : void undefined; var mapFn = arguments.length > 1 ? arguments[1] : void undefined;
var T; var T;
if (typeof mapFn !== 'undefined') { if (typeof mapFn !== 'undefined') {
// 5. else // 5. else
// 5. a If IsCallable(mapfn) is false, throw a TypeError exception. // 5. a If IsCallable(mapfn) is false, throw a TypeError exception.
if (!isCallable(mapFn)) { if (!isCallable(mapFn)) {
throw new TypeError('Array.from: when provided, the second argument must be a function'); throw new TypeError('Array.from: when provided, the second argument must be a function');
} }
// 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined. // 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined.
if (arguments.length > 2) { if (arguments.length > 2) {
T = arguments[2]; T = arguments[2];
} }
} }
// 10. Let lenValue be Get(items, "length"). // 10. Let lenValue be Get(items, "length").
// 11. Let len be ToLength(lenValue). // 11. Let len be ToLength(lenValue).
var len = toLength(items.length); var len = toLength(items.length);
// 13. If IsConstructor(C) is true, then // 13. If IsConstructor(C) is true, then
// 13. a. Let A be the result of calling the [[Construct]] internal method of C with an argument list containing the single item len. // 13. a. Let A be the result of calling the [[Construct]] internal method of C with an argument list containing the single item len.
// 14. a. Else, Let A be ArrayCreate(len). // 14. a. Else, Let A be ArrayCreate(len).
var A = isCallable(C) ? Object(new C(len)) : new Array(len); var A = isCallable(C) ? Object(new C(len)) : new Array(len);
// 16. Let k be 0. // 16. Let k be 0.
var k = 0; var k = 0;
// 17. Repeat, while k < len… (also steps a - h) // 17. Repeat, while k < len… (also steps a - h)
var kValue; var kValue;
while (k < len) { while (k < len) {
kValue = items[k]; kValue = items[k];
if (mapFn) { if (mapFn) {
A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k); A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k);
} else { } else {
A[k] = kValue; A[k] = kValue;
} }
k += 1; k += 1;
} }
// 18. Let putStatus be Put(A, "length", len, true). // 18. Let putStatus be Put(A, "length", len, true).
A.length = len; A.length = len;
// 20. Return A. // 20. Return A.
return A; return A;
}; };
}()); }());
} }
// Reference: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/find // Reference: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/find
if (!Array.prototype.find) { if (!Array.prototype.find) {
Array.prototype.find = function(predicate) { Array.prototype.find = function(predicate) {
'use strict'; 'use strict';
if (this == null) { if (this == null) {
throw new TypeError('Array.prototype.find called on null or undefined'); throw new TypeError('Array.prototype.find called on null or undefined');
} }
if (typeof predicate !== 'function') { if (typeof predicate !== 'function') {
throw new TypeError('predicate must be a function'); throw new TypeError('predicate must be a function');
} }
var list = Object(this); var list = Object(this);
var length = list.length >>> 0; var length = list.length >>> 0;
var thisArg = arguments[1]; var thisArg = arguments[1];
var value; var value;
for (var i = 0; i < length; i++) { for (var i = 0; i < length; i++) {
value = list[i]; value = list[i];
if (predicate.call(thisArg, value, i, list)) { if (predicate.call(thisArg, value, i, list)) {
return value; return value;
} }
} }
return undefined; return undefined;
}; };
} }

View file

@ -1,14 +1,13 @@
/* eslint-disable */ /* eslint-disable */
/** /**
* Capitalises the first letter of each word in a string * Capitalises the first letter of each word in a string
* @param {String} str String to capitalise * @param {String} str String to capitalise
* @return {String} Capitalised string * @return {String} Capitalised string
*/ */
export const capitalise = function(str) { export const capitalise = function(str) {
return str.replace(/\w\S*/g, function(txt){ return str.replace(/\w\S*/g, function(txt) {
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
}); });
}; };
/** /**
@ -18,8 +17,8 @@ export const capitalise = function(str) {
* @return {Boolean} * @return {Boolean}
*/ */
export const isType = function(type, obj) { export const isType = function(type, obj) {
var clas = Object.prototype.toString.call(obj).slice(8, -1); var clas = Object.prototype.toString.call(obj).slice(8, -1);
return obj !== undefined && obj !== null && clas === type; return obj !== undefined && obj !== null && clas === type;
}; };
/** /**
@ -28,10 +27,10 @@ export const isType = function(type, obj) {
* @return {Boolean} * @return {Boolean}
*/ */
export const isNode = (o) => { export const isNode = (o) => {
return ( return (
typeof Node === "object" ? o instanceof Node : typeof Node === "object" ? o instanceof Node :
o && typeof o === "object" && typeof o.nodeType === "number" && typeof o.nodeName==="string" o && typeof o === "object" && typeof o.nodeType === "number" && typeof o.nodeName === "string"
); );
}; };
/** /**
@ -40,10 +39,10 @@ export const isNode = (o) => {
* @return {Boolean} * @return {Boolean}
*/ */
export const isElement = (o) => { export const isElement = (o) => {
return ( return (
typeof HTMLElement === "object" ? o instanceof HTMLElement : //DOM2 typeof HTMLElement === "object" ? o instanceof HTMLElement : //DOM2
o && typeof o === "object" && o !== null && o.nodeType === 1 && typeof o.nodeName==="string" o && typeof o === "object" && o !== null && o.nodeType === 1 && typeof o.nodeName === "string"
); );
}; };
/** /**
@ -52,63 +51,63 @@ export const isElement = (o) => {
* @return {Object} Merged object of arguments * @return {Object} Merged object of arguments
*/ */
export const extend = function() { export const extend = function() {
let extended = {}; let extended = {};
let deep = false; let deep = false;
let length = arguments.length; let length = arguments.length;
/** /**
* Merge one object into another * Merge one object into another
* @param {Object} obj Object to merge into extended object * @param {Object} obj Object to merge into extended object
*/ */
let merge = function (obj) { let merge = function(obj) {
for (let prop in obj) { for (let prop in obj) {
if (Object.prototype.hasOwnProperty.call(obj, prop)) { if (Object.prototype.hasOwnProperty.call(obj, prop)) {
// If deep merge and property is an object, merge properties // If deep merge and property is an object, merge properties
if (deep && isType('Object', obj[prop])) { if (deep && isType('Object', obj[prop])) {
extended[prop] = extend( true, extended[prop], obj[prop]); extended[prop] = extend(true, extended[prop], obj[prop]);
} else {
extended[prop] = obj[prop];
}
}
}
};
// Loop through each passed argument
for (let i = 0; i < length; i++) {
// store argument at position i
let obj = arguments[i];
// If we are in fact dealing with an object, merge it. Otherwise throw error
if (isType('Object', obj)) {
merge(obj);
} else { } else {
console.error('Custom options must be an object'); extended[prop] = obj[prop];
} }
}
} }
};
return extended; // Loop through each passed argument
for (let i = 0; i < length; i++) {
// store argument at position i
let obj = arguments[i];
// If we are in fact dealing with an object, merge it. Otherwise throw error
if (isType('Object', obj)) {
merge(obj);
} else {
console.error('Custom options must be an object');
}
}
return extended;
}; };
/** /**
* CSS transition end event listener * CSS transition end event listener
* @return * @return
*/ */
export const whichTransitionEvent = function(){ export const whichTransitionEvent = function() {
var t, var t,
el = document.createElement("fakeelement"); el = document.createElement("fakeelement");
var transitions = { var transitions = {
"transition" : "transitionend", "transition": "transitionend",
"OTransition" : "oTransitionEnd", "OTransition": "oTransitionEnd",
"MozTransition" : "transitionend", "MozTransition": "transitionend",
"WebkitTransition": "webkitTransitionEnd" "WebkitTransition": "webkitTransitionEnd"
} }
for (t in transitions){ for (t in transitions) {
if (el.style[t] !== undefined){ if (el.style[t] !== undefined) {
return transitions[t]; return transitions[t];
}
} }
}
}; };
/** /**
@ -116,21 +115,21 @@ export const whichTransitionEvent = function(){
* @return * @return
*/ */
export const whichAnimationEvent = function() { export const whichAnimationEvent = function() {
var t, var t,
el = document.createElement('fakeelement'); el = document.createElement('fakeelement');
var animations = { var animations = {
'animation': 'animationend', 'animation': 'animationend',
'OAnimation': 'oAnimationEnd', 'OAnimation': 'oAnimationEnd',
'MozAnimation': 'animationend', 'MozAnimation': 'animationend',
'WebkitAnimation': 'webkitAnimationEnd' 'WebkitAnimation': 'webkitAnimationEnd'
}; };
for (t in animations) { for (t in animations) {
if (el.style[t] !== undefined) { if (el.style[t] !== undefined) {
return animations[t]; return animations[t];
}
} }
}
}; };
/** /**
@ -142,103 +141,103 @@ export const whichAnimationEvent = function() {
* @return {Array} Array of parent elements * @return {Array} Array of parent elements
*/ */
export const getParentsUntil = function(elem, parent, selector) { export const getParentsUntil = function(elem, parent, selector) {
var parents = []; var parents = [];
// Get matches // Get matches
for (; elem && elem !== document; elem = elem.parentNode) { for (; elem && elem !== document; elem = elem.parentNode) {
// Check if parent has been reached // Check if parent has been reached
if (parent) { if (parent) {
var parentType = parent.charAt(0); var parentType = parent.charAt(0);
// If parent is a class
if (parentType === '.') {
if (elem.classList.contains(parent.substr(1))) {
break;
}
}
// If parent is an ID
if (parentType === '#') {
if (elem.id === parent.substr(1)) {
break;
}
}
// If parent is a data attribute
if (parentType === '[') {
if (elem.hasAttribute(parent.substr(1, parent.length - 1))) {
break;
}
}
// If parent is a tag
if (elem.tagName.toLowerCase() === parent) {
break;
}
// If parent is a class
if (parentType === '.') {
if (elem.classList.contains(parent.substr(1))) {
break;
} }
if (selector) { }
var selectorType = selector.charAt(0);
// If selector is a class // If parent is an ID
if (selectorType === '.') { if (parentType === '#') {
if (elem.classList.contains(selector.substr(1))) { if (elem.id === parent.substr(1)) {
parents.push(elem); break;
}
}
// If selector is an ID
if (selectorType === '#') {
if (elem.id === selector.substr(1)) {
parents.push(elem);
}
}
// If selector is a data attribute
if (selectorType === '[') {
if (elem.hasAttribute(selector.substr(1, selector.length - 1))) {
parents.push(elem);
}
}
// If selector is a tag
if (elem.tagName.toLowerCase() === selector) {
parents.push(elem);
}
} else {
parents.push(elem);
} }
}
// If parent is a data attribute
if (parentType === '[') {
if (elem.hasAttribute(parent.substr(1, parent.length - 1))) {
break;
}
}
// If parent is a tag
if (elem.tagName.toLowerCase() === parent) {
break;
}
} }
if (selector) {
var selectorType = selector.charAt(0);
// If selector is a class
if (selectorType === '.') {
if (elem.classList.contains(selector.substr(1))) {
parents.push(elem);
}
}
// If selector is an ID
if (selectorType === '#') {
if (elem.id === selector.substr(1)) {
parents.push(elem);
}
}
// If selector is a data attribute
if (selectorType === '[') {
if (elem.hasAttribute(selector.substr(1, selector.length - 1))) {
parents.push(elem);
}
}
// If selector is a tag
if (elem.tagName.toLowerCase() === selector) {
parents.push(elem);
}
// Return parents if any exist
if (parents.length === 0) {
return null;
} else { } else {
return parents; parents.push(elem);
} }
}
// Return parents if any exist
if (parents.length === 0) {
return null;
} else {
return parents;
}
}; };
export const wrap = function (element, wrapper) { export const wrap = function(element, wrapper) {
wrapper = wrapper || document.createElement('div'); wrapper = wrapper || document.createElement('div');
if (element.nextSibling) { if (element.nextSibling) {
element.parentNode.insertBefore(wrapper, element.nextSibling); element.parentNode.insertBefore(wrapper, element.nextSibling);
} else { } else {
element.parentNode.appendChild(wrapper); element.parentNode.appendChild(wrapper);
} }
return wrapper.appendChild(element); return wrapper.appendChild(element);
}; };
export const getSiblings = function (elem) { export const getSiblings = function(elem) {
var siblings = []; var siblings = [];
var sibling = elem.parentNode.firstChild; var sibling = elem.parentNode.firstChild;
for ( ; sibling; sibling = sibling.nextSibling ) { for (; sibling; sibling = sibling.nextSibling) {
if ( sibling.nodeType === 1 && sibling !== elem ) { if (sibling.nodeType === 1 && sibling !== elem) {
siblings.push( sibling ); siblings.push(sibling);
}
} }
return siblings; }
return siblings;
}; };
/** /**
@ -248,8 +247,8 @@ export const getSiblings = function (elem) {
* @return {NodeElement} Found parent element * @return {NodeElement} Found parent element
*/ */
export const findAncestor = function(el, cls) { export const findAncestor = function(el, cls) {
while ((el = el.parentElement) && !el.classList.contains(cls)); while ((el = el.parentElement) && !el.classList.contains(cls));
return el; return el;
}; };
/** /**
@ -260,19 +259,19 @@ export const findAncestor = function(el, cls) {
* @return {Function} A function will be called after it stops being called for a given delay * @return {Function} A function will be called after it stops being called for a given delay
*/ */
export const debounce = function(func, wait, immediate) { export const debounce = function(func, wait, immediate) {
var timeout; var timeout;
return function() { return function() {
var context = this, var context = this,
args = arguments; args = arguments;
var later = function() { var later = function() {
timeout = null; timeout = null;
if (!immediate) func.apply(context, args); if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
}; };
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
}; };
/** /**
@ -282,14 +281,14 @@ export const debounce = function(func, wait, immediate) {
* @return {Number} Elements Distance from top of page * @return {Number} Elements Distance from top of page
*/ */
export const getElemDistance = function(el) { export const getElemDistance = function(el) {
var location = 0; var location = 0;
if (el.offsetParent) { if (el.offsetParent) {
do { do {
location += el.offsetTop; location += el.offsetTop;
el = el.offsetParent; el = el.offsetParent;
} while (el); } while (el);
} }
return location >= 0 ? location : 0; return location >= 0 ? location : 0;
}; };
/** /**
@ -299,11 +298,11 @@ export const getElemDistance = function(el) {
* @return {Number} Height of element * @return {Number} Height of element
*/ */
export const getElementOffset = function(el, offset) { export const getElementOffset = function(el, offset) {
var elOffset = offset; var elOffset = offset;
if(elOffset > 1) elOffset = 1; if (elOffset > 1) elOffset = 1;
if(elOffset > 0) elOffset = 0; if (elOffset > 0) elOffset = 0;
return Math.max(el.offsetHeight*elOffset); return Math.max(el.offsetHeight * elOffset);
}; };
/** /**
@ -314,15 +313,15 @@ export const getElementOffset = function(el, offset) {
* @return {[HTMLElement} Found element * @return {[HTMLElement} Found element
*/ */
export const getAdjacentEl = (startEl, className, direction = 1) => { export const getAdjacentEl = (startEl, className, direction = 1) => {
if(!startEl || !className) return; if (!startEl || !className) return;
const parent = startEl.parentNode.parentNode; const parent = startEl.parentNode.parentNode;
const children = Array.from(parent.querySelectorAll(className)); const children = Array.from(parent.querySelectorAll(className));
const startPos = children.indexOf(startEl); const startPos = children.indexOf(startEl);
const operatorDirection = direction > 0 ? 1 : -1; const operatorDirection = direction > 0 ? 1 : -1;
return children[startPos + operatorDirection]; return children[startPos + operatorDirection];
}; };
/** /**
@ -331,13 +330,13 @@ export const getAdjacentEl = (startEl, className, direction = 1) => {
* @return {String} Position of scroll * @return {String} Position of scroll
*/ */
export const getScrollPosition = function(position) { export const getScrollPosition = function(position) {
if(position === 'bottom') { if (position === 'bottom') {
// Scroll position from the bottom of the viewport // Scroll position from the bottom of the viewport
return Math.max((window.scrollY || window.pageYOffset) + (window.innerHeight || document.documentElement.clientHeight)); return Math.max((window.scrollY || window.pageYOffset) + (window.innerHeight || document.documentElement.clientHeight));
} else { } else {
// Scroll position from the top of the viewport // Scroll position from the top of the viewport
return (window.scrollY || window.pageYOffset); return (window.scrollY || window.pageYOffset);
} }
}; };
/** /**
@ -347,8 +346,8 @@ export const getScrollPosition = function(position) {
* @return {Boolean} * @return {Boolean}
*/ */
export const isInView = function(el, position, offset) { export const isInView = function(el, position, offset) {
// If the user has scrolled further than the distance from the element to the top of its parent // If the user has scrolled further than the distance from the element to the top of its parent
return this.getScrollPosition(position) > (this.getElemDistance(el) + this.getElementOffset(el, offset)) ? true : false; return this.getScrollPosition(position) > (this.getElemDistance(el) + this.getElementOffset(el, offset)) ? true : false;
}; };
/** /**
@ -359,19 +358,19 @@ export const isInView = function(el, position, offset) {
* @return {Boolean} * @return {Boolean}
*/ */
export const isScrolledIntoView = (el, parent, direction = 1) => { export const isScrolledIntoView = (el, parent, direction = 1) => {
if(!el) return; if (!el) return;
let isVisible; let isVisible;
if(direction > 0) { if (direction > 0) {
// In view from bottom // In view from bottom
isVisible = (parent.scrollTop + parent.offsetHeight) >= (el.offsetTop + el.offsetHeight) ; isVisible = (parent.scrollTop + parent.offsetHeight) >= (el.offsetTop + el.offsetHeight);
} else { } else {
// In view from top // In view from top
isVisible = el.offsetTop >= parent.scrollTop; isVisible = el.offsetTop >= parent.scrollTop;
} }
return isVisible; return isVisible;
}; };
/** /**
@ -380,9 +379,9 @@ export const isScrolledIntoView = (el, parent, direction = 1) => {
* @return {String} Sanitised string * @return {String} Sanitised string
*/ */
export const stripHTML = function(html) { export const stripHTML = function(html) {
let el = document.createElement("DIV"); let el = document.createElement("DIV");
el.innerHTML = html; el.innerHTML = html;
return el.textContent || el.innerText || ""; return el.textContent || el.innerText || "";
}; };
/** /**
@ -392,15 +391,15 @@ export const stripHTML = function(html) {
* @return * @return
*/ */
export const addAnimation = (el, animation) => { export const addAnimation = (el, animation) => {
let animationEvent = whichAnimationEvent(); let animationEvent = whichAnimationEvent();
let removeAnimation = () => { let removeAnimation = () => {
el.classList.remove(animation); el.classList.remove(animation);
el.removeEventListener(animationEvent, removeAnimation, false); el.removeEventListener(animationEvent, removeAnimation, false);
}; };
el.classList.add(animation); el.classList.add(animation);
el.addEventListener(animationEvent, removeAnimation, false); el.addEventListener(animationEvent, removeAnimation, false);
}; };
@ -411,7 +410,7 @@ export const addAnimation = (el, animation) => {
* @return {Number} Random number * @return {Number} Random number
*/ */
export const getRandomNumber = function(min, max) { export const getRandomNumber = function(min, max) {
return Math.floor(Math.random() * (max - min) + min); return Math.floor(Math.random() * (max - min) + min);
}; };
/** /**
@ -420,18 +419,18 @@ export const getRandomNumber = function(min, max) {
* @return {HTMLElement} Converted node element * @return {HTMLElement} Converted node element
*/ */
export const strToEl = (function() { export const strToEl = (function() {
var tmpEl = document.createElement('div'); var tmpEl = document.createElement('div');
return function(str) { return function(str) {
var r; var r;
tmpEl.innerHTML = str; tmpEl.innerHTML = str;
r = tmpEl.children[0]; r = tmpEl.children[0];
while (tmpEl.firstChild) { while (tmpEl.firstChild) {
tmpEl.removeChild(tmpEl.firstChild); tmpEl.removeChild(tmpEl.firstChild);
} }
return r; return r;
}; };
}()); }());
/** /**
@ -439,39 +438,39 @@ export const strToEl = (function() {
* @return {Number} Width of input * @return {Number} Width of input
*/ */
export const getWidthOfInput = (input) => { export const getWidthOfInput = (input) => {
const value = input.value || input.placeholder; const value = input.value || input.placeholder;
let width = input.offsetWidth; let width = input.offsetWidth;
if(value) { if (value) {
const testEl = strToEl(`<span>${ value }</span>`); const testEl = strToEl(`<span>${ value }</span>`);
testEl.style.position = 'absolute'; testEl.style.position = 'absolute';
testEl.style.padding = '0'; testEl.style.padding = '0';
testEl.style.top = '-9999px'; testEl.style.top = '-9999px';
testEl.style.left = '-9999px'; testEl.style.left = '-9999px';
testEl.style.width = 'auto'; testEl.style.width = 'auto';
testEl.style.whiteSpace = 'pre'; testEl.style.whiteSpace = 'pre';
document.body.appendChild(testEl); document.body.appendChild(testEl);
if(value && testEl.offsetWidth !== input.offsetWidth) { if (value && testEl.offsetWidth !== input.offsetWidth) {
width = testEl.offsetWidth + 4; width = testEl.offsetWidth + 4;
}
document.body.removeChild(testEl);
} }
return `${width}px`; document.body.removeChild(testEl);
}
return `${width}px`;
}; };
export const sortByAlpha = (a, b) => { export const sortByAlpha = (a, b) => {
const labelA = (a.label || a.value).toLowerCase(); const labelA = (a.label || a.value).toLowerCase();
const labelB = (b.label || b.value).toLowerCase(); const labelB = (b.label || b.value).toLowerCase();
if (labelA < labelB) return -1; if (labelA < labelB) return -1;
if (labelA > labelB) return 1; if (labelA > labelB) return 1;
return 0; return 0;
}; };
export const sortByScore = (a, b) => { export const sortByScore = (a, b) => {
return a.score - b.score; return a.score - b.score;
}; };

View file

@ -1,93 +1,93 @@
const choices = (state = [], action) => { const choices = (state = [], action) => {
switch (action.type) { switch (action.type) {
case 'ADD_CHOICE': { case 'ADD_CHOICE': {
/* /*
A disabled choice appears in the choice dropdown but cannot be selected A disabled choice appears in the choice dropdown but cannot be selected
A selected choice has been added to the passed input's value (added as an item) A selected choice has been added to the passed input's value (added as an item)
An active choice appears within the choice dropdown An active choice appears within the choice dropdown
*/ */
return [...state, { return [...state, {
id: action.id, id: action.id,
groupId: action.groupId, groupId: action.groupId,
value: action.value, value: action.value,
label: action.label, label: action.label,
disabled: action.disabled, disabled: action.disabled,
selected: false, selected: false,
active: true, active: true,
score: 9999, score: 9999,
}]; }];
}
case 'ADD_ITEM': {
let newState = state;
// If all choices need to be activated
if (action.activateOptions) {
newState = state.map((choice) => {
choice.active = action.active;
return choice;
});
}
// When an item is added and it has an associated choice,
// we want to disable it so it can't be chosen again
if (action.choiceId > -1) {
newState = state.map((choice) => {
if (choice.id === parseInt(action.choiceId, 10)) {
choice.selected = true;
}
return choice;
});
}
return newState;
}
case 'REMOVE_ITEM': {
// When an item is removed and it has an associated choice,
// we want to re-enable it so it can be chosen again
if (action.choiceId > -1) {
return state.map((choice) => {
if (choice.id === parseInt(action.choiceId, 10)) {
choice.selected = false;
}
return choice;
});
}
return state;
}
case 'FILTER_CHOICES': {
const filteredResults = action.results;
const filteredState = state.map((choice) => {
// Set active state based on whether choice is
// within filtered results
choice.active = filteredResults.some((result) => {
if (result.item.id === choice.id) {
choice.score = result.score;
return true;
}
return false;
});
return choice;
});
return filteredState;
}
case 'ACTIVATE_CHOICES': {
return state.map((choice) => {
choice.active = action.active;
return choice;
});
}
default: {
return state;
}
} }
case 'ADD_ITEM': {
let newState = state;
// If all choices need to be activated
if (action.activateOptions) {
newState = state.map((choice) => {
choice.active = action.active;
return choice;
});
}
// When an item is added and it has an associated choice,
// we want to disable it so it can't be chosen again
if (action.choiceId > -1) {
newState = state.map((choice) => {
if (choice.id === parseInt(action.choiceId, 10)) {
choice.selected = true;
}
return choice;
});
}
return newState;
}
case 'REMOVE_ITEM': {
// When an item is removed and it has an associated choice,
// we want to re-enable it so it can be chosen again
if (action.choiceId > -1) {
return state.map((choice) => {
if (choice.id === parseInt(action.choiceId, 10)) {
choice.selected = false;
}
return choice;
});
}
return state;
}
case 'FILTER_CHOICES': {
const filteredResults = action.results;
const filteredState = state.map((choice) => {
// Set active state based on whether choice is
// within filtered results
choice.active = filteredResults.some((result) => {
if (result.item.id === choice.id) {
choice.score = result.score;
return true;
}
return false;
});
return choice;
});
return filteredState;
}
case 'ACTIVATE_CHOICES': {
return state.map((choice) => {
choice.active = action.active;
return choice;
});
}
default: {
return state;
}
}
}; };
export default choices; export default choices;

View file

@ -1,18 +1,18 @@
const groups = (state = [], action) => { const groups = (state = [], action) => {
switch (action.type) { switch (action.type) {
case 'ADD_GROUP': { case 'ADD_GROUP': {
return [...state, { return [...state, {
id: action.id, id: action.id,
value: action.value, value: action.value,
active: action.active, active: action.active,
disabled: action.disabled, disabled: action.disabled,
}]; }];
}
default: {
return state;
}
} }
default: {
return state;
}
}
}; };
export default groups; export default groups;

View file

@ -4,22 +4,22 @@ import groups from './groups';
import choices from './choices'; import choices from './choices';
const appReducer = combineReducers({ const appReducer = combineReducers({
items, items,
groups, groups,
choices, choices,
}); });
const rootReducer = (passedState, action) => { const rootReducer = (passedState, action) => {
let state = passedState; let state = passedState;
// If we are clearing all items, groups and options we reassign // If we are clearing all items, groups and options we reassign
// state and then pass that state to our proper reducer. This isn't // state and then pass that state to our proper reducer. This isn't
// mutating our actual state // mutating our actual state
// See: http://stackoverflow.com/a/35641992 // See: http://stackoverflow.com/a/35641992
if (action.type === 'CLEAR_ALL') { if (action.type === 'CLEAR_ALL') {
state = undefined; state = undefined;
} }
return appReducer(state, action); return appReducer(state, action);
}; };
export default rootReducer; export default rootReducer;

View file

@ -1,47 +1,47 @@
const items = (state = [], action) => { const items = (state = [], action) => {
switch (action.type) { switch (action.type) {
case 'ADD_ITEM': { case 'ADD_ITEM': {
// Add object to items array // Add object to items array
const newState = [...state, { const newState = [...state, {
id: action.id, id: action.id,
choiceId: action.choiceId, choiceId: action.choiceId,
value: action.value, value: action.value,
label: action.label, label: action.label,
active: true, active: true,
highlighted: false, highlighted: false,
}]; }];
return newState.map((item) => { return newState.map((item) => {
if (item.highlighted) { if (item.highlighted) {
item.highlighted = false; item.highlighted = false;
}
return item;
});
}
case 'REMOVE_ITEM': {
// Set item to inactive
return state.map((item) => {
if (item.id === action.id) {
item.active = false;
}
return item;
});
}
case 'HIGHLIGHT_ITEM': {
return state.map((item) => {
if (item.id === action.id) {
item.highlighted = action.highlighted;
}
return item;
});
}
default: {
return state;
} }
return item;
});
} }
case 'REMOVE_ITEM': {
// Set item to inactive
return state.map((item) => {
if (item.id === action.id) {
item.active = false;
}
return item;
});
}
case 'HIGHLIGHT_ITEM': {
return state.map((item) => {
if (item.id === action.id) {
item.highlighted = action.highlighted;
}
return item;
});
}
default: {
return state;
}
}
}; };
export default items; export default items;

View file

@ -2,149 +2,149 @@ import { createStore } from 'redux';
import rootReducer from './../reducers/index.js'; import rootReducer from './../reducers/index.js';
export default class Store { export default class Store {
constructor() { constructor() {
this.store = createStore( this.store = createStore(
rootReducer, rootReducer
window.devToolsExtension ? window.devToolsExtension() : undefined , window.devToolsExtension ? window.devToolsExtension() : undefined
); );
}
/**
* Get store object (wrapping Redux method)
* @return {Object} State
*/
getState() {
return this.store.getState();
}
/**
* Dispatch event to store (wrapped Redux method)
* @param {Function} action Action function to trigger
* @return
*/
dispatch(action) {
this.store.dispatch(action);
}
/**
* Subscribe store to function call (wrapped Redux method)
* @param {Function} onChange Function to trigger when state changes
* @return
*/
subscribe(onChange) {
this.store.subscribe(onChange);
}
/**
* Get items from store
* @return {Array} Item objects
*/
getItems() {
const state = this.store.getState();
return state.items;
}
/**
* Get active items from store
* @return {Array} Item objects
*/
getItemsFilteredByActive() {
const items = this.getItems();
const values = items.filter((item) => {
return item.active === true;
}, []);
return values;
}
/**
* Get items from store reduced to just their values
* @return {Array} Item objects
*/
getItemsReducedToValues(items = this.getItems()) {
const values = items.reduce((prev, current) => {
prev.push(current.value);
return prev;
}, []);
return values;
}
/**
* Get choices from store
* @return {Array} Option objects
*/
getChoices() {
const state = this.store.getState();
return state.choices;
}
/**
* Get active choices from store
* @return {Array} Option objects
*/
getChoicesFilteredByActive() {
const choices = this.getChoices();
const values = choices.filter((choice) => {
return choice.active === true;
}, []);
return values;
}
/**
* Get selectable choices from store
* @return {Array} Option objects
*/
getChoicesFilteredBySelectable() {
const choices = this.getChoices();
const values = choices.filter((choice) => {
return choice.disabled !== true;
}, []);
return values;
}
/**
* Get single choice by it's ID
* @return {Object} Found choice
*/
getChoiceById(id) {
if (id) {
const choices = this.getChoicesFilteredByActive();
const foundChoice = choices.find((choice) => choice.id === parseInt(id, 10));
return foundChoice;
} }
return false;
}
/** /**
* Get store object (wrapping Redux method) * Get groups from store
* @return {Object} State * @return {Array} Group objects
*/ */
getState() { getGroups() {
return this.store.getState(); const state = this.store.getState();
} return state.groups;
}
/** /**
* Dispatch event to store (wrapped Redux method) * Get active groups from store
* @param {Function} action Action function to trigger * @return {Array} Group objects
* @return */
*/ getGroupsFilteredByActive() {
dispatch(action) { const groups = this.getGroups();
this.store.dispatch(action); const choices = this.getChoices();
}
/** const values = groups.filter((group) => {
* Subscribe store to function call (wrapped Redux method) const isActive = group.active === true && group.disabled === false;
* @param {Function} onChange Function to trigger when state changes const hasActiveOptions = choices.some((choice) => {
* @return return choice.active === true && choice.disabled === false;
*/ });
subscribe(onChange) { return isActive && hasActiveOptions;
this.store.subscribe(onChange); }, []);
}
/** return values;
* Get items from store }
* @return {Array} Item objects
*/
getItems() {
const state = this.store.getState();
return state.items;
}
/**
* Get active items from store
* @return {Array} Item objects
*/
getItemsFilteredByActive() {
const items = this.getItems();
const values = items.filter((item) => {
return item.active === true;
}, []);
return values;
}
/**
* Get items from store reduced to just their values
* @return {Array} Item objects
*/
getItemsReducedToValues(items = this.getItems()) {
const values = items.reduce((prev, current) => {
prev.push(current.value);
return prev;
}, []);
return values;
}
/**
* Get choices from store
* @return {Array} Option objects
*/
getChoices() {
const state = this.store.getState();
return state.choices;
}
/**
* Get active choices from store
* @return {Array} Option objects
*/
getChoicesFilteredByActive() {
const choices = this.getChoices();
const values = choices.filter((choice) => {
return choice.active === true;
}, []);
return values;
}
/**
* Get selectable choices from store
* @return {Array} Option objects
*/
getChoicesFilteredBySelectable() {
const choices = this.getChoices();
const values = choices.filter((choice) => {
return choice.disabled !== true;
}, []);
return values;
}
/**
* Get single choice by it's ID
* @return {Object} Found choice
*/
getChoiceById(id) {
if (id) {
const choices = this.getChoicesFilteredByActive();
const foundChoice = choices.find((choice) => choice.id === parseInt(id, 10));
return foundChoice;
}
return false;
}
/**
* Get groups from store
* @return {Array} Group objects
*/
getGroups() {
const state = this.store.getState();
return state.groups;
}
/**
* Get active groups from store
* @return {Array} Group objects
*/
getGroupsFilteredByActive() {
const groups = this.getGroups();
const choices = this.getChoices();
const values = groups.filter((group) => {
const isActive = group.active === true && group.disabled === false;
const hasActiveOptions = choices.some((choice) => {
return choice.active === true && choice.disabled === false;
});
return isActive && hasActiveOptions;
}, []);
return values;
}
} }
module.exports = Store; module.exports = Store;