From 487e878b88665693f56f765a735f48bf896a9506 Mon Sep 17 00:00:00 2001 From: Josh Johnson Date: Tue, 7 Nov 2017 11:59:49 +0000 Subject: [PATCH] Ensure webpack config is valid --- package.json | 2 + src/scripts/dist/choices.js | 13213 ++++++++++++++++-------------- src/scripts/dist/choices.js.map | 2 +- src/scripts/dist/choices.min.js | 4 +- webpack.config.dev.js | 48 +- 5 files changed, 6880 insertions(+), 6389 deletions(-) diff --git a/package.json b/package.json index d02974f..6019c3b 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "node-sass": "^3.4.2", "nodemon": "^1.9.1", "nyc": "^11.0.3", + "open": "0.0.5", "opn-cli": "^3.1.0", "postcss-cli": "^2.5.1", "sinon": "^2.4.0", @@ -66,6 +67,7 @@ "dependencies": { "classnames": "^2.2.5", "fuse.js": "^3.1.0", + "opn": "^5.1.0", "redux": "^3.3.1" }, "npmName": "choices.js", diff --git a/src/scripts/dist/choices.js b/src/scripts/dist/choices.js index 1e74a37..133e39e 100644 --- a/src/scripts/dist/choices.js +++ b/src/scripts/dist/choices.js @@ -12,6621 +12,7102 @@ return /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; - +/******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { - +/******/ /******/ // Check if module is in cache -/******/ if(installedModules[moduleId]) +/******/ if(installedModules[moduleId]) { /******/ return installedModules[moduleId].exports; - +/******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { -/******/ exports: {}, -/******/ id: moduleId, -/******/ loaded: false +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} /******/ }; - +/******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); - +/******/ /******/ // Flag the module as loaded -/******/ module.loaded = true; - +/******/ module.l = true; +/******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } - - +/******/ +/******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; - +/******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; - +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { +/******/ configurable: false, +/******/ enumerable: true, +/******/ get: getter +/******/ }); +/******/ } +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = "/src/scripts/dist/"; - +/******/ /******/ // Load entry module and return exports -/******/ return __webpack_require__(0); +/******/ return __webpack_require__(__webpack_require__.s = 6); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* unused harmony export capitalise */ +/* unused harmony export generateChars */ +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "d", function() { return generateId; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "f", function() { return getType; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "j", function() { return isType; }); +/* unused harmony export isNode */ +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "h", function() { return isElement; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return extend; }); +/* unused harmony export whichTransitionEvent */ +/* unused harmony export whichAnimationEvent */ +/* unused harmony export getParentsUntil */ +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "o", function() { return wrap; }); +/* unused harmony export getSiblings */ +/* unused harmony export findAncestor */ +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return findAncestorByAttrName; }); +/* unused harmony export debounce */ +/* unused harmony export getElemDistance */ +/* unused harmony export getElementOffset */ +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "e", function() { return getAdjacentEl; }); +/* unused harmony export getScrollPosition */ +/* unused harmony export isInView */ +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "i", function() { return isScrolledIntoView; }); +/* unused harmony export stripHTML */ +/* unused harmony export addAnimation */ +/* unused harmony export getRandomNumber */ +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "n", function() { return strToEl; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "g", function() { return getWidthOfInput; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "l", function() { return sortByAlpha; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "m", function() { return sortByScore; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return dispatchEvent; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "k", function() { return regexFilter; }); +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; + +/* eslint-disable */ + +/** + * Capitalises the first letter of each word in a string + * @param {String} str String to capitalise + * @return {String} Capitalised string + */ +var capitalise = function capitalise(str) { + return str.replace(/\w\S*/g, function (txt) { + return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); + }); +}; + +/** + * Generates a string of random chars + * @param {Number} length Length of the string to generate + * @return {String} String of random chars + */ +var generateChars = function generateChars(length) { + var chars = ''; + + for (var i = 0; i < length; i++) { + var randomChar = getRandomNumber(0, 36); + chars += randomChar.toString(36); + } + + return chars; +}; + +/** + * Generates a unique id based on an element + * @param {HTMLElement} element Element to generate the id from + * @param {String} Prefix for the Id + * @return {String} Unique Id + */ +var generateId = function generateId(element, prefix) { + var id = element.id || element.name && element.name + '-' + generateChars(2) || generateChars(4); + id = id.replace(/(:|\.|\[|\]|,)/g, ''); + id = prefix + id; + + return id; +}; + +/** + * Tests the type of an object + * @param {String} type Type to test object against + * @param {Object} obj Object to be tested + * @return {Boolean} + */ +var getType = function getType(obj) { + return Object.prototype.toString.call(obj).slice(8, -1); +}; + +/** + * Tests the type of an object + * @param {String} type Type to test object against + * @param {Object} obj Object to be tested + * @return {Boolean} + */ +var isType = function isType(type, obj) { + var clas = getType(obj); + return obj !== undefined && obj !== null && clas === type; +}; + +/** + * Tests to see if a passed object is a node + * @param {Object} obj Object to be tested + * @return {Boolean} + */ +var isNode = function isNode(o) { + return (typeof Node === 'undefined' ? 'undefined' : _typeof(Node)) === 'object' ? o instanceof Node : o && (typeof o === 'undefined' ? 'undefined' : _typeof(o)) === 'object' && typeof o.nodeType === 'number' && typeof o.nodeName === 'string'; +}; + +/** + * Tests to see if a passed object is an element + * @param {Object} obj Object to be tested + * @return {Boolean} + */ +var isElement = function isElement(o) { + return (typeof HTMLElement === 'undefined' ? 'undefined' : _typeof(HTMLElement)) === 'object' ? o instanceof HTMLElement : // DOM2 + o && (typeof o === 'undefined' ? 'undefined' : _typeof(o)) === 'object' && o !== null && o.nodeType === 1 && typeof o.nodeName === 'string'; +}; + +/** + * Merges unspecified amount of objects into new object + * @private + * @return {Object} Merged object of arguments + */ +var extend = function extend() { + var extended = {}; + var length = arguments.length; + + /** + * Merge one object into another + * @param {Object} obj Object to merge into extended object + */ + var merge = function merge(obj) { + for (var prop in obj) { + if (Object.prototype.hasOwnProperty.call(obj, prop)) { + // If deep merge and property is an object, merge properties + if (isType('Object', obj[prop])) { + extended[prop] = extend(true, extended[prop], obj[prop]); + } else { + extended[prop] = obj[prop]; + } + } + } + }; + + // Loop through each passed argument + for (var i = 0; i < length; i++) { + // store argument at position i + var obj = arguments[i]; + + // If we are in fact dealing with an object, merge it. + if (isType('Object', obj)) { + merge(obj); + } + } + + return extended; +}; + +/** + * CSS transition end event listener + * @return + */ +var whichTransitionEvent = function whichTransitionEvent() { + var t = void 0, + el = document.createElement('fakeelement'); + + var transitions = { + transition: 'transitionend', + OTransition: 'oTransitionEnd', + MozTransition: 'transitionend', + WebkitTransition: 'webkitTransitionEnd' + }; + + for (t in transitions) { + if (el.style[t] !== undefined) { + return transitions[t]; + } + } +}; + +/** + * CSS animation end event listener + * @return + */ +var whichAnimationEvent = function whichAnimationEvent() { + var t = void 0, + el = document.createElement('fakeelement'); + + var animations = { + animation: 'animationend', + OAnimation: 'oAnimationEnd', + MozAnimation: 'animationend', + WebkitAnimation: 'webkitAnimationEnd' + }; + + for (t in animations) { + if (el.style[t] !== undefined) { + return animations[t]; + } + } +}; + +/** + * Get the ancestors of each element in the current set of matched elements, + * up to but not including the element matched by the selector + * @param {NodeElement} elem Element to begin search from + * @param {NodeElement} parent Parent to find + * @param {String} selector Class to find + * @return {Array} Array of parent elements + */ +var getParentsUntil = function getParentsUntil(elem, parent, selector) { + var parents = []; + // Get matches + for (; elem && elem !== document; elem = elem.parentNode) { + // Check if parent has been reached + if (parent) { + 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 (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); + } + } else { + parents.push(elem); + } + } + + // Return parents if any exist + if (parents.length === 0) { + return null; + } + return parents; +}; + +var wrap = function wrap(element, wrapper) { + wrapper = wrapper || document.createElement('div'); + if (element.nextSibling) { + element.parentNode.insertBefore(wrapper, element.nextSibling); + } else { + element.parentNode.appendChild(wrapper); + } + return wrapper.appendChild(element); +}; + +var getSiblings = function getSiblings(elem) { + var siblings = []; + var sibling = elem.parentNode.firstChild; + for (; sibling; sibling = sibling.nextSibling) { + if (sibling.nodeType === 1 && sibling !== elem) { + siblings.push(sibling); + } + } + return siblings; +}; + +/** + * Find ancestor in DOM tree + * @param {NodeElement} el Element to start search from + * @param {[type]} cls Class of parent + * @return {NodeElement} Found parent element + */ +var findAncestor = function findAncestor(el, cls) { + while ((el = el.parentElement) && !el.classList.contains(cls)) {} + return el; +}; + +/** + * Find ancestor in DOM tree by attribute name + * @param {NodeElement} el Element to start search from + * @param {string} attr Attribute name of parent + * @return {?NodeElement} Found parent element or null + */ +var findAncestorByAttrName = function findAncestorByAttrName(el, attr) { + var target = el; + + while (target) { + if (target.hasAttribute(attr)) { + return target; + } + + target = target.parentElement; + } + + return null; +}; + +/** + * Debounce an event handler. + * @param {Function} func Function to run after wait + * @param {Number} wait The delay before the function is executed + * @param {Boolean} immediate If passed, trigger the function on the leading edge, instead of the trailing. + * @return {Function} A function will be called after it stops being called for a given delay + */ +var debounce = function debounce(func, wait, immediate) { + var timeout = void 0; + return function () { + var context = this, + args = arguments; + var later = function later() { + timeout = null; + if (!immediate) func.apply(context, args); + }; + var callNow = immediate && !timeout; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + if (callNow) func.apply(context, args); + }; +}; + +/** + * Get an element's distance from the top of the page + * @private + * @param {NodeElement} el Element to test for + * @return {Number} Elements Distance from top of page + */ +var getElemDistance = function getElemDistance(el) { + var location = 0; + if (el.offsetParent) { + do { + location += el.offsetTop; + el = el.offsetParent; + } while (el); + } + return location >= 0 ? location : 0; +}; + +/** + * Determine element height multiplied by any offsets + * @private + * @param {HTMLElement} el Element to test for + * @return {Number} Height of element + */ +var getElementOffset = function getElementOffset(el, offset) { + var elOffset = offset; + if (elOffset > 1) elOffset = 1; + if (elOffset > 0) elOffset = 0; + + return Math.max(el.offsetHeight * elOffset); +}; + +/** + * Get the next or previous element from a given start point + * @param {HTMLElement} startEl Element to start position from + * @param {String} className The class we will look through + * @param {Number} direction Positive next element, negative previous element + * @return {[HTMLElement} Found element + */ +var getAdjacentEl = function getAdjacentEl(startEl, className) { + var direction = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1; + + if (!startEl || !className) return; + + var parent = startEl.parentNode.parentNode; + var children = Array.from(parent.querySelectorAll(className)); + + var startPos = children.indexOf(startEl); + var operatorDirection = direction > 0 ? 1 : -1; + + return children[startPos + operatorDirection]; +}; + +/** + * Get scroll position based on top/bottom position + * @private + * @return {String} Position of scroll + */ +var getScrollPosition = function getScrollPosition(position) { + if (position === 'bottom') { + // Scroll position from the bottom of the viewport + return Math.max((window.scrollY || window.pageYOffset) + (window.innerHeight || document.documentElement.clientHeight)); + } + // Scroll position from the top of the viewport + return window.scrollY || window.pageYOffset; +}; + +/** + * Determine whether an element is within the viewport + * @param {HTMLElement} el Element to test + * @return {String} Position of scroll + * @return {Boolean} + */ +var isInView = function isInView(el, position, offset) { + // 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); +}; + +/** + * Determine whether an element is within + * @param {HTMLElement} el Element to test + * @param {HTMLElement} parent Scrolling parent + * @param {Number} direction Whether element is visible from above or below + * @return {Boolean} + */ +var isScrolledIntoView = function isScrolledIntoView(el, parent) { + var direction = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1; + + if (!el) return; + + var isVisible = void 0; + + if (direction > 0) { + // In view from bottom + isVisible = parent.scrollTop + parent.offsetHeight >= el.offsetTop + el.offsetHeight; + } else { + // In view from top + isVisible = el.offsetTop >= parent.scrollTop; + } + + return isVisible; +}; + +/** + * Remove html tags from a string + * @param {String} Initial string/html + * @return {String} Sanitised string + */ +var stripHTML = function stripHTML(html) { + var el = document.createElement('DIV'); + el.innerHTML = html; + return el.textContent || el.innerText || ''; +}; + +/** + * Adds animation to an element and removes it upon animation completion + * @param {Element} el Element to add animation to + * @param {String} animation Animation class to add to element + * @return + */ +var addAnimation = function addAnimation(el, animation) { + var animationEvent = whichAnimationEvent(); + + var removeAnimation = function removeAnimation() { + el.classList.remove(animation); + el.removeEventListener(animationEvent, removeAnimation, false); + }; + + el.classList.add(animation); + el.addEventListener(animationEvent, removeAnimation, false); +}; + +/** + * Get a random number between a range + * @param {Number} min Minimum range + * @param {Number} max Maximum range + * @return {Number} Random number + */ +var getRandomNumber = function getRandomNumber(min, max) { + return Math.floor(Math.random() * (max - min) + min); +}; + +/** + * Turn a string into a node + * @param {String} String to convert + * @return {HTMLElement} Converted node element + */ +var strToEl = function () { + var tmpEl = document.createElement('div'); + return function (str) { + var cleanedInput = str.trim(); + var r = void 0; + tmpEl.innerHTML = cleanedInput; + r = tmpEl.children[0]; + + while (tmpEl.firstChild) { + tmpEl.removeChild(tmpEl.firstChild); + } + + return r; + }; +}(); + +/** + * Sets the width of a passed input based on its value + * @return {Number} Width of input + */ +var getWidthOfInput = function getWidthOfInput(input) { + var value = input.value || input.placeholder; + var width = input.offsetWidth; + + if (value) { + var testEl = strToEl('' + value + ''); + testEl.style.position = 'absolute'; + testEl.style.padding = '0'; + testEl.style.top = '-9999px'; + testEl.style.left = '-9999px'; + testEl.style.width = 'auto'; + testEl.style.whiteSpace = 'pre'; + + if (document.body.contains(input) && window.getComputedStyle) { + var inputStyle = window.getComputedStyle(input); + + if (inputStyle) { + testEl.style.fontSize = inputStyle.fontSize; + testEl.style.fontFamily = inputStyle.fontFamily; + testEl.style.fontWeight = inputStyle.fontWeight; + testEl.style.fontStyle = inputStyle.fontStyle; + testEl.style.letterSpacing = inputStyle.letterSpacing; + testEl.style.textTransform = inputStyle.textTransform; + testEl.style.padding = inputStyle.padding; + } + } + + document.body.appendChild(testEl); + + if (value && testEl.offsetWidth !== input.offsetWidth) { + width = testEl.offsetWidth + 4; + } + + document.body.removeChild(testEl); + } + + return width + 'px'; +}; + +/** + * Sorting function for current and previous string + * @param {String} a Current value + * @param {String} b Next value + * @return {Number} -1 for after previous, + * 1 for before, + * 0 for same location + */ +var sortByAlpha = function sortByAlpha(a, b) { + var labelA = (a.label || a.value).toLowerCase(); + var labelB = (b.label || b.value).toLowerCase(); + + if (labelA < labelB) return -1; + if (labelA > labelB) return 1; + return 0; +}; + +/** + * Sort by numeric score + * @param {Object} a Current value + * @param {Object} b Next value + * @return {Number} -1 for after previous, + * 1 for before, + * 0 for same location + */ +var sortByScore = function sortByScore(a, b) { + return a.score - b.score; +}; + +/** + * Dispatch native event + * @param {NodeElement} element Element to trigger event on + * @param {String} type Type of event to trigger + * @param {Object} customArgs Data to pass with event + * @return {Object} Triggered event + */ +var dispatchEvent = function dispatchEvent(element, type) { + var customArgs = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; + + var event = new CustomEvent(type, { + detail: customArgs, + bubbles: true, + cancelable: true + }); + + return element.dispatchEvent(event); +}; + +/** + * Tests value against a regular expression + * @param {string} value Value to test + * @return {Boolean} Whether test passed/failed + * @private + */ +var regexFilter = function regexFilter(value, regex) { + if (!value || !regex) { + return false; + } + + var expression = new RegExp(regex.source, 'i'); + return expression.test(value); +}; + +/***/ }), +/* 1 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return DEFAULT_CLASSNAMES; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return DEFAULT_CONFIG; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "d", function() { return EVENTS; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return ACTION_TYPES; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "e", function() { return KEY_CODES; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "f", function() { return SCROLLING_SPEED; }); + +var DEFAULT_CLASSNAMES = { + containerOuter: 'choices', + containerInner: 'choices__inner', + input: 'choices__input', + inputCloned: 'choices__input--cloned', + list: 'choices__list', + listItems: 'choices__list--multiple', + listSingle: 'choices__list--single', + listDropdown: 'choices__list--dropdown', + item: 'choices__item', + itemSelectable: 'choices__item--selectable', + itemDisabled: 'choices__item--disabled', + itemChoice: 'choices__item--choice', + placeholder: 'choices__placeholder', + group: 'choices__group', + groupHeading: 'choices__heading', + button: 'choices__button', + activeState: 'is-active', + focusState: 'is-focused', + openState: 'is-open', + disabledState: 'is-disabled', + highlightedState: 'is-highlighted', + hiddenState: 'is-hidden', + flippedState: 'is-flipped', + loadingState: 'is-loading', + noResults: 'has-no-results', + noChoices: 'has-no-choices' +}; + +var DEFAULT_CONFIG = { + silent: false, + renderChoiceLimit: -1, + maxItemCount: -1, + addItems: true, + removeItems: true, + removeItemButton: false, + editItems: false, + duplicateItems: true, + delimiter: ',', + paste: true, + searchEnabled: true, + searchChoices: true, + searchFloor: 1, + searchResultLimit: 4, + searchFields: ['label', 'value'], + position: 'auto', + resetScrollPosition: true, + regexFilter: null, + shouldSort: true, + shouldSortItems: false, + placeholder: true, + placeholderValue: null, + searchPlaceholderValue: null, + prependValue: null, + appendValue: null, + renderSelectedChoices: 'auto', + loadingText: 'Loading...', + noResultsText: 'No results found', + noChoicesText: 'No choices to choose from', + itemSelectText: 'Press to select', + addItemText: function addItemText(value) { + return 'Press Enter to add "' + value + '"'; + }, + maxItemText: function maxItemText(maxItemCount) { + return 'Only ' + maxItemCount + ' values can be added.'; + }, + uniqueItemText: 'Only unique values can be added.', + fuseOptions: { + includeScore: true + }, + callbackOnInit: null, + callbackOnCreateTemplates: null +}; + +var EVENTS = { + showDropdown: 'showDropdown', + hideDropdown: 'hideDropdown', + change: 'change', + choice: 'choice', + search: 'search', + addItem: 'addItem', + removeItem: 'removeItem', + highlightItem: 'highlightItem' +}; + +var ACTION_TYPES = { + ADD_CHOICE: 'ADD_CHOICE', + FILTER_CHOICES: 'FILTER_CHOICES', + ACTIVATE_CHOICES: 'ACTIVATE_CHOICES', + CLEAR_CHOICES: 'CLEAR_CHOICES', + ADD_GROUP: 'ADD_GROUP', + ADD_ITEM: 'ADD_ITEM', + REMOVE_ITEM: 'REMOVE_ITEM', + HIGHLIGHT_ITEM: 'HIGHLIGHT_ITEM', + CLEAR_ALL: 'CLEAR_ALL' +}; + +var KEY_CODES = { + BACK_KEY: 46, + DELETE_KEY: 8, + ENTER_KEY: 13, + A_KEY: 65, + ESC_KEY: 27, + UP_KEY: 38, + DOWN_KEY: 40, + PAGE_UP_KEY: 33, + PAGE_DOWN_KEY: 34 +}; + +var SCROLLING_SPEED = 4; + +/***/ }), +/* 2 */ +/***/ (function(module, exports) { + +module.exports = function(originalModule) { + if(!originalModule.webpackPolyfill) { + var module = Object.create(originalModule); + // module.parent = undefined by default + if(!module.children) module.children = []; + Object.defineProperty(module, "loaded", { + enumerable: true, + get: function() { + return module.l; + } + }); + Object.defineProperty(module, "id", { + enumerable: true, + get: function() { + return module.i; + } + }); + Object.defineProperty(module, "exports", { + enumerable: true, + }); + module.webpackPolyfill = 1; + } + return module; +}; + + +/***/ }), +/* 3 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; + +// EXTERNAL MODULE: ./node_modules/redux/node_modules/lodash-es/_freeGlobal.js +var _freeGlobal = __webpack_require__(10); + +// CONCATENATED MODULE: ./node_modules/redux/node_modules/lodash-es/_root.js + + +/** Detect free variable `self`. */ +var freeSelf = typeof self == 'object' && self && self.Object === Object && self; + +/** Used as a reference to the global object. */ +var root = _freeGlobal["a" /* default */] || freeSelf || Function('return this')(); + +/* harmony default export */ var _root = (root); + +// CONCATENATED MODULE: ./node_modules/redux/node_modules/lodash-es/_Symbol.js + + +/** Built-in value references. */ +var Symbol = _root.Symbol; + +/* harmony default export */ var _Symbol = (Symbol); + +// CONCATENATED MODULE: ./node_modules/redux/node_modules/lodash-es/_getRawTag.js + + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var _getRawTag_hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ +var nativeObjectToString = objectProto.toString; + +/** Built-in value references. */ +var symToStringTag = _Symbol ? _Symbol.toStringTag : undefined; + +/** + * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the raw `toStringTag`. + */ +function getRawTag(value) { + var isOwn = _getRawTag_hasOwnProperty.call(value, symToStringTag), + tag = value[symToStringTag]; + + try { + value[symToStringTag] = undefined; + var unmasked = true; + } catch (e) {} + + var result = nativeObjectToString.call(value); + if (unmasked) { + if (isOwn) { + value[symToStringTag] = tag; + } else { + delete value[symToStringTag]; + } + } + return result; +} + +/* harmony default export */ var _getRawTag = (getRawTag); + +// CONCATENATED MODULE: ./node_modules/redux/node_modules/lodash-es/_objectToString.js +/** Used for built-in method references. */ +var _objectToString_objectProto = Object.prototype; + +/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ +var _objectToString_nativeObjectToString = _objectToString_objectProto.toString; + +/** + * Converts `value` to a string using `Object.prototype.toString`. + * + * @private + * @param {*} value The value to convert. + * @returns {string} Returns the converted string. + */ +function objectToString(value) { + return _objectToString_nativeObjectToString.call(value); +} + +/* harmony default export */ var _objectToString = (objectToString); + +// CONCATENATED MODULE: ./node_modules/redux/node_modules/lodash-es/_baseGetTag.js + + + + +/** `Object#toString` result references. */ +var nullTag = '[object Null]', + undefinedTag = '[object Undefined]'; + +/** Built-in value references. */ +var _baseGetTag_symToStringTag = _Symbol ? _Symbol.toStringTag : undefined; + +/** + * The base implementation of `getTag` without fallbacks for buggy environments. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ +function baseGetTag(value) { + if (value == null) { + return value === undefined ? undefinedTag : nullTag; + } + return (_baseGetTag_symToStringTag && _baseGetTag_symToStringTag in Object(value)) + ? _getRawTag(value) + : _objectToString(value); +} + +/* harmony default export */ var _baseGetTag = (baseGetTag); + +// CONCATENATED MODULE: ./node_modules/redux/node_modules/lodash-es/_overArg.js +/** + * Creates a unary function that invokes `func` with its argument transformed. + * + * @private + * @param {Function} func The function to wrap. + * @param {Function} transform The argument transform. + * @returns {Function} Returns the new function. + */ +function overArg(func, transform) { + return function(arg) { + return func(transform(arg)); + }; +} + +/* harmony default export */ var _overArg = (overArg); + +// CONCATENATED MODULE: ./node_modules/redux/node_modules/lodash-es/_getPrototype.js + + +/** Built-in value references. */ +var getPrototype = _overArg(Object.getPrototypeOf, Object); + +/* harmony default export */ var _getPrototype = (getPrototype); + +// CONCATENATED MODULE: ./node_modules/redux/node_modules/lodash-es/isObjectLike.js +/** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ +function isObjectLike(value) { + return value != null && typeof value == 'object'; +} + +/* harmony default export */ var lodash_es_isObjectLike = (isObjectLike); + +// CONCATENATED MODULE: ./node_modules/redux/node_modules/lodash-es/isPlainObject.js + + + + +/** `Object#toString` result references. */ +var objectTag = '[object Object]'; + +/** Used for built-in method references. */ +var funcProto = Function.prototype, + isPlainObject_objectProto = Object.prototype; + +/** Used to resolve the decompiled source of functions. */ +var funcToString = funcProto.toString; + +/** Used to check objects for own properties. */ +var isPlainObject_hasOwnProperty = isPlainObject_objectProto.hasOwnProperty; + +/** Used to infer the `Object` constructor. */ +var objectCtorString = funcToString.call(Object); + +/** + * Checks if `value` is a plain object, that is, an object created by the + * `Object` constructor or one with a `[[Prototype]]` of `null`. + * + * @static + * @memberOf _ + * @since 0.8.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. + * @example + * + * function Foo() { + * this.a = 1; + * } + * + * _.isPlainObject(new Foo); + * // => false + * + * _.isPlainObject([1, 2, 3]); + * // => false + * + * _.isPlainObject({ 'x': 0, 'y': 0 }); + * // => true + * + * _.isPlainObject(Object.create(null)); + * // => true + */ +function isPlainObject(value) { + if (!lodash_es_isObjectLike(value) || _baseGetTag(value) != objectTag) { + return false; + } + var proto = _getPrototype(value); + if (proto === null) { + return true; + } + var Ctor = isPlainObject_hasOwnProperty.call(proto, 'constructor') && proto.constructor; + return typeof Ctor == 'function' && Ctor instanceof Ctor && + funcToString.call(Ctor) == objectCtorString; +} + +/* harmony default export */ var lodash_es_isPlainObject = (isPlainObject); + +// EXTERNAL MODULE: ./node_modules/redux/node_modules/symbol-observable/index.js +var symbol_observable = __webpack_require__(11); +var symbol_observable_default = /*#__PURE__*/__webpack_require__.n(symbol_observable); + +// CONCATENATED MODULE: ./node_modules/redux/es/createStore.js + + + +/** + * These are private action types reserved by Redux. + * For any unknown actions, you must return the current state. + * If the current state is undefined, you must return the initial state. + * Do not reference these action types directly in your code. + */ +var ActionTypes = { + INIT: '@@redux/INIT' + + /** + * Creates a Redux store that holds the state tree. + * The only way to change the data in the store is to call `dispatch()` on it. + * + * There should only be a single store in your app. To specify how different + * parts of the state tree respond to actions, you may combine several reducers + * into a single reducer function by using `combineReducers`. + * + * @param {Function} reducer A function that returns the next state tree, given + * the current state tree and the action to handle. + * + * @param {any} [preloadedState] The initial state. You may optionally specify it + * to hydrate the state from the server in universal apps, or to restore a + * previously serialized user session. + * If you use `combineReducers` to produce the root reducer function, this must be + * an object with the same shape as `combineReducers` keys. + * + * @param {Function} [enhancer] The store enhancer. You may optionally specify it + * to enhance the store with third-party capabilities such as middleware, + * time travel, persistence, etc. The only store enhancer that ships with Redux + * is `applyMiddleware()`. + * + * @returns {Store} A Redux store that lets you read the state, dispatch actions + * and subscribe to changes. + */ +};function createStore_createStore(reducer, preloadedState, enhancer) { + var _ref2; + + if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') { + enhancer = preloadedState; + preloadedState = undefined; + } + + if (typeof enhancer !== 'undefined') { + if (typeof enhancer !== 'function') { + throw new Error('Expected the enhancer to be a function.'); + } + + return enhancer(createStore_createStore)(reducer, preloadedState); + } + + if (typeof reducer !== 'function') { + throw new Error('Expected the reducer to be a function.'); + } + + var currentReducer = reducer; + var currentState = preloadedState; + var currentListeners = []; + var nextListeners = currentListeners; + var isDispatching = false; + + function ensureCanMutateNextListeners() { + if (nextListeners === currentListeners) { + nextListeners = currentListeners.slice(); + } + } + + /** + * Reads the state tree managed by the store. + * + * @returns {any} The current state tree of your application. + */ + function getState() { + return currentState; + } + + /** + * Adds a change listener. It will be called any time an action is dispatched, + * and some part of the state tree may potentially have changed. You may then + * call `getState()` to read the current state tree inside the callback. + * + * You may call `dispatch()` from a change listener, with the following + * caveats: + * + * 1. The subscriptions are snapshotted just before every `dispatch()` call. + * If you subscribe or unsubscribe while the listeners are being invoked, this + * will not have any effect on the `dispatch()` that is currently in progress. + * However, the next `dispatch()` call, whether nested or not, will use a more + * recent snapshot of the subscription list. + * + * 2. The listener should not expect to see all state changes, as the state + * might have been updated multiple times during a nested `dispatch()` before + * the listener is called. It is, however, guaranteed that all subscribers + * registered before the `dispatch()` started will be called with the latest + * state by the time it exits. + * + * @param {Function} listener A callback to be invoked on every dispatch. + * @returns {Function} A function to remove this change listener. + */ + function subscribe(listener) { + if (typeof listener !== 'function') { + throw new Error('Expected listener to be a function.'); + } + + var isSubscribed = true; + + ensureCanMutateNextListeners(); + nextListeners.push(listener); + + return function unsubscribe() { + if (!isSubscribed) { + return; + } + + isSubscribed = false; + + ensureCanMutateNextListeners(); + var index = nextListeners.indexOf(listener); + nextListeners.splice(index, 1); + }; + } + + /** + * Dispatches an action. It is the only way to trigger a state change. + * + * The `reducer` function, used to create the store, will be called with the + * current state tree and the given `action`. Its return value will + * be considered the **next** state of the tree, and the change listeners + * will be notified. + * + * The base implementation only supports plain object actions. If you want to + * dispatch a Promise, an Observable, a thunk, or something else, you need to + * wrap your store creating function into the corresponding middleware. For + * example, see the documentation for the `redux-thunk` package. Even the + * middleware will eventually dispatch plain object actions using this method. + * + * @param {Object} action A plain object representing “what changed”. It is + * a good idea to keep actions serializable so you can record and replay user + * sessions, or use the time travelling `redux-devtools`. An action must have + * a `type` property which may not be `undefined`. It is a good idea to use + * string constants for action types. + * + * @returns {Object} For convenience, the same action object you dispatched. + * + * Note that, if you use a custom middleware, it may wrap `dispatch()` to + * return something else (for example, a Promise you can await). + */ + function dispatch(action) { + if (!lodash_es_isPlainObject(action)) { + throw new Error('Actions must be plain objects. ' + 'Use custom middleware for async actions.'); + } + + if (typeof action.type === 'undefined') { + throw new Error('Actions may not have an undefined "type" property. ' + 'Have you misspelled a constant?'); + } + + if (isDispatching) { + throw new Error('Reducers may not dispatch actions.'); + } + + try { + isDispatching = true; + currentState = currentReducer(currentState, action); + } finally { + isDispatching = false; + } + + var listeners = currentListeners = nextListeners; + for (var i = 0; i < listeners.length; i++) { + var listener = listeners[i]; + listener(); + } + + return action; + } + + /** + * Replaces the reducer currently used by the store to calculate the state. + * + * You might need this if your app implements code splitting and you want to + * load some of the reducers dynamically. You might also need this if you + * implement a hot reloading mechanism for Redux. + * + * @param {Function} nextReducer The reducer for the store to use instead. + * @returns {void} + */ + function replaceReducer(nextReducer) { + if (typeof nextReducer !== 'function') { + throw new Error('Expected the nextReducer to be a function.'); + } + + currentReducer = nextReducer; + dispatch({ type: ActionTypes.INIT }); + } + + /** + * Interoperability point for observable/reactive libraries. + * @returns {observable} A minimal observable of state changes. + * For more information, see the observable proposal: + * https://github.com/tc39/proposal-observable + */ + function observable() { + var _ref; + + var outerSubscribe = subscribe; + return _ref = { + /** + * The minimal observable subscription method. + * @param {Object} observer Any object that can be used as an observer. + * The observer object should have a `next` method. + * @returns {subscription} An object with an `unsubscribe` method that can + * be used to unsubscribe the observable from the store, and prevent further + * emission of values from the observable. + */ + subscribe: function subscribe(observer) { + if (typeof observer !== 'object') { + throw new TypeError('Expected the observer to be an object.'); + } + + function observeState() { + if (observer.next) { + observer.next(getState()); + } + } + + observeState(); + var unsubscribe = outerSubscribe(observeState); + return { unsubscribe: unsubscribe }; + } + }, _ref[symbol_observable_default.a] = function () { + return this; + }, _ref; + } + + // When a store is created, an "INIT" action is dispatched so that every + // reducer returns their initial state. This effectively populates + // the initial state tree. + dispatch({ type: ActionTypes.INIT }); + + return _ref2 = { + dispatch: dispatch, + subscribe: subscribe, + getState: getState, + replaceReducer: replaceReducer + }, _ref2[symbol_observable_default.a] = observable, _ref2; +} +// CONCATENATED MODULE: ./node_modules/redux/es/utils/warning.js +/** + * Prints a warning in the console if it exists. + * + * @param {String} message The warning message. + * @returns {void} + */ +function warning_warning(message) { + /* eslint-disable no-console */ + if (typeof console !== 'undefined' && typeof console.error === 'function') { + console.error(message); + } + /* eslint-enable no-console */ + try { + // This error was thrown as a convenience so that if you enable + // "break on all exceptions" in your console, + // it would pause the execution at this line. + throw new Error(message); + /* eslint-disable no-empty */ + } catch (e) {} + /* eslint-enable no-empty */ +} +// CONCATENATED MODULE: ./node_modules/redux/es/combineReducers.js + + + + +function getUndefinedStateErrorMessage(key, action) { + var actionType = action && action.type; + var actionName = actionType && '"' + actionType.toString() + '"' || 'an action'; + + return 'Given action ' + actionName + ', reducer "' + key + '" returned undefined. ' + 'To ignore an action, you must explicitly return the previous state. ' + 'If you want this reducer to hold no value, you can return null instead of undefined.'; +} + +function getUnexpectedStateShapeWarningMessage(inputState, reducers, action, unexpectedKeyCache) { + var reducerKeys = Object.keys(reducers); + var argumentName = action && action.type === ActionTypes.INIT ? 'preloadedState argument passed to createStore' : 'previous state received by the reducer'; + + if (reducerKeys.length === 0) { + return 'Store does not have a valid reducer. Make sure the argument passed ' + 'to combineReducers is an object whose values are reducers.'; + } + + if (!lodash_es_isPlainObject(inputState)) { + return 'The ' + argumentName + ' has unexpected type of "' + {}.toString.call(inputState).match(/\s([a-z|A-Z]+)/)[1] + '". Expected argument to be an object with the following ' + ('keys: "' + reducerKeys.join('", "') + '"'); + } + + var unexpectedKeys = Object.keys(inputState).filter(function (key) { + return !reducers.hasOwnProperty(key) && !unexpectedKeyCache[key]; + }); + + unexpectedKeys.forEach(function (key) { + unexpectedKeyCache[key] = true; + }); + + if (unexpectedKeys.length > 0) { + return 'Unexpected ' + (unexpectedKeys.length > 1 ? 'keys' : 'key') + ' ' + ('"' + unexpectedKeys.join('", "') + '" found in ' + argumentName + '. ') + 'Expected to find one of the known reducer keys instead: ' + ('"' + reducerKeys.join('", "') + '". Unexpected keys will be ignored.'); + } +} + +function assertReducerShape(reducers) { + Object.keys(reducers).forEach(function (key) { + var reducer = reducers[key]; + var initialState = reducer(undefined, { type: ActionTypes.INIT }); + + if (typeof initialState === 'undefined') { + throw new Error('Reducer "' + key + '" returned undefined during initialization. ' + 'If the state passed to the reducer is undefined, you must ' + 'explicitly return the initial state. The initial state may ' + 'not be undefined. If you don\'t want to set a value for this reducer, ' + 'you can use null instead of undefined.'); + } + + var type = '@@redux/PROBE_UNKNOWN_ACTION_' + Math.random().toString(36).substring(7).split('').join('.'); + if (typeof reducer(undefined, { type: type }) === 'undefined') { + throw new Error('Reducer "' + key + '" returned undefined when probed with a random type. ' + ('Don\'t try to handle ' + ActionTypes.INIT + ' or other actions in "redux/*" ') + 'namespace. They are considered private. Instead, you must return the ' + 'current state for any unknown actions, unless it is undefined, ' + 'in which case you must return the initial state, regardless of the ' + 'action type. The initial state may not be undefined, but can be null.'); + } + }); +} + +/** + * Turns an object whose values are different reducer functions, into a single + * reducer function. It will call every child reducer, and gather their results + * into a single state object, whose keys correspond to the keys of the passed + * reducer functions. + * + * @param {Object} reducers An object whose values correspond to different + * reducer functions that need to be combined into one. One handy way to obtain + * it is to use ES6 `import * as reducers` syntax. The reducers may never return + * undefined for any action. Instead, they should return their initial state + * if the state passed to them was undefined, and the current state for any + * unrecognized action. + * + * @returns {Function} A reducer function that invokes every reducer inside the + * passed object, and builds a state object with the same shape. + */ +function combineReducers(reducers) { + var reducerKeys = Object.keys(reducers); + var finalReducers = {}; + for (var i = 0; i < reducerKeys.length; i++) { + var key = reducerKeys[i]; + + if (false) { + if (typeof reducers[key] === 'undefined') { + warning('No reducer provided for key "' + key + '"'); + } + } + + if (typeof reducers[key] === 'function') { + finalReducers[key] = reducers[key]; + } + } + var finalReducerKeys = Object.keys(finalReducers); + + var unexpectedKeyCache = void 0; + if (false) { + unexpectedKeyCache = {}; + } + + var shapeAssertionError = void 0; + try { + assertReducerShape(finalReducers); + } catch (e) { + shapeAssertionError = e; + } + + return function combination() { + var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var action = arguments[1]; + + if (shapeAssertionError) { + throw shapeAssertionError; + } + + if (false) { + var warningMessage = getUnexpectedStateShapeWarningMessage(state, finalReducers, action, unexpectedKeyCache); + if (warningMessage) { + warning(warningMessage); + } + } + + var hasChanged = false; + var nextState = {}; + for (var _i = 0; _i < finalReducerKeys.length; _i++) { + var _key = finalReducerKeys[_i]; + var reducer = finalReducers[_key]; + var previousStateForKey = state[_key]; + var nextStateForKey = reducer(previousStateForKey, action); + if (typeof nextStateForKey === 'undefined') { + var errorMessage = getUndefinedStateErrorMessage(_key, action); + throw new Error(errorMessage); + } + nextState[_key] = nextStateForKey; + hasChanged = hasChanged || nextStateForKey !== previousStateForKey; + } + return hasChanged ? nextState : state; + }; +} +// CONCATENATED MODULE: ./node_modules/redux/es/bindActionCreators.js +function bindActionCreator(actionCreator, dispatch) { + return function () { + return dispatch(actionCreator.apply(undefined, arguments)); + }; +} + +/** + * Turns an object whose values are action creators, into an object with the + * same keys, but with every function wrapped into a `dispatch` call so they + * may be invoked directly. This is just a convenience method, as you can call + * `store.dispatch(MyActionCreators.doSomething())` yourself just fine. + * + * For convenience, you can also pass a single function as the first argument, + * and get a function in return. + * + * @param {Function|Object} actionCreators An object whose values are action + * creator functions. One handy way to obtain it is to use ES6 `import * as` + * syntax. You may also pass a single function. + * + * @param {Function} dispatch The `dispatch` function available on your Redux + * store. + * + * @returns {Function|Object} The object mimicking the original object, but with + * every action creator wrapped into the `dispatch` call. If you passed a + * function as `actionCreators`, the return value will also be a single + * function. + */ +function bindActionCreators(actionCreators, dispatch) { + if (typeof actionCreators === 'function') { + return bindActionCreator(actionCreators, dispatch); + } + + if (typeof actionCreators !== 'object' || actionCreators === null) { + throw new Error('bindActionCreators expected an object or a function, instead received ' + (actionCreators === null ? 'null' : typeof actionCreators) + '. ' + 'Did you write "import ActionCreators from" instead of "import * as ActionCreators from"?'); + } + + var keys = Object.keys(actionCreators); + var boundActionCreators = {}; + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + var actionCreator = actionCreators[key]; + if (typeof actionCreator === 'function') { + boundActionCreators[key] = bindActionCreator(actionCreator, dispatch); + } + } + return boundActionCreators; +} +// CONCATENATED MODULE: ./node_modules/redux/es/compose.js +/** + * Composes single-argument functions from right to left. The rightmost + * function can take multiple arguments as it provides the signature for + * the resulting composite function. + * + * @param {...Function} funcs The functions to compose. + * @returns {Function} A function obtained by composing the argument functions + * from right to left. For example, compose(f, g, h) is identical to doing + * (...args) => f(g(h(...args))). + */ + +function compose() { + for (var _len = arguments.length, funcs = Array(_len), _key = 0; _key < _len; _key++) { + funcs[_key] = arguments[_key]; + } + + if (funcs.length === 0) { + return function (arg) { + return arg; + }; + } + + if (funcs.length === 1) { + return funcs[0]; + } + + return funcs.reduce(function (a, b) { + return function () { + return a(b.apply(undefined, arguments)); + }; + }); +} +// CONCATENATED MODULE: ./node_modules/redux/es/applyMiddleware.js +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + + + +/** + * Creates a store enhancer that applies middleware to the dispatch method + * of the Redux store. This is handy for a variety of tasks, such as expressing + * asynchronous actions in a concise manner, or logging every action payload. + * + * See `redux-thunk` package as an example of the Redux middleware. + * + * Because middleware is potentially asynchronous, this should be the first + * store enhancer in the composition chain. + * + * Note that each middleware will be given the `dispatch` and `getState` functions + * as named arguments. + * + * @param {...Function} middlewares The middleware chain to be applied. + * @returns {Function} A store enhancer applying the middleware. + */ +function applyMiddleware() { + for (var _len = arguments.length, middlewares = Array(_len), _key = 0; _key < _len; _key++) { + middlewares[_key] = arguments[_key]; + } + + return function (createStore) { + return function (reducer, preloadedState, enhancer) { + var store = createStore(reducer, preloadedState, enhancer); + var _dispatch = store.dispatch; + var chain = []; + + var middlewareAPI = { + getState: store.getState, + dispatch: function dispatch(action) { + return _dispatch(action); + } + }; + chain = middlewares.map(function (middleware) { + return middleware(middlewareAPI); + }); + _dispatch = compose.apply(undefined, chain)(store.dispatch); + + return _extends({}, store, { + dispatch: _dispatch + }); + }; + }; +} +// CONCATENATED MODULE: ./node_modules/redux/es/index.js +/* concated harmony reexport */__webpack_require__.d(__webpack_exports__, "b", function() { return createStore_createStore; }); +/* concated harmony reexport */__webpack_require__.d(__webpack_exports__, "a", function() { return combineReducers; }); +/* unused concated harmony import bindActionCreators */ +/* concated harmony reexport */__webpack_require__.d(__webpack_exports__, false, function() { return bindActionCreators; }); +/* unused concated harmony import applyMiddleware */ +/* concated harmony reexport */__webpack_require__.d(__webpack_exports__, false, function() { return applyMiddleware; }); +/* unused concated harmony import compose */ +/* concated harmony reexport */__webpack_require__.d(__webpack_exports__, false, function() { return compose; }); + + + + + + + +/* +* This is a dummy function to check if the function name has been altered by minification. +* If the function has been minified and NODE_ENV !== 'production', warn the user. +*/ +function isCrushed() {} + +if (false) { + warning('You are currently using minified code outside of NODE_ENV === \'production\'. ' + 'This means that you are running a slower development build of Redux. ' + 'You can use loose-envify (https://github.com/zertosh/loose-envify) for browserify ' + 'or DefinePlugin for webpack (http://stackoverflow.com/questions/30030031) ' + 'to ensure you have the correct code for your production build.'); +} + + + +/***/ }), +/* 4 */ +/***/ (function(module, exports) { + +var g; + +// This works in non-strict mode +g = (function() { + return this; +})(); + +try { + // This works if eval is allowed (see CSP) + g = g || Function("return this")() || (1,eval)("this"); +} catch(e) { + // This works if the window reference is available + if(typeof window === "object") + g = window; +} + +// g can still be undefined, but nothing to do about it... +// We return undefined, instead of nothing here, so it's +// easier to handle this case. if(!global) { ...} + +module.exports = g; + + +/***/ }), +/* 5 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__lib_utils__ = __webpack_require__(0); +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + + + +var WrappedElement = function () { + function WrappedElement(instance, element, classNames) { + _classCallCheck(this, WrappedElement); + + this.parentInstance = instance; + this.element = element; + this.classNames = classNames; + this.isDisabled = false; + } + + _createClass(WrappedElement, [{ + key: 'getElement', + value: function getElement() { + return this.element; + } + }, { + key: 'getValue', + value: function getValue() { + return this.element.value; + } + }, { + key: 'conceal', + value: function conceal() { + // Hide passed input + this.element.classList.add(this.classNames.input, this.classNames.hiddenState); + + // Remove element from tab index + this.element.tabIndex = '-1'; + + // Backup original styles if any + var origStyle = this.element.getAttribute('style'); + + if (origStyle) { + this.element.setAttribute('data-choice-orig-style', origStyle); + } + + this.element.setAttribute('style', 'display:none;'); + this.element.setAttribute('aria-hidden', 'true'); + this.element.setAttribute('data-choice', 'active'); + } + }, { + key: 'reveal', + value: function reveal() { + // Reinstate passed element + this.element.classList.remove(this.classNames.input, this.classNames.hiddenState); + this.element.removeAttribute('tabindex'); + + // Recover original styles if any + var origStyle = this.element.getAttribute('data-choice-orig-style'); + + if (origStyle) { + this.element.removeAttribute('data-choice-orig-style'); + this.element.setAttribute('style', origStyle); + } else { + this.element.removeAttribute('style'); + } + this.element.removeAttribute('aria-hidden'); + this.element.removeAttribute('data-choice'); + + // Re-assign values - this is weird, I know + this.element.value = this.element.value; + } + }, { + key: 'enable', + value: function enable() { + this.element.removeAttribute('disabled'); + this.element.disabled = false; + this.isDisabled = false; + } + }, { + key: 'disable', + value: function disable() { + this.element.setAttribute('disabled', ''); + this.element.disabled = true; + this.isDisabled = true; + } + }, { + key: 'triggerEvent', + value: function triggerEvent(eventType, data) { + Object(__WEBPACK_IMPORTED_MODULE_0__lib_utils__["a" /* dispatchEvent */])(this.element, eventType, data); + } + }]); + + return WrappedElement; +}(); + +/* harmony default export */ __webpack_exports__["a"] = (WrappedElement); + +/***/ }), +/* 6 */ +/***/ (function(module, exports, __webpack_require__) { + +module.exports = __webpack_require__(7); + + +/***/ }), +/* 7 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +Object.defineProperty(__webpack_exports__, "__esModule", { value: true }); +/* WEBPACK VAR INJECTION */(function(module) {/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_fuse_js__ = __webpack_require__(8); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_fuse_js___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_fuse_js__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__store_store__ = __webpack_require__(9); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__components_dropdown__ = __webpack_require__(16); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__components_container__ = __webpack_require__(17); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__components_input__ = __webpack_require__(18); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__components_list__ = __webpack_require__(19); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__components_wrapped_input__ = __webpack_require__(20); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__components_wrapped_select__ = __webpack_require__(21); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__constants__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_9__templates__ = __webpack_require__(22); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_10__actions_choices__ = __webpack_require__(24); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_11__actions_items__ = __webpack_require__(25); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_12__actions_groups__ = __webpack_require__(26); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_13__actions_misc__ = __webpack_require__(27); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_14__lib_utils__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_15__lib_polyfills__ = __webpack_require__(28); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_15__lib_polyfills___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_15__lib_polyfills__); +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + + + + + + + + + + + + + + + + + + +/** + * Choices + */ + +var Choices = function () { + function Choices() { + var element = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '[data-choice]'; + var userConfig = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + _classCallCheck(this, Choices); + + // If there are multiple elements, create a new instance + // for each element besides the first one (as that already has an instance) + if (Object(__WEBPACK_IMPORTED_MODULE_14__lib_utils__["j" /* isType */])('String', element)) { + var elements = document.querySelectorAll(element); + if (elements.length > 1) { + for (var i = 1; i < elements.length; i += 1) { + var el = elements[i]; + /* eslint-disable no-new */ + new Choices(el, userConfig); + } + } + } + + var defaultConfig = _extends({}, __WEBPACK_IMPORTED_MODULE_8__constants__["c" /* DEFAULT_CONFIG */], { + items: [], + choices: [], + classNames: __WEBPACK_IMPORTED_MODULE_8__constants__["b" /* DEFAULT_CLASSNAMES */], + sortFilter: __WEBPACK_IMPORTED_MODULE_14__lib_utils__["l" /* sortByAlpha */] + }); + + // Merge options with user options + this.config = Object(__WEBPACK_IMPORTED_MODULE_14__lib_utils__["b" /* extend */])(defaultConfig, Choices.userDefaults, userConfig); + + if (!['auto', 'always'].includes(this.config.renderSelectedChoices)) { + this.config.renderSelectedChoices = 'auto'; + } + + // Create data store + this.store = new __WEBPACK_IMPORTED_MODULE_1__store_store__["a" /* default */](this.render); + + // State tracking + this.initialised = false; + this.currentState = {}; + this.prevState = {}; + this.currentValue = ''; + + // Retrieve triggering element (i.e. element with 'data-choice' trigger) + var passedElement = Object(__WEBPACK_IMPORTED_MODULE_14__lib_utils__["j" /* isType */])('String', element) ? document.querySelector(element) : element; + + this.isTextElement = passedElement.type === 'text'; + this.isSelectOneElement = passedElement.type === 'select-one'; + this.isSelectMultipleElement = passedElement.type === 'select-multiple'; + this.isSelectElement = this.isSelectOneElement || this.isSelectMultipleElement; + this.isValidElementType = this.isTextElement || this.isSelectElement; + + if (this.isTextElement) { + this.passedElement = new __WEBPACK_IMPORTED_MODULE_6__components_wrapped_input__["a" /* default */](this, passedElement, this.config.classNames); + } else if (this.isSelectElement) { + this.passedElement = new __WEBPACK_IMPORTED_MODULE_7__components_wrapped_select__["a" /* default */](this, passedElement, this.config.classNames); + } + + if (!this.passedElement) { + if (!this.config.silent) { + console.error('Passed element not found'); + } + return false; + } + + this.isIe11 = !!(navigator.userAgent.match(/Trident/) && navigator.userAgent.match(/rv[ :]11/)); + this.isScrollingOnIe = false; + + if (this.config.shouldSortItems === true && this.isSelectOneElement) { + if (!this.config.silent) { + console.warn('shouldSortElements: Type of passed element is \'select-one\', falling back to false.'); + } + } + + this.highlightPosition = 0; + this.canSearch = this.config.searchEnabled; + + this.placeholder = false; + if (!this.isSelectOneElement) { + this.placeholder = this.config.placeholder ? this.config.placeholderValue || this.passedElement.element.getAttribute('placeholder') : false; + } + + // Assign preset choices from passed object + this.presetChoices = this.config.choices; + // Assign preset items from passed object first + this.presetItems = this.config.items; + + // Then add any values passed from attribute + if (this.passedElement.getValue()) { + this.presetItems = this.presetItems.concat(this.passedElement.getValue().split(this.config.delimiter)); + } + + // Set unique base Id + this.baseId = Object(__WEBPACK_IMPORTED_MODULE_14__lib_utils__["d" /* generateId */])(this.passedElement.element, 'choices-'); + + this.idNames = { + itemChoice: 'item-choice' + }; + + // Bind methods + this.render = this.render.bind(this); + + // Bind event handlers + this._onFocus = this._onFocus.bind(this); + this._onBlur = this._onBlur.bind(this); + this._onKeyUp = this._onKeyUp.bind(this); + this._onKeyDown = this._onKeyDown.bind(this); + this._onClick = this._onClick.bind(this); + this._onTouchMove = this._onTouchMove.bind(this); + this._onTouchEnd = this._onTouchEnd.bind(this); + this._onMouseDown = this._onMouseDown.bind(this); + this._onMouseOver = this._onMouseOver.bind(this); + + // Monitor touch taps/scrolls + this.wasTap = true; + + // Cutting the mustard + var cuttingTheMustard = 'classList' in document.documentElement; + if (!cuttingTheMustard && !this.config.silent) { + console.error('Choices: Your browser doesn\'t support Choices'); + } + + var canInit = Object(__WEBPACK_IMPORTED_MODULE_14__lib_utils__["h" /* isElement */])(this.passedElement.element) && this.isValidElementType; + + if (canInit) { + // If element has already been initialised with Choices + if (this.passedElement.element.getAttribute('data-choice') === 'active') { + return false; + } + + // Let's go + this.init(); + } else if (!this.config.silent) { + console.error('Incompatible input passed'); + } + } + + /* ======================================== + = Public functions = + ======================================== */ + + /** + * Initialise Choices + * @return + * @public + */ + + + _createClass(Choices, [{ + key: 'init', + value: function init() { + if (this.initialised) { + return; + } + + // Set initialise flag + this.initialised = true; + // Create required elements + this._createTemplates(); + // Generate input markup + this._createInput(); + // Subscribe store to render method + this.store.subscribe(this.render); + // Render any items + this.render(); + // Trigger event listeners + this._addEventListeners(); + + var callback = this.config.callbackOnInit; + // Run callback if it is a function + if (callback && Object(__WEBPACK_IMPORTED_MODULE_14__lib_utils__["j" /* isType */])('Function', callback)) { + callback.call(this); + } + } + + /** + * Destroy Choices and nullify values + * @return + * @public + */ + + }, { + key: 'destroy', + value: function destroy() { + if (!this.initialised) { + return; + } + + // Remove all event listeners + this._removeEventListeners(); + this.passedElement.reveal(); + this.containerOuter.revert(this.passedElement.element); + + // Clear data store + this.clearStore(); + + // Nullify instance-specific data + this.config.templates = null; + + // Uninitialise + this.initialised = false; + } + + /** + * Enable interaction with Choices + * @return {Object} Class instance + */ + + }, { + key: 'enable', + value: function enable() { + if (!this.initialised) { + return this; + } + + this.passedElement.enable(); + + if (this.containerOuter.isDisabled) { + this._addEventListeners(); + this.input.enable(); + this.containerOuter.enable(); + } + + return this; + } + + /** + * Disable interaction with Choices + * @return {Object} Class instance + * @public + */ + + }, { + key: 'disable', + value: function disable() { + if (!this.initialised) { + return this; + } + + this.passedElement.disable(); + + if (!this.containerOuter.isDisabled) { + this._removeEventListeners(); + this.input.disable(); + this.containerOuter.disable(); + } + + return this; + } + + /** + * Render group choices into a DOM fragment and append to choice list + * @param {Array} groups Groups to add to list + * @param {Array} choices Choices to add to groups + * @param {DocumentFragment} fragment Fragment to add groups and options to (optional) + * @return {DocumentFragment} Populated options fragment + * @private + */ + + }, { + key: 'renderGroups', + value: function renderGroups(groups, choices, fragment) { + var _this = this; + + var groupFragment = fragment || document.createDocumentFragment(); + var filter = this.config.sortFilter; + var getGroupChoices = function getGroupChoices(group) { + return choices.filter(function (choice) { + if (_this.isSelectOneElement) { + return choice.groupId === group.id; + } + return choice.groupId === group.id && (_this.config.renderSelectedChoices === 'always' || !choice.selected); + }); + }; + + // If sorting is enabled, filter groups + if (this.config.shouldSort) { + groups.sort(filter); + } + + groups.forEach(function (group) { + var groupChoices = getGroupChoices(group); + + if (groupChoices.length >= 1) { + var dropdownGroup = _this._getTemplate('choiceGroup', group); + groupFragment.appendChild(dropdownGroup); + _this.renderChoices(groupChoices, groupFragment, true); + } + }); + + return groupFragment; + } + + /** + * Render choices into a DOM fragment and append to choice list + * @param {Array} choices Choices to add to list + * @param {DocumentFragment} fragment Fragment to add choices to (optional) + * @return {DocumentFragment} Populated choices fragment + * @private + */ + + }, { + key: 'renderChoices', + value: function renderChoices(choices, fragment) { + var _this2 = this; + + var withinGroup = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + + // Create a fragment to store our list items (so we don't have to update the DOM for each item) + var choicesFragment = fragment || document.createDocumentFragment(); + var _config = this.config, + renderSelectedChoices = _config.renderSelectedChoices, + searchResultLimit = _config.searchResultLimit, + renderChoiceLimit = _config.renderChoiceLimit; + + var filter = this.isSearching ? __WEBPACK_IMPORTED_MODULE_14__lib_utils__["m" /* sortByScore */] : this.config.sortFilter; + var appendChoice = function appendChoice(choice) { + var shouldRender = renderSelectedChoices === 'auto' ? _this2.isSelectOneElement || !choice.selected : true; + if (shouldRender) { + var dropdownItem = _this2._getTemplate('choice', choice, _this2.config.itemSelectText); + choicesFragment.appendChild(dropdownItem); + } + }; + + var rendererableChoices = choices; + + if (renderSelectedChoices === 'auto' && !this.isSelectOneElement) { + rendererableChoices = choices.filter(function (choice) { + return !choice.selected; + }); + } + + // Split array into placeholders and "normal" choices + + var _rendererableChoices$ = rendererableChoices.reduce(function (acc, choice) { + if (choice.placeholder) { + acc.placeholderChoices.push(choice); + } else { + acc.normalChoices.push(choice); + } + return acc; + }, { placeholderChoices: [], normalChoices: [] }), + placeholderChoices = _rendererableChoices$.placeholderChoices, + normalChoices = _rendererableChoices$.normalChoices; + + // If sorting is enabled or the user is searching, filter choices + + + if (this.config.shouldSort || this.isSearching) { + normalChoices.sort(filter); + } + + var choiceLimit = rendererableChoices.length; + + // Prepend placeholeder + var sortedChoices = [].concat(_toConsumableArray(placeholderChoices), _toConsumableArray(normalChoices)); + + if (this.isSearching) { + choiceLimit = searchResultLimit; + } else if (renderChoiceLimit > 0 && !withinGroup) { + choiceLimit = renderChoiceLimit; + } + + // Add each choice to dropdown within range + for (var i = 0; i < choiceLimit; i += 1) { + if (sortedChoices[i]) { + appendChoice(sortedChoices[i]); + } + } + + return choicesFragment; + } + + /** + * Render items into a DOM fragment and append to items list + * @param {Array} items Items to add to list + * @param {DocumentFragment} [fragment] Fragment to add items to (optional) + * @return + * @private + */ + + }, { + key: 'renderItems', + value: function renderItems(items) { + var _this3 = this; + + var fragment = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; + + // Create fragment to add elements to + var itemListFragment = fragment || document.createDocumentFragment(); + + // If sorting is enabled, filter items + if (this.config.shouldSortItems && !this.isSelectOneElement) { + items.sort(this.config.sortFilter); + } + + if (this.isTextElement) { + // Simplify store data to just values + var itemsFiltered = this.store.getItemsReducedToValues(items); + var itemsFilteredString = itemsFiltered.join(this.config.delimiter); + + // Update the value of the hidden input + this.passedElement.setValue(itemsFilteredString); + } else { + var selectedOptionsFragment = document.createDocumentFragment(); + var addOptionToFragment = function addOptionToFragment(item) { + // Create a standard select option + var option = _this3._getTemplate('option', item); + // Append it to fragment + selectedOptionsFragment.appendChild(option); + }; + + // Add each list item to list + items.forEach(function (item) { + return addOptionToFragment(item); + }); + // Update the options of the hidden input + this.passedElement.setOptions(selectedOptionsFragment); + } + + var addItemToFragment = function addItemToFragment(item) { + // Create new list element + var listItem = _this3._getTemplate('item', item, _this3.config.removeItemButton); + // Append it to list + itemListFragment.appendChild(listItem); + }; + + // Add each list item to list + items.forEach(function (item) { + return addItemToFragment(item); + }); + + return itemListFragment; + } + + /** + * Render DOM with values + * @return + * @private + */ + + }, { + key: 'render', + value: function render() { + this.currentState = this.store.getState(); + var stateChanged = this.currentState.choices !== this.prevState.choices || this.currentState.groups !== this.prevState.groups || this.currentState.items !== this.prevState.items; + + if (!stateChanged) { + return; + } + + /* Choices */ + + if (this.isSelectElement) { + // Get active groups/choices + var activeGroups = this.store.getGroupsFilteredByActive(); + var activeChoices = this.store.getChoicesFilteredByActive(); + + var choiceListFragment = document.createDocumentFragment(); + + // Clear choices + this.choiceList.clear(); + + // Scroll back to top of choices list + if (this.config.resetScrollPosition) { + this.choiceList.scrollTo(0); + } + + // If we have grouped options + if (activeGroups.length >= 1 && !this.isSearching) { + // If we have a placeholder choice along with groups + var activePlaceholders = activeChoices.filter(function (activeChoice) { + return activeChoice.placeholder === true && activeChoice.groupId === -1; + }); + if (activePlaceholders.length >= 1) { + choiceListFragment = this.renderChoices(activePlaceholders, choiceListFragment); + } + choiceListFragment = this.renderGroups(activeGroups, activeChoices, choiceListFragment); + } else if (activeChoices.length >= 1) { + choiceListFragment = this.renderChoices(activeChoices, choiceListFragment); + } + + var _activeItems = this.store.getItemsFilteredByActive(); + var canAddItem = this._canAddItem(_activeItems, this.input.getValue()); + + // If we have choices to show + if (choiceListFragment.childNodes && choiceListFragment.childNodes.length > 0) { + // ...and we can select them + if (canAddItem.response) { + // ...append them and highlight the first choice + this.choiceList.append(choiceListFragment); + this._highlightChoice(); + } else { + // ...otherwise show a notice + this.choiceList.append(this._getTemplate('notice', canAddItem.notice)); + } + } else { + // Otherwise show a notice + var dropdownItem = void 0; + var notice = void 0; + + if (this.isSearching) { + notice = Object(__WEBPACK_IMPORTED_MODULE_14__lib_utils__["j" /* isType */])('Function', this.config.noResultsText) ? this.config.noResultsText() : this.config.noResultsText; + + dropdownItem = this._getTemplate('notice', notice, 'no-results'); + } else { + notice = Object(__WEBPACK_IMPORTED_MODULE_14__lib_utils__["j" /* isType */])('Function', this.config.noChoicesText) ? this.config.noChoicesText() : this.config.noChoicesText; + + dropdownItem = this._getTemplate('notice', notice, 'no-choices'); + } + + this.choiceList.append(dropdownItem); + } + } + + /* Items */ + + // Get active items (items that can be selected) + var activeItems = this.store.getItemsFilteredByActive() || []; + // Clear list + this.itemList.clear(); + + if (activeItems.length) { + // Create a fragment to store our list items + // (so we don't have to update the DOM for each item) + var itemListFragment = this.renderItems(activeItems); + + // If we have items to add + if (itemListFragment.childNodes) { + // Update list + this.itemList.append(itemListFragment); + } + } + + this.prevState = this.currentState; + } + + /** + * Select item (a selected item can be deleted) + * @param {Element} item Element to select + * @param {Boolean} [runEvent=true] Whether to trigger 'highlightItem' event + * @return {Object} Class instance + * @public + */ + + }, { + key: 'highlightItem', + value: function highlightItem(item) { + var runEvent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + + if (!item) { + return this; + } + + var id = item.id; + var groupId = item.groupId; + var group = groupId >= 0 ? this.store.getGroupById(groupId) : null; + + this.store.dispatch(Object(__WEBPACK_IMPORTED_MODULE_11__actions_items__["b" /* highlightItem */])(id, true)); + + if (runEvent) { + var eventResponse = { + id: id, + value: item.value, + label: item.label + }; + + if (group && group.value) { + eventResponse.groupValue = group.value; + } + + this.passedElement.triggerEvent(__WEBPACK_IMPORTED_MODULE_8__constants__["d" /* EVENTS */].highlightItem, eventResponse); + } + + return this; + } + + /** + * Deselect item + * @param {Element} item Element to de-select + * @return {Object} Class instance + * @public + */ + + }, { + key: 'unhighlightItem', + value: function unhighlightItem(item) { + if (!item) { + return this; + } + + var id = item.id; + var groupId = item.groupId; + var group = groupId >= 0 ? this.store.getGroupById(groupId) : null; + var eventResponse = { + id: id, + value: item.value, + label: item.label + }; + + if (group && group.value) { + eventResponse.groupValue = group.value; + } + + this.store.dispatch(Object(__WEBPACK_IMPORTED_MODULE_11__actions_items__["b" /* highlightItem */])(id, false)); + this.passedElement.triggerEvent(__WEBPACK_IMPORTED_MODULE_8__constants__["d" /* EVENTS */].highlightItem, eventResponse); + + return this; + } + + /** + * Highlight items within store + * @return {Object} Class instance + * @public + */ + + }, { + key: 'highlightAll', + value: function highlightAll() { + var _this4 = this; + + var items = this.store.getItems(); + items.forEach(function (item) { + return _this4.highlightItem(item); + }); + return this; + } + + /** + * Deselect items within store + * @return {Object} Class instance + * @public + */ + + }, { + key: 'unhighlightAll', + value: function unhighlightAll() { + var _this5 = this; + + var items = this.store.getItems(); + items.forEach(function (item) { + return _this5.unhighlightItem(item); + }); + return this; + } + + /** + * Remove an item from the store by its value + * @param {String} value Value to search for + * @return {Object} Class instance + * @public + */ + + }, { + key: 'removeItemsByValue', + value: function removeItemsByValue(value) { + var _this6 = this; + + if (!value || !Object(__WEBPACK_IMPORTED_MODULE_14__lib_utils__["j" /* isType */])('String', value)) { + return this; + } + + var items = this.store.getItemsFilteredByActive(); + + items.forEach(function (item) { + if (item.value === value) { + _this6._removeItem(item); + } + }); + + return this; + } + + /** + * Remove all items from store array + * @note Removed items are soft deleted + * @param {Number} excludedId Optionally exclude item by ID + * @return {Object} Class instance + * @public + */ + + }, { + key: 'removeActiveItems', + value: function removeActiveItems(excludedId) { + var _this7 = this; + + var items = this.store.getItemsFilteredByActive(); + + items.forEach(function (item) { + if (item.active && excludedId !== item.id) { + _this7._removeItem(item); + } + }); + + return this; + } + + /** + * Remove all selected items from store + * @note Removed items are soft deleted + * @return {Object} Class instance + * @public + */ + + }, { + key: 'removeHighlightedItems', + value: function removeHighlightedItems() { + var _this8 = this; + + var runEvent = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + + var items = this.store.getItemsFilteredByActive(); + + items.forEach(function (item) { + if (item.highlighted && item.active) { + _this8._removeItem(item); + // If this action was performed by the user + // trigger the event + if (runEvent) { + _this8._triggerChange(item.value); + } + } + }); + + return this; + } + + /** + * Show dropdown to user by adding active state class + * @return {Object} Class instance + * @public + */ + + }, { + key: 'showDropdown', + value: function showDropdown() { + var focusInput = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + + if (this.dropdown.isActive) { + return this; + } + + this.containerOuter.open(this.dropdown.getVerticalPos()); + this.dropdown.show(); + this.input.activate(focusInput); + this.passedElement.triggerEvent(__WEBPACK_IMPORTED_MODULE_8__constants__["d" /* EVENTS */].showDropdown, {}); + + return this; + } + + /** + * Hide dropdown from user + * @return {Object} Class instance + * @public + */ + + }, { + key: 'hideDropdown', + value: function hideDropdown() { + var blurInput = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + + if (!this.dropdown.isActive) { + return this; + } + + this.containerOuter.close(); + this.dropdown.hide(); + this.input.deactivate(blurInput); + this.passedElement.triggerEvent(__WEBPACK_IMPORTED_MODULE_8__constants__["d" /* EVENTS */].hideDropdown, {}); + + return this; + } + + /** + * Determine whether to hide or show dropdown based on its current state + * @return {Object} Class instance + * @public + */ + + }, { + key: 'toggleDropdown', + value: function toggleDropdown() { + if (this.dropdown.isActive) { + this.hideDropdown(); + } else { + this.showDropdown(true); + } + + return this; + } + + /** + * Get value(s) of input (i.e. inputted items (text) or selected choices (select)) + * @param {Boolean} valueOnly Get only values of selected items, otherwise return selected items + * @return {Array/String} selected value (select-one) or + * array of selected items (inputs & select-multiple) + * @public + */ + + }, { + key: 'getValue', + value: function getValue() { + var _this9 = this; + + var valueOnly = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + + var items = this.store.getItemsFilteredByActive(); + + var values = items.reduce(function (selectedItems, item) { + var itemValue = valueOnly ? item.value : item; + if (_this9.isTextElement || item.active) { + selectedItems.push(itemValue); + } + + return selectedItems; + }, []); + + return this.isSelectOneElement ? values[0] : values; + } + + /** + * Set value of input. If the input is a select box, a choice will + * be created and selected otherwise an item will created directly. + * @param {Array} args Array of value objects or value strings + * @return {Object} Class instance + * @public + */ + + }, { + key: 'setValue', + value: function setValue(args) { + var _this10 = this; + + if (!this.initialised) { + return this; + } + + // Convert args to an iterable array + var values = [].concat(_toConsumableArray(args)); + var handleValue = function handleValue(item) { + var itemType = Object(__WEBPACK_IMPORTED_MODULE_14__lib_utils__["f" /* getType */])(item).toLowerCase(); + var handleType = { + object: function object() { + if (!item.value) { + return; + } + + // If we are dealing with a select input, we need to create an option first + // that is then selected. For text inputs we can just add items normally. + if (!_this10.isTextElement) { + _this10._addChoice(item.value, item.label, true, false, -1, item.customProperties, item.placeholder); + } else { + _this10._addItem(item.value, item.label, item.id, undefined, item.customProperties, item.placeholder); + } + }, + string: function string() { + if (!_this10.isTextElement) { + _this10._addChoice(item, item, true, false, -1, null); + } else { + _this10._addItem(item); + } + } + }; + + handleType[itemType](); + }; + + values.forEach(function (value) { + return handleValue(value); + }); + + return this; + } + + /** + * Select value of select box via the value of an existing choice + * @param {Array/String} value An array of strings of a single string + * @return {Object} Class instance + * @public + */ + + }, { + key: 'setValueByChoice', + value: function setValueByChoice(value) { + var _this11 = this; + + if (this.isTextElement) { + return this; + } + + var choices = this.store.getChoices(); + // If only one value has been passed, convert to array + var choiceValue = Object(__WEBPACK_IMPORTED_MODULE_14__lib_utils__["j" /* isType */])('Array', value) ? value : [value]; + var findAndSelectChoice = function findAndSelectChoice(val) { + // Check 'value' property exists and the choice isn't already selected + var foundChoice = choices.find(function (choice) { + return choice.value === val; + }); + + if (foundChoice && !foundChoice.selected) { + _this11._addItem(foundChoice.value, foundChoice.label, foundChoice.id, foundChoice.groupId, foundChoice.customProperties, foundChoice.placeholder, foundChoice.keyCode); + } + }; + + // Loop through each value and + choiceValue.forEach(function (val) { + return findAndSelectChoice(val); + }); + + return this; + } + + /** + * Direct populate choices + * @param {Array} choices - Choices to insert + * @param {String} value - Name of 'value' property + * @param {String} label - Name of 'label' property + * @param {Boolean} replaceChoices Whether existing choices should be removed + * @return {Object} Class instance + * @public + */ + + }, { + key: 'setChoices', + value: function setChoices(choices, value, label) { + var _this12 = this; + + var replaceChoices = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; + + if (!this.initialised || !this.isSelectElement || !Object(__WEBPACK_IMPORTED_MODULE_14__lib_utils__["j" /* isType */])('Array', choices) || !value) { + return this; + } + + // Clear choices if needed + if (replaceChoices) { + this._clearChoices(); + } + + // Add choices if passed + if (choices && choices.length) { + this.containerOuter.removeLoadingState(); + + choices.forEach(function (result) { + if (result.choices) { + _this12._addGroup(result, result.id || null, value, label); + } else { + _this12._addChoice(result[value], result[label], result.selected, result.disabled, undefined, result.customProperties, result.placeholder); + } + }); + } + + return this; + } + + /** + * Clear items,choices and groups + * @note Hard delete + * @return {Object} Class instance + * @public + */ + + }, { + key: 'clearStore', + value: function clearStore() { + this.store.dispatch(Object(__WEBPACK_IMPORTED_MODULE_13__actions_misc__["a" /* clearAll */])()); + return this; + } + + /** + * Set value of input to blank + * @return {Object} Class instance + * @public + */ + + }, { + key: 'clearInput', + value: function clearInput() { + var shouldSetInputWidth = !this.isSelectOneElement; + this.input.clear(shouldSetInputWidth); + + if (!this.isTextElement && this.config.searchEnabled) { + this.isSearching = false; + this.store.dispatch(Object(__WEBPACK_IMPORTED_MODULE_10__actions_choices__["a" /* activateChoices */])(true)); + } + + return this; + } + + /** + * Populate options via ajax callback + * @param {Function} fn Function that actually makes an AJAX request + * @return {Object} Class instance + * @public + */ + + }, { + key: 'ajax', + value: function ajax(fn) { + var _this13 = this; + + if (!this.initialised || !this.isSelectElement) { + return this; + } + + // Show loading text + requestAnimationFrame(function () { + return _this13._handleLoadingState(true); + }); + // Run callback + fn(this._ajaxCallback()); + + return this; + } + + /* ===== End of Public functions ====== */ + + /* ============================================= + = Private functions = + ============================================= */ + + /** + * Call change callback + * @param {String} value - last added/deleted/selected value + * @return + * @private + */ + + }, { + key: '_triggerChange', + value: function _triggerChange(value) { + if (!value) { + return; + } + + this.passedElement.triggerEvent(__WEBPACK_IMPORTED_MODULE_8__constants__["d" /* EVENTS */].change, { + value: value + }); + } + + /** + * Select placeholder choice + */ + + }, { + key: '_selectPlaceholderChoice', + value: function _selectPlaceholderChoice() { + var placeholderChoice = this.store.getPlaceholderChoice(); + + if (placeholderChoice) { + this._addItem(placeholderChoice.value, placeholderChoice.label, placeholderChoice.id, placeholderChoice.groupId, null, placeholderChoice.placeholder); + this._triggerChange(placeholderChoice.value); + } + } + + /** + * Process enter/click of an item button + * @param {Array} activeItems The currently active items + * @param {Element} element Button being interacted with + * @return + * @private + */ + + }, { + key: '_handleButtonAction', + value: function _handleButtonAction(activeItems, element) { + if (!activeItems || !element || !this.config.removeItems || !this.config.removeItemButton) { + return; + } + + var itemId = element.parentNode.getAttribute('data-id'); + var itemToRemove = activeItems.find(function (item) { + return item.id === parseInt(itemId, 10); + }); + + // Remove item associated with button + this._removeItem(itemToRemove); + this._triggerChange(itemToRemove.value); + + if (this.isSelectOneElement) { + this._selectPlaceholderChoice(); + } + } + + /** + * Process click of an item + * @param {Array} activeItems The currently active items + * @param {Element} element Item being interacted with + * @param {Boolean} hasShiftKey Whether the user has the shift key active + * @return + * @private + */ + + }, { + key: '_handleItemAction', + value: function _handleItemAction(activeItems, element) { + var _this14 = this; + + var hasShiftKey = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + + if (!activeItems || !element || !this.config.removeItems || this.isSelectOneElement) { + return; + } + + var passedId = element.getAttribute('data-id'); + + // We only want to select one item with a click + // so we deselect any items that aren't the target + // unless shift is being pressed + activeItems.forEach(function (item) { + if (item.id === parseInt(passedId, 10) && !item.highlighted) { + _this14.highlightItem(item); + } else if (!hasShiftKey && item.highlighted) { + _this14.unhighlightItem(item); + } + }); + + // Focus input as without focus, a user cannot do anything with a + // highlighted item + this.input.focus(); + } + + /** + * Process click of a choice + * @param {Array} activeItems The currently active items + * @param {Element} element Choice being interacted with + * @return + */ + + }, { + key: '_handleChoiceAction', + value: function _handleChoiceAction(activeItems, element) { + if (!activeItems || !element) { + return; + } + + // If we are clicking on an option + var id = element.getAttribute('data-id'); + var choice = this.store.getChoiceById(id); + var passedKeyCode = activeItems[0] && activeItems[0].keyCode ? activeItems[0].keyCode : null; + var hasActiveDropdown = this.dropdown.isActive; + + // Update choice keyCode + choice.keyCode = passedKeyCode; + + this.passedElement.triggerEvent(__WEBPACK_IMPORTED_MODULE_8__constants__["d" /* EVENTS */].choice, { + choice: choice + }); + + if (choice && !choice.selected && !choice.disabled) { + var canAddItem = this._canAddItem(activeItems, choice.value); + + if (canAddItem.response) { + this._addItem(choice.value, choice.label, choice.id, choice.groupId, choice.customProperties, choice.placeholder, choice.keyCode); + this._triggerChange(choice.value); + } + } + + this.clearInput(); + + // We wont to close the dropdown if we are dealing with a single select box + if (hasActiveDropdown && this.isSelectOneElement) { + this.hideDropdown(); + this.containerOuter.focus(); + } + } + + /** + * Process back space event + * @param {Array} activeItems items + * @return + * @private + */ + + }, { + key: '_handleBackspace', + value: function _handleBackspace(activeItems) { + if (!this.config.removeItems || !activeItems) { + return; + } + + var lastItem = activeItems[activeItems.length - 1]; + var hasHighlightedItems = activeItems.some(function (item) { + return item.highlighted; + }); + + // If editing the last item is allowed and there are not other selected items, + // we can edit the item value. Otherwise if we can remove items, remove all selected items + if (this.config.editItems && !hasHighlightedItems && lastItem) { + this.input.setValue(lastItem.value); + this.input.setWidth(); + this._removeItem(lastItem); + this._triggerChange(lastItem.value); + } else { + if (!hasHighlightedItems) { + // Highlight last item if none already highlighted + this.highlightItem(lastItem, false); + } + this.removeHighlightedItems(true); + } + } + + /** + * Apply or remove a loading state to the component. + * @param {Boolean} isLoading default value set to 'true'. + * @return + * @private + */ + + }, { + key: '_handleLoadingState', + value: function _handleLoadingState() { + var isLoading = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; + + var placeholderItem = this.itemList.getChild('.' + this.config.classNames.placeholder); + if (isLoading) { + this.containerOuter.addLoadingState(); + if (this.isSelectOneElement) { + if (!placeholderItem) { + placeholderItem = this._getTemplate('placeholder', this.config.loadingText); + this.itemList.append(placeholderItem); + } else { + placeholderItem.innerHTML = this.config.loadingText; + } + } else { + this.input.setPlaceholder(this.config.loadingText); + } + } else { + this.containerOuter.removeLoadingState(); + + if (this.isSelectOneElement) { + placeholderItem.innerHTML = this.placeholder || ''; + } else { + this.input.setPlaceholder(this.placeholder || ''); + } + } + } + + /** + * Validates whether an item can be added by a user + * @param {Array} activeItems The currently active items + * @param {String} value Value of item to add + * @return {Object} Response: Whether user can add item + * Notice: Notice show in dropdown + */ + + }, { + key: '_canAddItem', + value: function _canAddItem(activeItems, value) { + var canAddItem = true; + var notice = Object(__WEBPACK_IMPORTED_MODULE_14__lib_utils__["j" /* isType */])('Function', this.config.addItemText) ? this.config.addItemText(value) : this.config.addItemText; + + if (this.isSelectMultipleElement || this.isTextElement) { + if (this.config.maxItemCount > 0 && this.config.maxItemCount <= activeItems.length) { + // If there is a max entry limit and we have reached that limit + // don't update + canAddItem = false; + notice = Object(__WEBPACK_IMPORTED_MODULE_14__lib_utils__["j" /* isType */])('Function', this.config.maxItemText) ? this.config.maxItemText(this.config.maxItemCount) : this.config.maxItemText; + } + } + + if (this.isTextElement && this.config.addItems && canAddItem && this.config.regexFilter) { + // If a user has supplied a regular expression filter + // determine whether we can update based on whether + // our regular expression passes + canAddItem = Object(__WEBPACK_IMPORTED_MODULE_14__lib_utils__["k" /* regexFilter */])(value, this.config.regexFilter); + } + + // If no duplicates are allowed, and the value already exists + // in the array + var isUnique = !activeItems.some(function (item) { + if (Object(__WEBPACK_IMPORTED_MODULE_14__lib_utils__["j" /* isType */])('String', value)) { + return item.value === value.trim(); + } + + return item.value === value; + }); + + if (!isUnique && !this.config.duplicateItems && !this.isSelectOneElement && canAddItem) { + canAddItem = false; + notice = Object(__WEBPACK_IMPORTED_MODULE_14__lib_utils__["j" /* isType */])('Function', this.config.uniqueItemText) ? this.config.uniqueItemText(value) : this.config.uniqueItemText; + } + + return { + response: canAddItem, + notice: notice + }; + } + + /** + * Retrieve the callback used to populate component's choices in an async way. + * @returns {Function} The callback as a function. + * @private + */ + + }, { + key: '_ajaxCallback', + value: function _ajaxCallback() { + var _this15 = this; + + return function (results, value, label) { + if (!results || !value) { + return; + } + + var parsedResults = Object(__WEBPACK_IMPORTED_MODULE_14__lib_utils__["j" /* isType */])('Object', results) ? [results] : results; + + if (parsedResults && Object(__WEBPACK_IMPORTED_MODULE_14__lib_utils__["j" /* isType */])('Array', parsedResults) && parsedResults.length) { + // Remove loading states/text + _this15._handleLoadingState(false); + // Add each result as a choice + parsedResults.forEach(function (result) { + if (result.choices) { + var groupId = result.id || null; + _this15._addGroup(result, groupId, value, label); + } else { + _this15._addChoice(result[value], result[label], result.selected, result.disabled, undefined, result.customProperties, result.placeholder); + } + }); + + if (_this15.isSelectOneElement) { + _this15._selectPlaceholderChoice(); + } + } else { + // No results, remove loading state + _this15._handleLoadingState(false); + } + }; + } + + /** + * Filter choices based on search value + * @param {String} value Value to filter by + * @return + * @private + */ + + }, { + key: '_searchChoices', + value: function _searchChoices(value) { + var newValue = Object(__WEBPACK_IMPORTED_MODULE_14__lib_utils__["j" /* isType */])('String', value) ? value.trim() : value; + var currentValue = Object(__WEBPACK_IMPORTED_MODULE_14__lib_utils__["j" /* isType */])('String', this.currentValue) ? this.currentValue.trim() : this.currentValue; + + if (newValue.length < 1 && newValue === currentValue + ' ') { + return 0; + } + + // If new value matches the desired length and is not the same as the current value with a space + var haystack = this.store.getSearchableChoices(); + var needle = newValue; + var keys = Object(__WEBPACK_IMPORTED_MODULE_14__lib_utils__["j" /* isType */])('Array', this.config.searchFields) ? this.config.searchFields : [this.config.searchFields]; + var options = Object.assign(this.config.fuseOptions, { keys: keys }); + var fuse = new __WEBPACK_IMPORTED_MODULE_0_fuse_js___default.a(haystack, options); + var results = fuse.search(needle); + + this.currentValue = newValue; + this.highlightPosition = 0; + this.isSearching = true; + this.store.dispatch(Object(__WEBPACK_IMPORTED_MODULE_10__actions_choices__["d" /* filterChoices */])(results)); + + return results.length; + } + + /** + * Determine the action when a user is searching + * @param {String} value Value entered by user + * @return + * @private + */ + + }, { + key: '_handleSearch', + value: function _handleSearch(value) { + if (!value || !this.input.isFocussed) { + return; + } + + var choices = this.store.getChoices(); + var hasUnactiveChoices = choices.some(function (option) { + return !option.active; + }); + + // Check that we have a value to search and the input was an alphanumeric character + if (value && value.length >= this.config.searchFloor) { + var resultCount = this.config.searchChoices ? this._searchChoices(value) : 0; + // Trigger search event + this.passedElement.triggerEvent(__WEBPACK_IMPORTED_MODULE_8__constants__["d" /* EVENTS */].search, { + value: value, + resultCount: resultCount + }); + } else if (hasUnactiveChoices) { + // Otherwise reset choices to active + this.isSearching = false; + this.store.dispatch(Object(__WEBPACK_IMPORTED_MODULE_10__actions_choices__["a" /* activateChoices */])(true)); + } + } + + /** + * Trigger event listeners + * @return + * @private + */ + + }, { + key: '_addEventListeners', + value: function _addEventListeners() { + document.addEventListener('keyup', this._onKeyUp); + document.addEventListener('keydown', this._onKeyDown); + document.addEventListener('click', this._onClick); + document.addEventListener('touchmove', this._onTouchMove); + document.addEventListener('touchend', this._onTouchEnd); + document.addEventListener('mousedown', this._onMouseDown); + document.addEventListener('mouseover', this._onMouseOver); + + if (this.isSelectOneElement) { + this.containerOuter.element.addEventListener('focus', this._onFocus); + this.containerOuter.element.addEventListener('blur', this._onBlur); + } + + this.input.element.addEventListener('focus', this._onFocus); + this.input.element.addEventListener('blur', this._onBlur); + + this.input.addEventListeners(); + } + + /** + * Remove event listeners + * @return + * @private + */ + + }, { + key: '_removeEventListeners', + value: function _removeEventListeners() { + document.removeEventListener('keyup', this._onKeyUp); + document.removeEventListener('keydown', this._onKeyDown); + document.removeEventListener('click', this._onClick); + document.removeEventListener('touchmove', this._onTouchMove); + document.removeEventListener('touchend', this._onTouchEnd); + document.removeEventListener('mousedown', this._onMouseDown); + document.removeEventListener('mouseover', this._onMouseOver); + + if (this.isSelectOneElement) { + this.containerOuter.element.removeEventListener('focus', this._onFocus); + this.containerOuter.element.removeEventListener('blur', this._onBlur); + } + + this.input.element.removeEventListener('focus', this._onFocus); + this.input.element.removeEventListener('blur', this._onBlur); + + this.input.removeEventListeners(); + } + + /** + * Key down event + * @param {Object} e Event + * @return + */ + + }, { + key: '_onKeyDown', + value: function _onKeyDown(e) { + var _this16 = this, + _keyDownActions; + + if (e.target !== this.input.element && !this.containerOuter.element.contains(e.target)) { + return; + } + + var target = e.target; + var activeItems = this.store.getItemsFilteredByActive(); + var hasFocusedInput = this.input.isFocussed; + var hasActiveDropdown = this.dropdown.isActive; + var hasItems = this.itemList.hasChildren; + var keyString = String.fromCharCode(e.keyCode); + var backKey = __WEBPACK_IMPORTED_MODULE_8__constants__["e" /* KEY_CODES */].BACK_KEY; + var deleteKey = __WEBPACK_IMPORTED_MODULE_8__constants__["e" /* KEY_CODES */].DELETE_KEY; + var enterKey = __WEBPACK_IMPORTED_MODULE_8__constants__["e" /* KEY_CODES */].ENTER_KEY; + var aKey = __WEBPACK_IMPORTED_MODULE_8__constants__["e" /* KEY_CODES */].A_KEY; + var escapeKey = __WEBPACK_IMPORTED_MODULE_8__constants__["e" /* KEY_CODES */].ESC_KEY; + var upKey = __WEBPACK_IMPORTED_MODULE_8__constants__["e" /* KEY_CODES */].UP_KEY; + var downKey = __WEBPACK_IMPORTED_MODULE_8__constants__["e" /* KEY_CODES */].DOWN_KEY; + var pageUpKey = __WEBPACK_IMPORTED_MODULE_8__constants__["e" /* KEY_CODES */].PAGE_UP_KEY; + var pageDownKey = __WEBPACK_IMPORTED_MODULE_8__constants__["e" /* KEY_CODES */].PAGE_DOWN_KEY; + var ctrlDownKey = e.ctrlKey || e.metaKey; + + // If a user is typing and the dropdown is not active + if (!this.isTextElement && /[a-zA-Z0-9-_ ]/.test(keyString)) { + this.showDropdown(true); + } + + this.canSearch = this.config.searchEnabled; + + var onAKey = function onAKey() { + // If CTRL + A or CMD + A have been pressed and there are items to select + if (ctrlDownKey && hasItems) { + _this16.canSearch = false; + if (_this16.config.removeItems && !_this16.input.getValue() && _this16.input.element === document.activeElement) { + // Highlight items + _this16.highlightAll(); + } + } + }; + + var onEnterKey = function onEnterKey() { + // If enter key is pressed and the input has a value + if (_this16.isTextElement && target.value) { + var value = _this16.input.getValue(); + var canAddItem = _this16._canAddItem(activeItems, value); + + // All is good, add + if (canAddItem.response) { + _this16.hideDropdown(); + _this16._addItem(value); + _this16._triggerChange(value); + _this16.clearInput(); + } + } + + if (target.hasAttribute('data-button')) { + _this16._handleButtonAction(activeItems, target); + e.preventDefault(); + } + + if (hasActiveDropdown) { + e.preventDefault(); + var highlighted = _this16.dropdown.getChild('.' + _this16.config.classNames.highlightedState); + + // If we have a highlighted choice + if (highlighted) { + // add enter keyCode value + if (activeItems[0]) { + activeItems[0].keyCode = enterKey; + } + _this16._handleChoiceAction(activeItems, highlighted); + } + } else if (_this16.isSelectOneElement) { + // Open single select dropdown if it's not active + _this16.showDropdown(true); + e.preventDefault(); + } + }; + + var onEscapeKey = function onEscapeKey() { + if (hasActiveDropdown) { + _this16.hideDropdown(); + _this16.containerOuter.focus(); + } + }; + + var onDirectionKey = function onDirectionKey() { + // If up or down key is pressed, traverse through options + if (hasActiveDropdown || _this16.isSelectOneElement) { + // Show dropdown if focus + _this16.showDropdown(true); + + _this16.canSearch = false; + + var directionInt = e.keyCode === downKey || e.keyCode === pageDownKey ? 1 : -1; + var skipKey = e.metaKey || e.keyCode === pageDownKey || e.keyCode === pageUpKey; + + var nextEl = void 0; + if (skipKey) { + if (directionInt > 0) { + nextEl = Array.from(_this16.dropdown.element.querySelectorAll('[data-choice-selectable]')).pop(); + } else { + nextEl = _this16.dropdown.element.querySelector('[data-choice-selectable]'); + } + } else { + var currentEl = _this16.dropdown.element.querySelector('.' + _this16.config.classNames.highlightedState); + if (currentEl) { + nextEl = Object(__WEBPACK_IMPORTED_MODULE_14__lib_utils__["e" /* getAdjacentEl */])(currentEl, '[data-choice-selectable]', directionInt); + } else { + nextEl = _this16.dropdown.element.querySelector('[data-choice-selectable]'); + } + } + + if (nextEl) { + // We prevent default to stop the cursor moving + // when pressing the arrow + if (!Object(__WEBPACK_IMPORTED_MODULE_14__lib_utils__["i" /* isScrolledIntoView */])(nextEl, _this16.choiceList, directionInt)) { + _this16._scrollToChoice(nextEl, directionInt); + } + _this16._highlightChoice(nextEl); + } + + // Prevent default to maintain cursor position whilst + // traversing dropdown options + e.preventDefault(); + } + }; + + var onDeleteKey = function onDeleteKey() { + // If backspace or delete key is pressed and the input has no value + if (hasFocusedInput && !e.target.value && !_this16.isSelectOneElement) { + _this16._handleBackspace(activeItems); + e.preventDefault(); + } + }; + + // Map keys to key actions + var keyDownActions = (_keyDownActions = {}, _defineProperty(_keyDownActions, aKey, onAKey), _defineProperty(_keyDownActions, enterKey, onEnterKey), _defineProperty(_keyDownActions, escapeKey, onEscapeKey), _defineProperty(_keyDownActions, upKey, onDirectionKey), _defineProperty(_keyDownActions, pageUpKey, onDirectionKey), _defineProperty(_keyDownActions, downKey, onDirectionKey), _defineProperty(_keyDownActions, pageDownKey, onDirectionKey), _defineProperty(_keyDownActions, deleteKey, onDeleteKey), _defineProperty(_keyDownActions, backKey, onDeleteKey), _keyDownActions); + + // If keycode has a function, run it + if (keyDownActions[e.keyCode]) { + keyDownActions[e.keyCode](); + } + } + + /** + * Key up event + * @param {Object} e Event + * @return + * @private + */ + + }, { + key: '_onKeyUp', + value: function _onKeyUp(e) { + if (e.target !== this.input.element) { + return; + } + + var value = this.input.getValue(); + var activeItems = this.store.getItemsFilteredByActive(); + var canAddItem = this._canAddItem(activeItems, value); + + // We are typing into a text input and have a value, we want to show a dropdown + // notice. Otherwise hide the dropdown + if (this.isTextElement) { + if (value) { + if (canAddItem.notice) { + var dropdownItem = this._getTemplate('notice', canAddItem.notice); + this.dropdown.element.innerHTML = dropdownItem.outerHTML; + } + + if (canAddItem.response === true) { + this.showDropdown(); + } else if (!canAddItem.notice) { + this.hideDropdown(); + } + } else { + this.hideDropdown(); + } + } else { + var backKey = __WEBPACK_IMPORTED_MODULE_8__constants__["e" /* KEY_CODES */].BACK_KEY; + var deleteKey = __WEBPACK_IMPORTED_MODULE_8__constants__["e" /* KEY_CODES */].DELETE_KEY; + + // If user has removed value... + if ((e.keyCode === backKey || e.keyCode === deleteKey) && !e.target.value) { + // ...and it is a multiple select input, activate choices (if searching) + if (!this.isTextElement && this.isSearching) { + this.isSearching = false; + this.store.dispatch(Object(__WEBPACK_IMPORTED_MODULE_10__actions_choices__["a" /* activateChoices */])(true)); + } + } else if (this.canSearch && canAddItem.response) { + this._handleSearch(this.input.getValue()); + } + } + // Re-establish canSearch value from changes in _onKeyDown + this.canSearch = this.config.searchEnabled; + } + + /** + * Touch move event + * @return + * @private + */ + + }, { + key: '_onTouchMove', + value: function _onTouchMove() { + if (this.wasTap === true) { + this.wasTap = false; + } + } + + /** + * Touch end event + * @param {Object} e Event + * @return + * @private + */ + + }, { + key: '_onTouchEnd', + value: function _onTouchEnd(e) { + var target = e.target || e.touches[0].target; + + // If a user tapped within our container... + if (this.wasTap === true && this.containerOuter.element.contains(target)) { + // ...and we aren't dealing with a single select box, show dropdown/focus input + if ((target === this.containerOuter.element || target === this.containerInner.element) && !this.isSelectOneElement) { + if (this.isTextElement) { + // If text element, we only want to focus the input + this.input.focus(); + } else { + // If a select box, we want to show the dropdown + this.showDropdown(true); + } + } + // Prevents focus event firing + e.stopPropagation(); + } + + this.wasTap = true; + } + + /** + * Mouse down event + * @param {Object} e Event + * @return + * @private + */ + + }, { + key: '_onMouseDown', + value: function _onMouseDown(e) { + var target = e.target; + + // If we have our mouse down on the scrollbar and are on IE11... + if (target === this.choiceList && this.isIe11) { + this.isScrollingOnIe = true; + } + + if (this.containerOuter.element.contains(target) && target !== this.input.element) { + var activeItems = this.store.getItemsFilteredByActive(); + var hasShiftKey = e.shiftKey; + + var buttonTarget = Object(__WEBPACK_IMPORTED_MODULE_14__lib_utils__["c" /* findAncestorByAttrName */])(target, 'data-button'); + var itemTarget = Object(__WEBPACK_IMPORTED_MODULE_14__lib_utils__["c" /* findAncestorByAttrName */])(target, 'data-item'); + var choiceTarget = Object(__WEBPACK_IMPORTED_MODULE_14__lib_utils__["c" /* findAncestorByAttrName */])(target, 'data-choice'); + + if (buttonTarget) { + this._handleButtonAction(activeItems, buttonTarget); + } else if (itemTarget) { + this._handleItemAction(activeItems, itemTarget, hasShiftKey); + } else if (choiceTarget) { + this._handleChoiceAction(activeItems, choiceTarget); + } + + e.preventDefault(); + } + } + + /** + * Mouse over (hover) event + * @param {Object} e Event + * @return + * @private + */ + + }, { + key: '_onMouseOver', + value: function _onMouseOver(e) { + // If the dropdown is either the target or one of its children is the target + var targetWithinDropdown = e.target === this.dropdown || this.dropdown.element.contains(e.target); + var shouldHighlightChoice = targetWithinDropdown && e.target.hasAttribute('data-choice'); + + if (shouldHighlightChoice) { + this._highlightChoice(e.target); + } + } + + /** + * Click event + * @param {Object} e Event + * @return + * @private + */ + + }, { + key: '_onClick', + value: function _onClick(e) { + var target = e.target; + var hasActiveDropdown = this.dropdown.isActive; + var activeItems = this.store.getItemsFilteredByActive(); + + // If target is something that concerns us + if (this.containerOuter.element.contains(target)) { + if (!hasActiveDropdown) { + if (this.isTextElement) { + if (document.activeElement !== this.input.element) { + this.input.focus(); + } + } else if (this.canSearch) { + this.showDropdown(true); + } else { + this.showDropdown(); + // code smell + this.containerOuter.focus(); + } + } else if (this.isSelectOneElement && target !== this.input.element && !this.dropdown.element.contains(target)) { + this.hideDropdown(true); + } + } else { + var hasHighlightedItems = activeItems.some(function (item) { + return item.highlighted; + }); + + // De-select any highlighted items + if (hasHighlightedItems) { + this.unhighlightAll(); + } + + // Remove focus state + this.containerOuter.removeFocusState(); + + // Close all other dropdowns + this.hideDropdown(); + } + } + + /** + * Focus event + * @param {Object} e Event + * @return + * @private + */ + + }, { + key: '_onFocus', + value: function _onFocus(e) { + var _this17 = this; + + var target = e.target; + if (!this.containerOuter.element.contains(target)) { + return; + } + + var focusActions = { + text: function text() { + if (target === _this17.input.element) { + _this17.containerOuter.addFocusState(); + } + }, + 'select-one': function selectOne() { + _this17.containerOuter.addFocusState(); + if (target === _this17.input.element) { + // Show dropdown if it isn't already showing + _this17.showDropdown(); + } + }, + 'select-multiple': function selectMultiple() { + if (target === _this17.input.element) { + // If element is a select box, the focused element is the container and the dropdown + // isn't already open, focus and show dropdown + _this17.containerOuter.addFocusState(); + _this17.showDropdown(true); + } + } + }; + + focusActions[this.passedElement.element.type](); + } + + /** + * Blur event + * @param {Object} e Event + * @return + * @private + */ + + }, { + key: '_onBlur', + value: function _onBlur(e) { + var _this18 = this; + + var target = e.target; + // If target is something that concerns us + if (this.containerOuter.element.contains(target) && !this.isScrollingOnIe) { + var activeItems = this.store.getItemsFilteredByActive(); + var hasHighlightedItems = activeItems.some(function (item) { + return item.highlighted; + }); + var blurActions = { + text: function text() { + if (target === _this18.input.element) { + // Remove the focus state + _this18.containerOuter.removeFocusState(); + // De-select any highlighted items + if (hasHighlightedItems) { + _this18.unhighlightAll(); + } + _this18.hideDropdown(); + } + }, + 'select-one': function selectOne() { + _this18.containerOuter.removeFocusState(); + if (target === _this18.containerOuter.element) { + // Hide dropdown if it is showing + if (!_this18.canSearch) { + _this18.hideDropdown(); + } + } + if (target === _this18.input.element) { + // Hide dropdown if it is showing + _this18.hideDropdown(); + } + }, + 'select-multiple': function selectMultiple() { + if (target === _this18.input.element) { + // Remove the focus state + _this18.containerOuter.removeFocusState(); + _this18.hideDropdown(); + // De-select any highlighted items + if (hasHighlightedItems) { + _this18.unhighlightAll(); + } + } + } + }; + + blurActions[this.passedElement.element.type](); + } else { + // On IE11, clicking the scollbar blurs our input and thus + // closes the dropdown. To stop this, we refocus our input + // if we know we are on IE *and* are scrolling. + this.isScrollingOnIe = false; + this.input.element.focus(); + } + } + + /** + * Scroll to an option element + * @param {HTMLElement} choice Option to scroll to + * @param {Number} direction Whether option is above or below + * @return + * @private + */ + + }, { + key: '_scrollToChoice', + value: function _scrollToChoice(choice, direction) { + var _this19 = this; + + if (!choice) { + return; + } + + var dropdownHeight = this.choiceList.height; + var choiceHeight = choice.offsetHeight; + // Distance from bottom of element to top of parent + var choicePos = choice.offsetTop + choiceHeight; + // Scroll position of dropdown + var containerScrollPos = this.choiceList.scrollPos + dropdownHeight; + // Difference between the choice and scroll position + var endPoint = direction > 0 ? this.choiceList.scrollPos + choicePos - containerScrollPos : choice.offsetTop; + + var animateScroll = function animateScroll() { + var strength = __WEBPACK_IMPORTED_MODULE_8__constants__["f" /* SCROLLING_SPEED */]; + var choiceListScrollTop = _this19.choiceList.scrollPos; + var continueAnimation = false; + var easing = void 0; + var distance = void 0; + + if (direction > 0) { + easing = (endPoint - choiceListScrollTop) / strength; + distance = easing > 1 ? easing : 1; + + _this19.choiceList.scrollTo(choiceListScrollTop + distance); + if (choiceListScrollTop < endPoint) { + continueAnimation = true; + } + } else { + easing = (choiceListScrollTop - endPoint) / strength; + distance = easing > 1 ? easing : 1; + + _this19.choiceList.scrollTo(choiceListScrollTop - distance); + if (choiceListScrollTop > endPoint) { + continueAnimation = true; + } + } + + if (continueAnimation) { + requestAnimationFrame(function (time) { + animateScroll(time, endPoint, direction); + }); + } + }; + + requestAnimationFrame(function (time) { + animateScroll(time, endPoint, direction); + }); + } + + /** + * Highlight choice + * @param {HTMLElement} [el] Element to highlight + * @return + * @private + */ + + }, { + key: '_highlightChoice', + value: function _highlightChoice() { + var _this20 = this; + + var el = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + + // Highlight first element in dropdown + var choices = Array.from(this.dropdown.element.querySelectorAll('[data-choice-selectable]')); + var passedEl = el; + + if (choices && choices.length) { + var highlightedChoices = Array.from(this.dropdown.element.querySelectorAll('.' + this.config.classNames.highlightedState)); + var hasActiveDropdown = this.dropdown.isActive; + + // Remove any highlighted choices + highlightedChoices.forEach(function (choice) { + choice.classList.remove(_this20.config.classNames.highlightedState); + choice.setAttribute('aria-selected', 'false'); + }); + + if (passedEl) { + this.highlightPosition = choices.indexOf(passedEl); + } else { + // Highlight choice based on last known highlight location + if (choices.length > this.highlightPosition) { + // If we have an option to highlight + passedEl = choices[this.highlightPosition]; + } else { + // Otherwise highlight the option before + passedEl = choices[choices.length - 1]; + } + + if (!passedEl) { + passedEl = choices[0]; + } + } + + // Highlight given option, and set accessiblity attributes + passedEl.classList.add(this.config.classNames.highlightedState); + passedEl.setAttribute('aria-selected', 'true'); + + if (hasActiveDropdown) { + // IE11 ignores aria-label and blocks virtual keyboard + // if aria-activedescendant is set without a dropdown + this.input.setActiveDescendant(passedEl.id); + this.containerOuter.setActiveDescendant(passedEl.id); + } + } + } + + /** + * Add item to store with correct value + * @param {String} value Value to add to store + * @param {String} [label] Label to add to store + * @param {Number} [choiceId=-1] ID of the associated choice that was selected + * @param {Number} [groupId=-1] ID of group choice is within. Negative number indicates no group + * @param {Object} [customProperties] Object containing user defined properties + * @return {Object} Class instance + * @public + */ + + }, { + key: '_addItem', + value: function _addItem(value) { + var label = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; + var choiceId = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : -1; + var groupId = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : -1; + var customProperties = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null; + var placeholder = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false; + var keyCode = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : null; + + var passedValue = Object(__WEBPACK_IMPORTED_MODULE_14__lib_utils__["j" /* isType */])('String', value) ? value.trim() : value; + var passedKeyCode = keyCode; + var items = this.store.getItems(); + var passedLabel = label || passedValue; + var passedOptionId = parseInt(choiceId, 10) || -1; + + // Get group if group ID passed + var group = groupId >= 0 ? this.store.getGroupById(groupId) : null; + + // Generate unique id + var id = items ? items.length + 1 : 1; + + // If a prepended value has been passed, prepend it + if (this.config.prependValue) { + passedValue = this.config.prependValue + passedValue.toString(); + } + + // If an appended value has been passed, append it + if (this.config.appendValue) { + passedValue += this.config.appendValue.toString(); + } + + this.store.dispatch(Object(__WEBPACK_IMPORTED_MODULE_11__actions_items__["a" /* addItem */])(passedValue, passedLabel, id, passedOptionId, groupId, customProperties, placeholder, passedKeyCode)); + + if (this.isSelectOneElement) { + this.removeActiveItems(id); + } + + // Trigger change event + if (group && group.value) { + this.passedElement.triggerEvent(__WEBPACK_IMPORTED_MODULE_8__constants__["d" /* EVENTS */].addItem, { + id: id, + value: passedValue, + label: passedLabel, + groupValue: group.value, + keyCode: passedKeyCode + }); + } else { + this.passedElement.triggerEvent(__WEBPACK_IMPORTED_MODULE_8__constants__["d" /* EVENTS */].addItem, { + id: id, + value: passedValue, + label: passedLabel, + keyCode: passedKeyCode + }); + } + + return this; + } + + /** + * Remove item from store + * @param {Object} item Item to remove + * @return {Object} Class instance + * @public + */ + + }, { + key: '_removeItem', + value: function _removeItem(item) { + if (!item || !Object(__WEBPACK_IMPORTED_MODULE_14__lib_utils__["j" /* isType */])('Object', item)) { + return this; + } + + var id = item.id; + var value = item.value; + var label = item.label; + var choiceId = item.choiceId; + var groupId = item.groupId; + var group = groupId >= 0 ? this.store.getGroupById(groupId) : null; + + this.store.dispatch(Object(__WEBPACK_IMPORTED_MODULE_11__actions_items__["c" /* removeItem */])(id, choiceId)); + + if (group && group.value) { + this.passedElement.triggerEvent(__WEBPACK_IMPORTED_MODULE_8__constants__["d" /* EVENTS */].removeItem, { + id: id, + value: value, + label: label, + groupValue: group.value + }); + } else { + this.passedElement.triggerEvent(__WEBPACK_IMPORTED_MODULE_8__constants__["d" /* EVENTS */].removeItem, { + id: id, + value: value, + label: label + }); + } + + return this; + } + + /** + * Add choice to dropdown + * @param {String} value Value of choice + * @param {String} [label] Label of choice + * @param {Boolean} [isSelected=false] Whether choice is selected + * @param {Boolean} [isDisabled=false] Whether choice is disabled + * @param {Number} [groupId=-1] ID of group choice is within. Negative number indicates no group + * @param {Object} [customProperties] Object containing user defined properties + * @return + * @private + */ + + }, { + key: '_addChoice', + value: function _addChoice(value) { + var label = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; + var isSelected = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + var isDisabled = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; + var groupId = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : -1; + var customProperties = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : null; + var placeholder = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : false; + var keyCode = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : null; + + if (typeof value === 'undefined' || value === null) { + return; + } + + // Generate unique id + var choices = this.store.getChoices(); + var choiceLabel = label || value; + var choiceId = choices ? choices.length + 1 : 1; + var choiceElementId = this.baseId + '-' + this.idNames.itemChoice + '-' + choiceId; + + this.store.dispatch(Object(__WEBPACK_IMPORTED_MODULE_10__actions_choices__["b" /* addChoice */])(value, choiceLabel, choiceId, groupId, isDisabled, choiceElementId, customProperties, placeholder, keyCode)); + + if (isSelected) { + this._addItem(value, choiceLabel, choiceId, undefined, customProperties, placeholder, keyCode); + } + } + + /** + * Clear all choices added to the store. + * @return + * @private + */ + + }, { + key: '_clearChoices', + value: function _clearChoices() { + this.store.dispatch(Object(__WEBPACK_IMPORTED_MODULE_10__actions_choices__["c" /* clearChoices */])()); + } + + /** + * Add group to dropdown + * @param {Object} group Group to add + * @param {Number} id Group ID + * @param {String} [valueKey] name of the value property on the object + * @param {String} [labelKey] name of the label property on the object + * @return + * @private + */ + + }, { + key: '_addGroup', + value: function _addGroup(group, id) { + var _this21 = this; + + var valueKey = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'value'; + var labelKey = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'label'; + + var groupChoices = Object(__WEBPACK_IMPORTED_MODULE_14__lib_utils__["j" /* isType */])('Object', group) ? group.choices : Array.from(group.getElementsByTagName('OPTION')); + var groupId = id || Math.floor(new Date().valueOf() * Math.random()); + var isDisabled = group.disabled ? group.disabled : false; + + if (groupChoices) { + this.store.dispatch(Object(__WEBPACK_IMPORTED_MODULE_12__actions_groups__["a" /* addGroup */])(group.label, groupId, true, isDisabled)); + + groupChoices.forEach(function (option) { + var isOptDisabled = option.disabled || option.parentNode && option.parentNode.disabled; + _this21._addChoice(option[valueKey], Object(__WEBPACK_IMPORTED_MODULE_14__lib_utils__["j" /* isType */])('Object', option) ? option[labelKey] : option.innerHTML, option.selected, isOptDisabled, groupId, option.customProperties, option.placeholder); + }); + } else { + this.store.dispatch(Object(__WEBPACK_IMPORTED_MODULE_12__actions_groups__["a" /* addGroup */])(group.label, group.id, false, group.disabled)); + } + } + + /** + * Get template from name + * @param {String} template Name of template to get + * @param {...} args Data to pass to template + * @return {HTMLElement} Template + * @private + */ + + }, { + key: '_getTemplate', + value: function _getTemplate(template) { + var _templates$template; + + if (!template) { + return null; + } + var templates = this.config.templates; + var globalClasses = this.config.classNames; + + for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + + return (_templates$template = templates[template]).call.apply(_templates$template, [this, globalClasses].concat(args)); + } + + /** + * Create HTML element based on type and arguments + * @return + * @private + */ + + }, { + key: '_createTemplates', + value: function _createTemplates() { + // User's custom templates + var callbackTemplate = this.config.callbackOnCreateTemplates; + var userTemplates = {}; + if (callbackTemplate && Object(__WEBPACK_IMPORTED_MODULE_14__lib_utils__["j" /* isType */])('Function', callbackTemplate)) { + userTemplates = callbackTemplate.call(this, __WEBPACK_IMPORTED_MODULE_14__lib_utils__["n" /* strToEl */]); + } + + this.config.templates = Object(__WEBPACK_IMPORTED_MODULE_14__lib_utils__["b" /* extend */])(__WEBPACK_IMPORTED_MODULE_9__templates__["a" /* TEMPLATES */], userTemplates); + } + + /** + * Create DOM structure around passed select element + * @return + * @private + */ + + }, { + key: '_createInput', + value: function _createInput() { + var _this22 = this; + + var direction = this.passedElement.element.getAttribute('dir') || 'ltr'; + var containerOuter = this._getTemplate('containerOuter', direction, this.isSelectElement, this.isSelectOneElement, this.config.searchEnabled, this.passedElement.element.type); + var containerInner = this._getTemplate('containerInner'); + var itemList = this._getTemplate('itemList', this.isSelectOneElement); + var choiceList = this._getTemplate('choiceList', this.isSelectOneElement); + var input = this._getTemplate('input'); + var dropdown = this._getTemplate('dropdown'); + + this.containerOuter = new __WEBPACK_IMPORTED_MODULE_3__components_container__["a" /* default */](this, containerOuter, this.config.classNames); + this.containerInner = new __WEBPACK_IMPORTED_MODULE_3__components_container__["a" /* default */](this, containerInner, this.config.classNames); + this.input = new __WEBPACK_IMPORTED_MODULE_4__components_input__["a" /* default */](this, input, this.config.classNames); + this.choiceList = new __WEBPACK_IMPORTED_MODULE_5__components_list__["a" /* default */](this, choiceList, this.config.classNames); + this.itemList = new __WEBPACK_IMPORTED_MODULE_5__components_list__["a" /* default */](this, itemList, this.config.classNames); + this.dropdown = new __WEBPACK_IMPORTED_MODULE_2__components_dropdown__["a" /* default */](this, dropdown, this.config.classNames); + + this.passedElement.conceal(); + + // Wrap input in container preserving DOM ordering + Object(__WEBPACK_IMPORTED_MODULE_14__lib_utils__["o" /* wrap */])(this.passedElement.element, this.containerInner.element); + // Wrapper inner container with outer container + Object(__WEBPACK_IMPORTED_MODULE_14__lib_utils__["o" /* wrap */])(this.containerInner.element, this.containerOuter.element); + + if (this.isSelectOneElement) { + this.input.setPlaceholder(this.config.searchPlaceholderValue || ''); + } else if (this.placeholder) { + this.input.setPlaceholder(this.placeholder); + this.input.setWidth(true); + } + + if (!this.config.addItems) { + this.disable(); + } + + this.containerOuter.element.appendChild(this.containerInner.element); + this.containerOuter.element.appendChild(this.dropdown.element); + this.containerInner.element.appendChild(itemList); + + if (!this.isTextElement) { + dropdown.appendChild(choiceList); + } + + if (!this.isSelectOneElement) { + this.containerInner.element.appendChild(this.input.element); + } else if (this.canSearch) { + dropdown.insertBefore(input, dropdown.firstChild); + } + + if (this.isSelectElement) { + var passedGroups = this.passedElement.getOptionGroups(); + + this.highlightPosition = 0; + this.isSearching = false; + + if (passedGroups && passedGroups.length) { + // If we have a placeholder option + var placeholderChoice = this.passedElement.getPlaceholderOption(); + if (placeholderChoice && placeholderChoice.parentNode.tagName === 'SELECT') { + this._addChoice(placeholderChoice.value, placeholderChoice.innerHTML, placeholderChoice.selected, placeholderChoice.disabled, undefined, undefined, + /* placeholder */true); + } + + passedGroups.forEach(function (group) { + _this22._addGroup(group, group.id || null); + }); + } else { + var passedOptions = this.passedElement.getOptions(); + var filter = this.config.sortFilter; + var allChoices = this.presetChoices; + + // Create array of options from option elements + passedOptions.forEach(function (o) { + allChoices.push({ + value: o.value, + label: o.innerHTML, + selected: o.selected, + disabled: o.disabled || o.parentNode.disabled, + placeholder: o.hasAttribute('placeholder') + }); + }); + + // If sorting is enabled or the user is searching, filter choices + if (this.config.shouldSort) { + allChoices.sort(filter); + } + + // Determine whether there is a selected choice + var hasSelectedChoice = allChoices.some(function (choice) { + return choice.selected; + }); + var handleChoice = function handleChoice(choice, index) { + if (_this22.isSelectElement) { + // If the choice is actually a group + if (choice.choices) { + _this22._addGroup(choice, choice.id || null); + } else { + // If there is a selected choice already or the choice is not + // the first in the array, add each choice normally + // Otherwise pre-select the first choice in the array if it's a single select + var shouldPreselect = _this22.isSelectOneElement && !hasSelectedChoice && index === 0; + var isSelected = shouldPreselect ? true : choice.selected; + var isDisabled = shouldPreselect ? false : choice.disabled; + + _this22._addChoice(choice.value, choice.label, isSelected, isDisabled, undefined, choice.customProperties, choice.placeholder); + } + } else { + _this22._addChoice(choice.value, choice.label, choice.selected, choice.disabled, undefined, choice.customProperties, choice.placeholder); + } + }; + + // Add each choice + allChoices.forEach(function (choice, index) { + return handleChoice(choice, index); + }); + } + } else if (this.isTextElement) { + var handlePresetItem = function handlePresetItem(item) { + var itemType = Object(__WEBPACK_IMPORTED_MODULE_14__lib_utils__["f" /* getType */])(item); + if (itemType === 'Object') { + if (!item.value) { + return; + } + _this22._addItem(item.value, item.label, item.id, undefined, item.customProperties, item.placeholder); + } else if (itemType === 'String') { + _this22._addItem(item); + } + }; + + this.presetItems.forEach(function (item) { + return handlePresetItem(item); + }); + } + } + + /* ===== End of Private functions ====== */ + + }]); + + return Choices; +}(); + +Choices.userDefaults = {}; + +module.exports = Choices; +/* WEBPACK VAR INJECTION */}.call(__webpack_exports__, __webpack_require__(2)(module))) + +/***/ }), +/* 8 */ +/***/ (function(module, exports, __webpack_require__) { + +/*! + * Fuse.js v3.2.0 - Lightweight fuzzy-search (http://fusejs.io) + * + * Copyright (c) 2012-2017 Kirollos Risk (http://kiro.me) + * All Rights Reserved. Apache Software License 2.0 + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ +(function webpackUniversalModuleDefinition(root, factory) { + if(true) + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define("Fuse", [], factory); + else if(typeof exports === 'object') + exports["Fuse"] = factory(); + else + root["Fuse"] = factory(); +})(this, function() { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // identity function for calling harmony imports with the correct context +/******/ __webpack_require__.i = function(value) { return value; }; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { +/******/ configurable: false, +/******/ enumerable: true, +/******/ get: getter +/******/ }); +/******/ } +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 8); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ (function(module, exports, __webpack_require__) { - module.exports = __webpack_require__(1); +"use strict"; +module.exports = function (obj) { + return Object.prototype.toString.call(obj) === '[object Array]'; +}; + /***/ }), /* 1 */ /***/ (function(module, exports, __webpack_require__) { - 'use strict'; - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _fuse = __webpack_require__(2); - - var _fuse2 = _interopRequireDefault(_fuse); - - var _classnames = __webpack_require__(3); - - var _classnames2 = _interopRequireDefault(_classnames); - - var _store = __webpack_require__(4); - - var _store2 = _interopRequireDefault(_store); - - var _dropdown = __webpack_require__(30); - - var _dropdown2 = _interopRequireDefault(_dropdown); - - var _container = __webpack_require__(31); - - var _container2 = _interopRequireDefault(_container); - - var _input = __webpack_require__(32); - - var _input2 = _interopRequireDefault(_input); - - var _list = __webpack_require__(34); - - var _list2 = _interopRequireDefault(_list); - - var _actions = __webpack_require__(35); - - var _utils = __webpack_require__(33); - - __webpack_require__(36); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } - - function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - /** - * Choices - */ - var Choices = function () { - function Choices() { - var element = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '[data-choice]'; - var userConfig = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - - _classCallCheck(this, Choices); - - // If there are multiple elements, create a new instance - // for each element besides the first one (as that already has an instance) - if ((0, _utils.isType)('String', element)) { - var elements = document.querySelectorAll(element); - if (elements.length > 1) { - for (var i = 1; i < elements.length; i += 1) { - var el = elements[i]; - /* eslint-disable no-new */ - new Choices(el, userConfig); - } - } - } - - var defaultConfig = { - silent: false, - items: [], - choices: [], - renderChoiceLimit: -1, - maxItemCount: -1, - addItems: true, - removeItems: true, - removeItemButton: false, - editItems: false, - duplicateItems: true, - delimiter: ',', - paste: true, - searchEnabled: true, - searchChoices: true, - searchFloor: 1, - searchResultLimit: 4, - searchFields: ['label', 'value'], - position: 'auto', - resetScrollPosition: true, - regexFilter: null, - shouldSort: true, - shouldSortItems: false, - sortFilter: _utils.sortByAlpha, - placeholder: true, - placeholderValue: null, - searchPlaceholderValue: null, - prependValue: null, - appendValue: null, - renderSelectedChoices: 'auto', - loadingText: 'Loading...', - noResultsText: 'No results found', - noChoicesText: 'No choices to choose from', - itemSelectText: 'Press to select', - addItemText: function addItemText(value) { - return 'Press Enter to add "' + value + '"'; - }, - maxItemText: function maxItemText(maxItemCount) { - return 'Only ' + maxItemCount + ' values can be added.'; - }, - uniqueItemText: 'Only unique values can be added.', - classNames: { - containerOuter: 'choices', - containerInner: 'choices__inner', - input: 'choices__input', - inputCloned: 'choices__input--cloned', - list: 'choices__list', - listItems: 'choices__list--multiple', - listSingle: 'choices__list--single', - listDropdown: 'choices__list--dropdown', - item: 'choices__item', - itemSelectable: 'choices__item--selectable', - itemDisabled: 'choices__item--disabled', - itemChoice: 'choices__item--choice', - placeholder: 'choices__placeholder', - group: 'choices__group', - groupHeading: 'choices__heading', - button: 'choices__button', - activeState: 'is-active', - focusState: 'is-focused', - openState: 'is-open', - disabledState: 'is-disabled', - highlightedState: 'is-highlighted', - hiddenState: 'is-hidden', - flippedState: 'is-flipped', - loadingState: 'is-loading', - noResults: 'has-no-results', - noChoices: 'has-no-choices' - }, - fuseOptions: { - include: 'score' - }, - callbackOnInit: null, - callbackOnCreateTemplates: null - }; - - this.idNames = { - itemChoice: 'item-choice' - }; - - // Merge options with user options - this.config = (0, _utils.extend)(defaultConfig, Choices.userDefaults, userConfig); - - if (!['auto', 'always'].includes(this.config.renderSelectedChoices)) { - this.config.renderSelectedChoices = 'auto'; - } - - // Create data store - this.store = new _store2.default(this.render); - - // State tracking - this.initialised = false; - this.currentState = {}; - this.prevState = {}; - this.currentValue = ''; - - // Retrieve triggering element (i.e. element with 'data-choice' trigger) - this.element = element; - this.passedElement = (0, _utils.isType)('String', element) ? document.querySelector(element) : element; - - if (!this.passedElement) { - if (!this.config.silent) { - console.error('Passed element not found'); - } - return false; - } - - this.isTextElement = this.passedElement.type === 'text'; - this.isSelectOneElement = this.passedElement.type === 'select-one'; - this.isSelectMultipleElement = this.passedElement.type === 'select-multiple'; - this.isSelectElement = this.isSelectOneElement || this.isSelectMultipleElement; - this.isValidElementType = this.isTextElement || this.isSelectElement; - this.isIe11 = !!(navigator.userAgent.match(/Trident/) && navigator.userAgent.match(/rv[ :]11/)); - this.isScrollingOnIe = false; - - if (this.config.shouldSortItems === true && this.isSelectOneElement) { - if (!this.config.silent) { - console.warn('shouldSortElements: Type of passed element is \'select-one\', falling back to false.'); - } - } - - this.highlightPosition = 0; - this.canSearch = this.config.searchEnabled; - - this.placeholder = false; - if (!this.isSelectOneElement) { - this.placeholder = this.config.placeholder ? this.config.placeholderValue || this.passedElement.getAttribute('placeholder') : false; - } - - // Assign preset choices from passed object - this.presetChoices = this.config.choices; - - // Assign preset items from passed object first - this.presetItems = this.config.items; - - // Then add any values passed from attribute - if (this.passedElement.value) { - this.presetItems = this.presetItems.concat(this.passedElement.value.split(this.config.delimiter)); - } - - // Set unique base Id - this.baseId = (0, _utils.generateId)(this.passedElement, 'choices-'); - - // Bind methods - this.render = this.render.bind(this); - - // Bind event handlers - this._onFocus = this._onFocus.bind(this); - this._onBlur = this._onBlur.bind(this); - this._onKeyUp = this._onKeyUp.bind(this); - this._onKeyDown = this._onKeyDown.bind(this); - this._onClick = this._onClick.bind(this); - this._onTouchMove = this._onTouchMove.bind(this); - this._onTouchEnd = this._onTouchEnd.bind(this); - this._onMouseDown = this._onMouseDown.bind(this); - this._onMouseOver = this._onMouseOver.bind(this); - - // Monitor touch taps/scrolls - this.wasTap = true; - - // Cutting the mustard - var cuttingTheMustard = 'classList' in document.documentElement; - if (!cuttingTheMustard && !this.config.silent) { - console.error('Choices: Your browser doesn\'t support Choices'); - } - - var canInit = (0, _utils.isElement)(this.passedElement) && this.isValidElementType; - - if (canInit) { - // If element has already been initialised with Choices - if (this.passedElement.getAttribute('data-choice') === 'active') { - return false; - } - - // Let's go - this.init(); - } else if (!this.config.silent) { - console.error('Incompatible input passed'); - } - } - - /* ======================================== - = Public functions = - ======================================== */ - - /** - * Initialise Choices - * @return - * @public - */ - - - _createClass(Choices, [{ - key: 'init', - value: function init() { - if (this.initialised) { - return; - } - - // Set initialise flag - this.initialised = true; - // Create required elements - this._createTemplates(); - // Generate input markup - this._createInput(); - // Subscribe store to render method - this.store.subscribe(this.render); - // Render any items - this.render(); - // Trigger event listeners - this._addEventListeners(); - - var callback = this.config.callbackOnInit; - // Run callback if it is a function - if (callback && (0, _utils.isType)('Function', callback)) { - callback.call(this); - } - } - - /** - * Destroy Choices and nullify values - * @return - * @public - */ - - }, { - key: 'destroy', - value: function destroy() { - if (!this.initialised) { - return; - } - - // Remove all event listeners - this._removeEventListeners(); - - // Reinstate passed element - this.passedElement.classList.remove(this.config.classNames.input, this.config.classNames.hiddenState); - this.passedElement.removeAttribute('tabindex'); - - // Recover original styles if any - var origStyle = this.passedElement.getAttribute('data-choice-orig-style'); - if (origStyle) { - this.passedElement.removeAttribute('data-choice-orig-style'); - this.passedElement.setAttribute('style', origStyle); - } else { - this.passedElement.removeAttribute('style'); - } - this.passedElement.removeAttribute('aria-hidden'); - this.passedElement.removeAttribute('data-choice'); - - // Re-assign values - this is weird, I know - this.passedElement.value = this.passedElement.value; - - // Move passed element back to original position - this.containerOuter.element.parentNode.insertBefore(this.passedElement, this.containerOuter.element); - - // Remove added elements - this.containerOuter.element.parentNode.removeChild(this.containerOuter.element); - - // Clear data store - this.clearStore(); - - // Nullify instance-specific data - this.config.templates = null; - - // Uninitialise - this.initialised = false; - } - - /** - * Render group choices into a DOM fragment and append to choice list - * @param {Array} groups Groups to add to list - * @param {Array} choices Choices to add to groups - * @param {DocumentFragment} fragment Fragment to add groups and options to (optional) - * @return {DocumentFragment} Populated options fragment - * @private - */ - - }, { - key: 'renderGroups', - value: function renderGroups(groups, choices, fragment) { - var _this = this; - - var groupFragment = fragment || document.createDocumentFragment(); - var filter = this.config.sortFilter; - - // If sorting is enabled, filter groups - if (this.config.shouldSort) { - groups.sort(filter); - } - - groups.forEach(function (group) { - // Grab options that are children of this group - var groupChoices = choices.filter(function (choice) { - if (_this.isSelectOneElement) { - return choice.groupId === group.id; - } - return choice.groupId === group.id && (_this.config.renderSelectedChoices === 'always' || !choice.selected); - }); - - if (groupChoices.length >= 1) { - var dropdownGroup = _this._getTemplate('choiceGroup', group); - groupFragment.appendChild(dropdownGroup); - _this.renderChoices(groupChoices, groupFragment, true); - } - }); - - return groupFragment; - } - - /** - * Render choices into a DOM fragment and append to choice list - * @param {Array} choices Choices to add to list - * @param {DocumentFragment} fragment Fragment to add choices to (optional) - * @return {DocumentFragment} Populated choices fragment - * @private - */ - - }, { - key: 'renderChoices', - value: function renderChoices(choices, fragment) { - var _this2 = this; - - var withinGroup = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; - - // Create a fragment to store our list items (so we don't have to update the DOM for each item) - var choicesFragment = fragment || document.createDocumentFragment(); - var _config = this.config, - renderSelectedChoices = _config.renderSelectedChoices, - searchResultLimit = _config.searchResultLimit, - renderChoiceLimit = _config.renderChoiceLimit; - - var filter = this.isSearching ? _utils.sortByScore : this.config.sortFilter; - var appendChoice = function appendChoice(choice) { - var shouldRender = renderSelectedChoices === 'auto' ? _this2.isSelectOneElement || !choice.selected : true; - if (shouldRender) { - var dropdownItem = _this2._getTemplate('choice', choice); - choicesFragment.appendChild(dropdownItem); - } - }; - - var rendererableChoices = choices; - - if (renderSelectedChoices === 'auto' && !this.isSelectOneElement) { - rendererableChoices = choices.filter(function (choice) { - return !choice.selected; - }); - } - - // Split array into placeholders and "normal" choices - - var _rendererableChoices$ = rendererableChoices.reduce(function (acc, choice) { - if (choice.placeholder) { - acc.placeholderChoices.push(choice); - } else { - acc.normalChoices.push(choice); - } - return acc; - }, { placeholderChoices: [], normalChoices: [] }), - placeholderChoices = _rendererableChoices$.placeholderChoices, - normalChoices = _rendererableChoices$.normalChoices; - - // If sorting is enabled or the user is searching, filter choices - - - if (this.config.shouldSort || this.isSearching) { - normalChoices.sort(filter); - } - - var choiceLimit = rendererableChoices.length; - - // Prepend placeholeder - var sortedChoices = [].concat(_toConsumableArray(placeholderChoices), _toConsumableArray(normalChoices)); - - if (this.isSearching) { - choiceLimit = searchResultLimit; - } else if (renderChoiceLimit > 0 && !withinGroup) { - choiceLimit = renderChoiceLimit; - } - - // Add each choice to dropdown within range - for (var i = 0; i < choiceLimit; i += 1) { - if (sortedChoices[i]) { - appendChoice(sortedChoices[i]); - } - } - - return choicesFragment; - } - - /** - * Render items into a DOM fragment and append to items list - * @param {Array} items Items to add to list - * @param {DocumentFragment} [fragment] Fragment to add items to (optional) - * @return - * @private - */ - - }, { - key: 'renderItems', - value: function renderItems(items) { - var _this3 = this; - - var fragment = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; - - // Create fragment to add elements to - var itemListFragment = fragment || document.createDocumentFragment(); - - // If sorting is enabled, filter items - if (this.config.shouldSortItems && !this.isSelectOneElement) { - items.sort(this.config.sortFilter); - } - - if (this.isTextElement) { - // Simplify store data to just values - var itemsFiltered = this.store.getItemsReducedToValues(items); - var itemsFilteredString = itemsFiltered.join(this.config.delimiter); - // Update the value of the hidden input - this.passedElement.setAttribute('value', itemsFilteredString); - this.passedElement.value = itemsFilteredString; - } else { - var selectedOptionsFragment = document.createDocumentFragment(); - - // Add each list item to list - items.forEach(function (item) { - // Create a standard select option - var option = _this3._getTemplate('option', item); - // Append it to fragment - selectedOptionsFragment.appendChild(option); - }); - - // Update selected choices - this.passedElement.innerHTML = ''; - this.passedElement.appendChild(selectedOptionsFragment); - } - - // Add each list item to list - items.forEach(function (item) { - // Create new list element - var listItem = _this3._getTemplate('item', item); - // Append it to list - itemListFragment.appendChild(listItem); - }); - - return itemListFragment; - } - - /** - * Render DOM with values - * @return - * @private - */ - - }, { - key: 'render', - value: function render() { - this.currentState = this.store.getState(); - - // Only render if our state has actually changed - if (this.currentState !== this.prevState) { - // Choices - if ((this.currentState.choices !== this.prevState.choices || this.currentState.groups !== this.prevState.groups || this.currentState.items !== this.prevState.items) && this.isSelectElement) { - // Get active groups/choices - var activeGroups = this.store.getGroupsFilteredByActive(); - var activeChoices = this.store.getChoicesFilteredByActive(); - - var choiceListFragment = document.createDocumentFragment(); - - // Clear choices - this.choiceList.clear(); - - // Scroll back to top of choices list - if (this.config.resetScrollPosition) { - this.choiceList.scrollTo(0); - } - - // If we have grouped options - if (activeGroups.length >= 1 && this.isSearching !== true) { - // If we have a placeholder choice along with groups - var activePlaceholders = activeChoices.filter(function (activeChoice) { - return activeChoice.placeholder === true && activeChoice.groupId === -1; - }); - if (activePlaceholders.length >= 1) { - choiceListFragment = this.renderChoices(activePlaceholders, choiceListFragment); - } - choiceListFragment = this.renderGroups(activeGroups, activeChoices, choiceListFragment); - } else if (activeChoices.length >= 1) { - choiceListFragment = this.renderChoices(activeChoices, choiceListFragment); - } - - var activeItems = this.store.getItemsFilteredByActive(); - var canAddItem = this._canAddItem(activeItems, this.input.getValue()); - - // If we have choices to show - if (choiceListFragment.childNodes && choiceListFragment.childNodes.length > 0) { - // ...and we can select them - if (canAddItem.response) { - // ...append them and highlight the first choice - this.choiceList.append(choiceListFragment); - this._highlightChoice(); - } else { - // ...otherwise show a notice - this.choiceList.append(this._getTemplate('notice', canAddItem.notice)); - } - } else { - // Otherwise show a notice - var dropdownItem = void 0; - var notice = void 0; - - if (this.isSearching) { - notice = (0, _utils.isType)('Function', this.config.noResultsText) ? this.config.noResultsText() : this.config.noResultsText; - - dropdownItem = this._getTemplate('notice', notice, 'no-results'); - } else { - notice = (0, _utils.isType)('Function', this.config.noChoicesText) ? this.config.noChoicesText() : this.config.noChoicesText; - - dropdownItem = this._getTemplate('notice', notice, 'no-choices'); - } - - this.choiceList.append(dropdownItem); - } - } - - // Items - if (this.currentState.items !== this.prevState.items) { - // Get active items (items that can be selected) - var _activeItems = this.store.getItemsFilteredByActive(); - - // Clear list - this.itemList.clear(); - - if (_activeItems && _activeItems.length) { - // Create a fragment to store our list items - // (so we don't have to update the DOM for each item) - var itemListFragment = this.renderItems(_activeItems); - - // If we have items to add - if (itemListFragment.childNodes) { - // Update list - this.itemList.append(itemListFragment); - } - } - } - - this.prevState = this.currentState; - } - } - - /** - * Select item (a selected item can be deleted) - * @param {Element} item Element to select - * @param {Boolean} [runEvent=true] Whether to trigger 'highlightItem' event - * @return {Object} Class instance - * @public - */ - - }, { - key: 'highlightItem', - value: function highlightItem(item) { - var runEvent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; - - if (!item) { - return this; - } - - var id = item.id; - var groupId = item.groupId; - var group = groupId >= 0 ? this.store.getGroupById(groupId) : null; - - this.store.dispatch((0, _actions.highlightItem)(id, true)); - - if (runEvent) { - var eventResponse = { - id: id, - value: item.value, - label: item.label - }; - - if (group && group.value) { - eventResponse.groupValue = group.value; - } - - (0, _utils.triggerEvent)(this.passedElement, 'highlightItem', eventResponse); - } - - return this; - } - - /** - * Deselect item - * @param {Element} item Element to de-select - * @return {Object} Class instance - * @public - */ - - }, { - key: 'unhighlightItem', - value: function unhighlightItem(item) { - if (!item) { - return this; - } - - var id = item.id; - var groupId = item.groupId; - var group = groupId >= 0 ? this.store.getGroupById(groupId) : null; - var eventResponse = { - id: id, - value: item.value, - label: item.label - }; - - if (group && group.value) { - eventResponse.groupValue = group.value; - } - - this.store.dispatch((0, _actions.highlightItem)(id, false)); - - (0, _utils.triggerEvent)(this.passedElement, 'highlightItem', eventResponse); - - return this; - } - - /** - * Highlight items within store - * @return {Object} Class instance - * @public - */ - - }, { - key: 'highlightAll', - value: function highlightAll() { - var _this4 = this; - - var items = this.store.getItems(); - items.forEach(function (item) { - return _this4.highlightItem(item); - }); - return this; - } - - /** - * Deselect items within store - * @return {Object} Class instance - * @public - */ - - }, { - key: 'unhighlightAll', - value: function unhighlightAll() { - var _this5 = this; - - var items = this.store.getItems(); - items.forEach(function (item) { - return _this5.unhighlightItem(item); - }); - return this; - } - - /** - * Remove an item from the store by its value - * @param {String} value Value to search for - * @return {Object} Class instance - * @public - */ - - }, { - key: 'removeItemsByValue', - value: function removeItemsByValue(value) { - var _this6 = this; - - if (!value || !(0, _utils.isType)('String', value)) { - return this; - } - - var items = this.store.getItemsFilteredByActive(); - - items.forEach(function (item) { - if (item.value === value) { - _this6._removeItem(item); - } - }); - - return this; - } - - /** - * Remove all items from store array - * @note Removed items are soft deleted - * @param {Number} excludedId Optionally exclude item by ID - * @return {Object} Class instance - * @public - */ - - }, { - key: 'removeActiveItems', - value: function removeActiveItems(excludedId) { - var _this7 = this; - - var items = this.store.getItemsFilteredByActive(); - - items.forEach(function (item) { - if (item.active && excludedId !== item.id) { - _this7._removeItem(item); - } - }); - - return this; - } - - /** - * Remove all selected items from store - * @note Removed items are soft deleted - * @return {Object} Class instance - * @public - */ - - }, { - key: 'removeHighlightedItems', - value: function removeHighlightedItems() { - var _this8 = this; - - var runEvent = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; - - var items = this.store.getItemsFilteredByActive(); - - items.forEach(function (item) { - if (item.highlighted && item.active) { - _this8._removeItem(item); - // If this action was performed by the user - // trigger the event - if (runEvent) { - _this8._triggerChange(item.value); - } - } - }); - - return this; - } - - /** - * Show dropdown to user by adding active state class - * @return {Object} Class instance - * @public - */ - - }, { - key: 'showDropdown', - value: function showDropdown() { - var focusInput = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; - - if (this.dropdown.isActive) { - return this; - } - - this.containerOuter.open(this.dropdown.getVerticalPos()); - this.dropdown.show(); - this.input.activate(focusInput); - - (0, _utils.triggerEvent)(this.passedElement, 'showDropdown', {}); - return this; - } - - /** - * Hide dropdown from user - * @return {Object} Class instance - * @public - */ - - }, { - key: 'hideDropdown', - value: function hideDropdown() { - var blurInput = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; - - if (!this.dropdown.isActive) { - return this; - } - - this.containerOuter.close(); - this.dropdown.hide(); - this.input.deactivate(blurInput); - - (0, _utils.triggerEvent)(this.passedElement, 'hideDropdown', {}); - return this; - } - - /** - * Determine whether to hide or show dropdown based on its current state - * @return {Object} Class instance - * @public - */ - - }, { - key: 'toggleDropdown', - value: function toggleDropdown() { - if (this.dropdown.isActive) { - this.hideDropdown(); - } else { - this.showDropdown(true); - } - - return this; - } - - /** - * Get value(s) of input (i.e. inputted items (text) or selected choices (select)) - * @param {Boolean} valueOnly Get only values of selected items, otherwise return selected items - * @return {Array/String} selected value (select-one) or - * array of selected items (inputs & select-multiple) - * @public - */ - - }, { - key: 'getValue', - value: function getValue() { - var _this9 = this; - - var valueOnly = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; - - var items = this.store.getItemsFilteredByActive(); - var selectedItems = []; - - items.forEach(function (item) { - var itemValue = valueOnly ? item.value : item; - if (_this9.isTextElement || item.active) { - selectedItems.push(itemValue); - } - }); - - return this.isSelectOneElement ? selectedItems[0] : selectedItems; - } - - /** - * Set value of input. If the input is a select box, a choice will - * be created and selected otherwise an item will created directly. - * @param {Array} args Array of value objects or value strings - * @return {Object} Class instance - * @public - */ - - }, { - key: 'setValue', - value: function setValue(args) { - var _this10 = this; - - if (!this.initialised) { - return this; - } - - // Convert args to an iterable array - var values = [].concat(_toConsumableArray(args)); - var handleValue = function handleValue(item) { - var itemType = (0, _utils.getType)(item).toLowerCase(); - var handleType = { - object: function object() { - if (!item.value) { - return; - } - - // If we are dealing with a select input, we need to create an option first - // that is then selected. For text inputs we can just add items normally. - if (!_this10.isTextElement) { - _this10._addChoice(item.value, item.label, true, false, -1, item.customProperties, item.placeholder); - } else { - _this10._addItem(item.value, item.label, item.id, undefined, item.customProperties, item.placeholder); - } - }, - string: function string() { - if (!_this10.isTextElement) { - _this10._addChoice(item, item, true, false, -1, null); - } else { - _this10._addItem(item); - } - } - }; - - handleType[itemType](); - }; - - values.forEach(function (value) { - return handleValue(value); - }); - - return this; - } - - /** - * Select value of select box via the value of an existing choice - * @param {Array/String} value An array of strings of a single string - * @return {Object} Class instance - * @public - */ - - }, { - key: 'setValueByChoice', - value: function setValueByChoice(value) { - var _this11 = this; - - if (this.isTextElement) { - return this; - } - - var choices = this.store.getChoices(); - // If only one value has been passed, convert to array - var choiceValue = (0, _utils.isType)('Array', value) ? value : [value]; - - // Loop through each value and - choiceValue.forEach(function (val) { - // Check 'value' property exists and the choice isn't already selected - var foundChoice = choices.find(function (choice) { - return choice.value === val; - }); - - if (foundChoice) { - if (!foundChoice.selected) { - _this11._addItem(foundChoice.value, foundChoice.label, foundChoice.id, foundChoice.groupId, foundChoice.customProperties, foundChoice.placeholder, foundChoice.keyCode); - } else if (!_this11.config.silent) { - console.warn('Attempting to select choice already selected'); - } - } else if (!_this11.config.silent) { - console.warn('Attempting to select choice that does not exist'); - } - }); - - return this; - } - - /** - * Direct populate choices - * @param {Array} choices - Choices to insert - * @param {String} value - Name of 'value' property - * @param {String} label - Name of 'label' property - * @param {Boolean} replaceChoices Whether existing choices should be removed - * @return {Object} Class instance - * @public - */ - - }, { - key: 'setChoices', - value: function setChoices(choices, value, label) { - var _this12 = this; - - var replaceChoices = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; - - if (!this.initialised || !this.isSelectElement || !(0, _utils.isType)('Array', choices) || !value) { - return this; - } - - // Clear choices if needed - if (replaceChoices) { - this._clearChoices(); - } - - // Add choices if passed - if (choices && choices.length) { - this.containerOuter.removeLoadingState(); - - choices.forEach(function (result) { - if (result.choices) { - _this12._addGroup(result, result.id || null, value, label); - } else { - _this12._addChoice(result[value], result[label], result.selected, result.disabled, undefined, result.customProperties, result.placeholder); - } - }); - } - - return this; - } - - /** - * Clear items,choices and groups - * @note Hard delete - * @return {Object} Class instance - * @public - */ - - }, { - key: 'clearStore', - value: function clearStore() { - this.store.dispatch((0, _actions.clearAll)()); - return this; - } - - /** - * Set value of input to blank - * @return {Object} Class instance - * @public - */ - - }, { - key: 'clearInput', - value: function clearInput() { - var shouldSetInputWidth = !this.isSelectOneElement; - this.input.clear(shouldSetInputWidth); - - if (!this.isTextElement && this.config.searchEnabled) { - this.isSearching = false; - this.store.dispatch((0, _actions.activateChoices)(true)); - } - - return this; - } - - /** - * Enable interaction with Choices - * @return {Object} Class instance - */ - - }, { - key: 'enable', - value: function enable() { - if (!this.initialised) { - return this; - } - - this.passedElement.disabled = false; - - if (this.containerOuter.isDisabled) { - this._addEventListeners(); - this.passedElement.removeAttribute('disabled'); - this.input.enable(); - this.containerOuter.enable(); - } - - return this; - } - - /** - * Disable interaction with Choices - * @return {Object} Class instance - * @public - */ - - }, { - key: 'disable', - value: function disable() { - if (!this.initialised) { - return this; - } - - this.passedElement.disabled = true; - - if (!this.containerOuter.isDisabled) { - this._removeEventListeners(); - this.passedElement.setAttribute('disabled', ''); - this.input.disable(); - this.containerOuter.disable(); - } - - return this; - } - - /** - * Populate options via ajax callback - * @param {Function} fn Function that actually makes an AJAX request - * @return {Object} Class instance - * @public - */ - - }, { - key: 'ajax', - value: function ajax(fn) { - var _this13 = this; - - if (!this.initialised || !this.isSelectElement) { - return this; - } - - // Show loading text - requestAnimationFrame(function () { - return _this13._handleLoadingState(true); - }); - // Run callback - fn(this._ajaxCallback()); - - return this; - } - - /* ===== End of Public functions ====== */ - - /* ============================================= - = Private functions = - ============================================= */ - - /** - * Call change callback - * @param {String} value - last added/deleted/selected value - * @return - * @private - */ - - }, { - key: '_triggerChange', - value: function _triggerChange(value) { - if (!value) { - return; - } - - (0, _utils.triggerEvent)(this.passedElement, 'change', { - value: value - }); - } - - /** - * Process enter/click of an item button - * @param {Array} activeItems The currently active items - * @param {Element} element Button being interacted with - * @return - * @private - */ - - }, { - key: '_handleButtonAction', - value: function _handleButtonAction(activeItems, element) { - if (!activeItems || !element || !this.config.removeItems || !this.config.removeItemButton) { - return; - } - - var itemId = element.parentNode.getAttribute('data-id'); - var itemToRemove = activeItems.find(function (item) { - return item.id === parseInt(itemId, 10); - }); - - // Remove item associated with button - this._removeItem(itemToRemove); - this._triggerChange(itemToRemove.value); - - if (this.isSelectOneElement) { - this._selectPlaceholderChoice(); - } - } - - /** - * Select placeholder choice - */ - - }, { - key: '_selectPlaceholderChoice', - value: function _selectPlaceholderChoice() { - var placeholderChoice = this.store.getPlaceholderChoice(); - - if (placeholderChoice) { - this._addItem(placeholderChoice.value, placeholderChoice.label, placeholderChoice.id, placeholderChoice.groupId, null, placeholderChoice.placeholder); - this._triggerChange(placeholderChoice.value); - } - } - - /** - * Process click of an item - * @param {Array} activeItems The currently active items - * @param {Element} element Item being interacted with - * @param {Boolean} hasShiftKey Whether the user has the shift key active - * @return - * @private - */ - - }, { - key: '_handleItemAction', - value: function _handleItemAction(activeItems, element) { - var _this14 = this; - - var hasShiftKey = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; - - if (!activeItems || !element || !this.config.removeItems || this.isSelectOneElement) { - return; - } - - var passedId = element.getAttribute('data-id'); - - // We only want to select one item with a click - // so we deselect any items that aren't the target - // unless shift is being pressed - activeItems.forEach(function (item) { - if (item.id === parseInt(passedId, 10) && !item.highlighted) { - _this14.highlightItem(item); - } else if (!hasShiftKey && item.highlighted) { - _this14.unhighlightItem(item); - } - }); - - // Focus input as without focus, a user cannot do anything with a - // highlighted item - this.input.focus(); - } - - /** - * Process click of a choice - * @param {Array} activeItems The currently active items - * @param {Element} element Choice being interacted with - * @return - */ - - }, { - key: '_handleChoiceAction', - value: function _handleChoiceAction(activeItems, element) { - if (!activeItems || !element) { - return; - } - - // If we are clicking on an option - var id = element.getAttribute('data-id'); - var choice = this.store.getChoiceById(id); - var passedKeyCode = activeItems[0] && activeItems[0].keyCode ? activeItems[0].keyCode : null; - var hasActiveDropdown = this.dropdown.isActive; - - // Update choice keyCode - choice.keyCode = passedKeyCode; - - (0, _utils.triggerEvent)(this.passedElement, 'choice', { - choice: choice - }); - - if (choice && !choice.selected && !choice.disabled) { - var canAddItem = this._canAddItem(activeItems, choice.value); - - if (canAddItem.response) { - this._addItem(choice.value, choice.label, choice.id, choice.groupId, choice.customProperties, choice.placeholder, choice.keyCode); - this._triggerChange(choice.value); - } - } - - this.clearInput(); - - // We wont to close the dropdown if we are dealing with a single select box - if (hasActiveDropdown && this.isSelectOneElement) { - this.hideDropdown(); - this.containerOuter.focus(); - } - } - - /** - * Process back space event - * @param {Array} activeItems items - * @return - * @private - */ - - }, { - key: '_handleBackspace', - value: function _handleBackspace(activeItems) { - if (!this.config.removeItems || !activeItems) { - return; - } - - var lastItem = activeItems[activeItems.length - 1]; - var hasHighlightedItems = activeItems.some(function (item) { - return item.highlighted; - }); - - // If editing the last item is allowed and there are not other selected items, - // we can edit the item value. Otherwise if we can remove items, remove all selected items - if (this.config.editItems && !hasHighlightedItems && lastItem) { - this.input.setValue(lastItem.value); - this.input.setWidth(); - this._removeItem(lastItem); - this._triggerChange(lastItem.value); - } else { - if (!hasHighlightedItems) { - this.highlightItem(lastItem, false); - } - this.removeHighlightedItems(true); - } - } - - /** - * Validates whether an item can be added by a user - * @param {Array} activeItems The currently active items - * @param {String} value Value of item to add - * @return {Object} Response: Whether user can add item - * Notice: Notice show in dropdown - */ - - }, { - key: '_canAddItem', - value: function _canAddItem(activeItems, value) { - var canAddItem = true; - var notice = (0, _utils.isType)('Function', this.config.addItemText) ? this.config.addItemText(value) : this.config.addItemText; - - if (this.isSelectMultipleElement || this.isTextElement) { - if (this.config.maxItemCount > 0 && this.config.maxItemCount <= activeItems.length) { - // If there is a max entry limit and we have reached that limit - // don't update - canAddItem = false; - notice = (0, _utils.isType)('Function', this.config.maxItemText) ? this.config.maxItemText(this.config.maxItemCount) : this.config.maxItemText; - } - } - - if (this.isTextElement && this.config.addItems && canAddItem && this.config.regexFilter) { - // If a user has supplied a regular expression filter - // determine whether we can update based on whether - // our regular expression passes - canAddItem = (0, _utils.regexFilter)(value, this.config.regexFilter); - } - - // If no duplicates are allowed, and the value already exists - // in the array - var isUnique = !activeItems.some(function (item) { - if ((0, _utils.isType)('String', value)) { - return item.value === value.trim(); - } - - return item.value === value; - }); - - if (!isUnique && !this.config.duplicateItems && !this.isSelectOneElement && canAddItem) { - canAddItem = false; - notice = (0, _utils.isType)('Function', this.config.uniqueItemText) ? this.config.uniqueItemText(value) : this.config.uniqueItemText; - } - - return { - response: canAddItem, - notice: notice - }; - } - - /** - * Apply or remove a loading state to the component. - * @param {Boolean} isLoading default value set to 'true'. - * @return - * @private - */ - - }, { - key: '_handleLoadingState', - value: function _handleLoadingState() { - var isLoading = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; - - var placeholderItem = this.itemList.getChild('.' + this.config.classNames.placeholder); - if (isLoading) { - this.containerOuter.addLoadingState(); - if (this.isSelectOneElement) { - if (!placeholderItem) { - placeholderItem = this._getTemplate('placeholder', this.config.loadingText); - this.itemList.append(placeholderItem); - } else { - placeholderItem.innerHTML = this.config.loadingText; - } - } else { - this.input.setPlaceholder(this.config.loadingText); - } - } else { - this.containerOuter.removeLoadingState(); - - if (this.isSelectOneElement) { - placeholderItem.innerHTML = this.placeholder || ''; - } else { - this.input.setPlaceholder(this.placeholder || ''); - } - } - } - - /** - * Retrieve the callback used to populate component's choices in an async way. - * @returns {Function} The callback as a function. - * @private - */ - - }, { - key: '_ajaxCallback', - value: function _ajaxCallback() { - var _this15 = this; - - return function (results, value, label) { - if (!results || !value) { - return; - } - - var parsedResults = (0, _utils.isType)('Object', results) ? [results] : results; - - if (parsedResults && (0, _utils.isType)('Array', parsedResults) && parsedResults.length) { - // Remove loading states/text - _this15._handleLoadingState(false); - // Add each result as a choice - parsedResults.forEach(function (result) { - if (result.choices) { - var groupId = result.id || null; - _this15._addGroup(result, groupId, value, label); - } else { - _this15._addChoice(result[value], result[label], result.selected, result.disabled, undefined, result.customProperties, result.placeholder); - } - }); - - if (_this15.isSelectOneElement) { - _this15._selectPlaceholderChoice(); - } - } else { - // No results, remove loading state - _this15._handleLoadingState(false); - } - }; - } - - /** - * Filter choices based on search value - * @param {String} value Value to filter by - * @return - * @private - */ - - }, { - key: '_searchChoices', - value: function _searchChoices(value) { - var newValue = (0, _utils.isType)('String', value) ? value.trim() : value; - var currentValue = (0, _utils.isType)('String', this.currentValue) ? this.currentValue.trim() : this.currentValue; - - // If new value matches the desired length and is not the same as the current value with a space - if (newValue.length >= 1 && newValue !== currentValue + ' ') { - var haystack = this.store.getSearchableChoices(); - var needle = newValue; - var keys = (0, _utils.isType)('Array', this.config.searchFields) ? this.config.searchFields : [this.config.searchFields]; - var options = Object.assign(this.config.fuseOptions, { keys: keys }); - var fuse = new _fuse2.default(haystack, options); - var results = fuse.search(needle); - - this.currentValue = newValue; - this.highlightPosition = 0; - this.isSearching = true; - this.store.dispatch((0, _actions.filterChoices)(results)); - - return results.length; - } - - return 0; - } - - /** - * Determine the action when a user is searching - * @param {String} value Value entered by user - * @return - * @private - */ - - }, { - key: '_handleSearch', - value: function _handleSearch(value) { - if (!value || !this.input.isFocussed) { - return; - } - - var choices = this.store.getChoices(); - var hasUnactiveChoices = choices.some(function (option) { - return !option.active; - }); - - // Check that we have a value to search and the input was an alphanumeric character - if (value && value.length >= this.config.searchFloor) { - var resultCount = this.config.searchChoices ? this._searchChoices(value) : 0; - // Trigger search event - (0, _utils.triggerEvent)(this.passedElement, 'search', { - value: value, - resultCount: resultCount - }); - } else if (hasUnactiveChoices) { - // Otherwise reset choices to active - this.isSearching = false; - this.store.dispatch((0, _actions.activateChoices)(true)); - } - } - - /** - * Trigger event listeners - * @return - * @private - */ - - }, { - key: '_addEventListeners', - value: function _addEventListeners() { - document.addEventListener('keyup', this._onKeyUp); - document.addEventListener('keydown', this._onKeyDown); - document.addEventListener('click', this._onClick); - document.addEventListener('touchmove', this._onTouchMove); - document.addEventListener('touchend', this._onTouchEnd); - document.addEventListener('mousedown', this._onMouseDown); - document.addEventListener('mouseover', this._onMouseOver); - - if (this.isSelectOneElement) { - this.containerOuter.element.addEventListener('focus', this._onFocus); - this.containerOuter.element.addEventListener('blur', this._onBlur); - } - - this.input.element.addEventListener('focus', this._onFocus); - this.input.element.addEventListener('blur', this._onBlur); - - this.input.addEventListeners(); - } - - /** - * Remove event listeners - * @return - * @private - */ - - }, { - key: '_removeEventListeners', - value: function _removeEventListeners() { - document.removeEventListener('keyup', this._onKeyUp); - document.removeEventListener('keydown', this._onKeyDown); - document.removeEventListener('click', this._onClick); - document.removeEventListener('touchmove', this._onTouchMove); - document.removeEventListener('touchend', this._onTouchEnd); - document.removeEventListener('mousedown', this._onMouseDown); - document.removeEventListener('mouseover', this._onMouseOver); - - if (this.isSelectOneElement) { - this.containerOuter.element.removeEventListener('focus', this._onFocus); - this.containerOuter.element.removeEventListener('blur', this._onBlur); - } - - this.input.element.removeEventListener('focus', this._onFocus); - this.input.element.removeEventListener('blur', this._onBlur); - - this.input.removeEventListeners(); - } - - /** - * Key down event - * @param {Object} e Event - * @return - */ - - }, { - key: '_onKeyDown', - value: function _onKeyDown(e) { - var _this16 = this, - _keyDownActions; - - if (e.target !== this.input.element && !this.containerOuter.element.contains(e.target)) { - return; - } - - var target = e.target; - var activeItems = this.store.getItemsFilteredByActive(); - var hasFocusedInput = this.input.isFocussed; - var hasActiveDropdown = this.dropdown.isActive; - var hasItems = this.itemList.hasChildren; - var keyString = String.fromCharCode(e.keyCode); - - // TO DO: Move into constants file - var backKey = 46; - var deleteKey = 8; - var enterKey = 13; - var aKey = 65; - var escapeKey = 27; - var upKey = 38; - var downKey = 40; - var pageUpKey = 33; - var pageDownKey = 34; - var ctrlDownKey = e.ctrlKey || e.metaKey; - - // If a user is typing and the dropdown is not active - if (!this.isTextElement && /[a-zA-Z0-9-_ ]/.test(keyString)) { - this.showDropdown(true); - } - - this.canSearch = this.config.searchEnabled; - - var onAKey = function onAKey() { - // If CTRL + A or CMD + A have been pressed and there are items to select - if (ctrlDownKey && hasItems) { - _this16.canSearch = false; - if (_this16.config.removeItems && !_this16.input.element.value && _this16.input.element === document.activeElement) { - // Highlight items - _this16.highlightAll(); - } - } - }; - - var onEnterKey = function onEnterKey() { - // If enter key is pressed and the input has a value - if (_this16.isTextElement && target.value) { - var value = _this16.input.element.value; - var canAddItem = _this16._canAddItem(activeItems, value); - - // All is good, add - if (canAddItem.response) { - _this16.hideDropdown(); - _this16._addItem(value); - _this16._triggerChange(value); - _this16.clearInput(); - } - } - - if (target.hasAttribute('data-button')) { - _this16._handleButtonAction(activeItems, target); - e.preventDefault(); - } - - if (hasActiveDropdown) { - e.preventDefault(); - var highlighted = _this16.dropdown.getChild('.' + _this16.config.classNames.highlightedState); - - // If we have a highlighted choice - if (highlighted) { - // add enter keyCode value - if (activeItems[0]) { - activeItems[0].keyCode = enterKey; - } - _this16._handleChoiceAction(activeItems, highlighted); - } - } else if (_this16.isSelectOneElement) { - // Open single select dropdown if it's not active - _this16.showDropdown(true); - e.preventDefault(); - } - }; - - var onEscapeKey = function onEscapeKey() { - if (hasActiveDropdown) { - _this16.hideDropdown(); - _this16.containerOuter.focus(); - } - }; - - var onDirectionKey = function onDirectionKey() { - // If up or down key is pressed, traverse through options - if (hasActiveDropdown || _this16.isSelectOneElement) { - // Show dropdown if focus - _this16.showDropdown(true); - - _this16.canSearch = false; - - var directionInt = e.keyCode === downKey || e.keyCode === pageDownKey ? 1 : -1; - var skipKey = e.metaKey || e.keyCode === pageDownKey || e.keyCode === pageUpKey; - - var nextEl = void 0; - if (skipKey) { - if (directionInt > 0) { - nextEl = Array.from(_this16.dropdown.element.querySelectorAll('[data-choice-selectable]')).pop(); - } else { - nextEl = _this16.dropdown.element.querySelector('[data-choice-selectable]'); - } - } else { - var currentEl = _this16.dropdown.element.querySelector('.' + _this16.config.classNames.highlightedState); - if (currentEl) { - nextEl = (0, _utils.getAdjacentEl)(currentEl, '[data-choice-selectable]', directionInt); - } else { - nextEl = _this16.dropdown.element.querySelector('[data-choice-selectable]'); - } - } - - if (nextEl) { - // We prevent default to stop the cursor moving - // when pressing the arrow - if (!(0, _utils.isScrolledIntoView)(nextEl, _this16.choiceList, directionInt)) { - _this16._scrollToChoice(nextEl, directionInt); - } - _this16._highlightChoice(nextEl); - } - - // Prevent default to maintain cursor position whilst - // traversing dropdown options - e.preventDefault(); - } - }; - - var onDeleteKey = function onDeleteKey() { - // If backspace or delete key is pressed and the input has no value - if (hasFocusedInput && !e.target.value && !_this16.isSelectOneElement) { - _this16._handleBackspace(activeItems); - e.preventDefault(); - } - }; - - // Map keys to key actions - var keyDownActions = (_keyDownActions = {}, _defineProperty(_keyDownActions, aKey, onAKey), _defineProperty(_keyDownActions, enterKey, onEnterKey), _defineProperty(_keyDownActions, escapeKey, onEscapeKey), _defineProperty(_keyDownActions, upKey, onDirectionKey), _defineProperty(_keyDownActions, pageUpKey, onDirectionKey), _defineProperty(_keyDownActions, downKey, onDirectionKey), _defineProperty(_keyDownActions, pageDownKey, onDirectionKey), _defineProperty(_keyDownActions, deleteKey, onDeleteKey), _defineProperty(_keyDownActions, backKey, onDeleteKey), _keyDownActions); - - // If keycode has a function, run it - if (keyDownActions[e.keyCode]) { - keyDownActions[e.keyCode](); - } - } - - /** - * Key up event - * @param {Object} e Event - * @return - * @private - */ - - }, { - key: '_onKeyUp', - value: function _onKeyUp(e) { - if (e.target !== this.input.element) { - return; - } - - var value = this.input.element.value; - var activeItems = this.store.getItemsFilteredByActive(); - var canAddItem = this._canAddItem(activeItems, value); - - // We are typing into a text input and have a value, we want to show a dropdown - // notice. Otherwise hide the dropdown - if (this.isTextElement) { - if (value) { - if (canAddItem.notice) { - var dropdownItem = this._getTemplate('notice', canAddItem.notice); - this.dropdown.element.innerHTML = dropdownItem.outerHTML; - } - - if (canAddItem.response === true) { - this.showDropdown(); - } else if (!canAddItem.notice) { - this.hideDropdown(); - } - } else { - this.hideDropdown(); - } - } else { - var backKey = 46; - var deleteKey = 8; - - // If user has removed value... - if ((e.keyCode === backKey || e.keyCode === deleteKey) && !e.target.value) { - // ...and it is a multiple select input, activate choices (if searching) - if (!this.isTextElement && this.isSearching) { - this.isSearching = false; - this.store.dispatch((0, _actions.activateChoices)(true)); - } - } else if (this.canSearch && canAddItem.response) { - this._handleSearch(this.input.element.value); - } - } - // Re-establish canSearch value from changes in _onKeyDown - this.canSearch = this.config.searchEnabled; - } - - /** - * Touch move event - * @return - * @private - */ - - }, { - key: '_onTouchMove', - value: function _onTouchMove() { - if (this.wasTap === true) { - this.wasTap = false; - } - } - - /** - * Touch end event - * @param {Object} e Event - * @return - * @private - */ - - }, { - key: '_onTouchEnd', - value: function _onTouchEnd(e) { - var target = e.target || e.touches[0].target; - - // If a user tapped within our container... - if (this.wasTap === true && this.containerOuter.element.contains(target)) { - // ...and we aren't dealing with a single select box, show dropdown/focus input - if ((target === this.containerOuter.element || target === this.containerInner.element) && !this.isSelectOneElement) { - if (this.isTextElement) { - // If text element, we only want to focus the input - this.input.focus(); - } else { - // If a select box, we want to show the dropdown - this.showDropdown(true); - } - } - // Prevents focus event firing - e.stopPropagation(); - } - - this.wasTap = true; - } - - /** - * Mouse down event - * @param {Object} e Event - * @return - * @private - */ - - }, { - key: '_onMouseDown', - value: function _onMouseDown(e) { - var target = e.target; - - // If we have our mouse down on the scrollbar and are on IE11... - if (target === this.choiceList && this.isIe11) { - this.isScrollingOnIe = true; - } - - if (this.containerOuter.element.contains(target) && target !== this.input.element) { - var activeItems = this.store.getItemsFilteredByActive(); - var hasShiftKey = e.shiftKey; - - var buttonTarget = (0, _utils.findAncestorByAttrName)(target, 'data-button'); - var itemTarget = (0, _utils.findAncestorByAttrName)(target, 'data-item'); - var choiceTarget = (0, _utils.findAncestorByAttrName)(target, 'data-choice'); - - if (buttonTarget) { - this._handleButtonAction(activeItems, buttonTarget); - } else if (itemTarget) { - this._handleItemAction(activeItems, itemTarget, hasShiftKey); - } else if (choiceTarget) { - this._handleChoiceAction(activeItems, choiceTarget); - } - - e.preventDefault(); - } - } - - /** - * Click event - * @param {Object} e Event - * @return - * @private - */ - - }, { - key: '_onClick', - value: function _onClick(e) { - var target = e.target; - var hasActiveDropdown = this.dropdown.isActive; - var activeItems = this.store.getItemsFilteredByActive(); - - // If target is something that concerns us - if (this.containerOuter.element.contains(target)) { - if (!hasActiveDropdown) { - if (this.isTextElement) { - if (document.activeElement !== this.input.element) { - this.input.focus(); - } - } else if (this.canSearch) { - this.showDropdown(true); - } else { - this.showDropdown(); - this.containerOuter.focus(); - } - } else if (this.isSelectOneElement && target !== this.input.element && !this.dropdown.element.contains(target)) { - this.hideDropdown(true); - } - } else { - var hasHighlightedItems = activeItems.some(function (item) { - return item.highlighted; - }); - - // De-select any highlighted items - if (hasHighlightedItems) { - this.unhighlightAll(); - } - - // Remove focus state - this.containerOuter.removeFocusState(); - - // Close all other dropdowns - this.hideDropdown(); - } - } - - /** - * Mouse over (hover) event - * @param {Object} e Event - * @return - * @private - */ - - }, { - key: '_onMouseOver', - value: function _onMouseOver(e) { - // If the dropdown is either the target or one of its children is the target - if ((e.target === this.dropdown || this.dropdown.element.contains(e.target)) && e.target.hasAttribute('data-choice')) { - this._highlightChoice(e.target); - } - } - - /** - * Focus event - * @param {Object} e Event - * @return - * @private - */ - - }, { - key: '_onFocus', - value: function _onFocus(e) { - var _this17 = this; - - var target = e.target; - // If target is something that concerns us - if (this.containerOuter.element.contains(target)) { - var focusActions = { - text: function text() { - if (target === _this17.input.element) { - _this17.containerOuter.addFocusState(); - } - }, - 'select-one': function selectOne() { - _this17.containerOuter.addFocusState(); - if (target === _this17.input.element) { - // Show dropdown if it isn't already showing - _this17.showDropdown(); - } - }, - 'select-multiple': function selectMultiple() { - if (target === _this17.input.element) { - // If element is a select box, the focused element is the container and the dropdown - // isn't already open, focus and show dropdown - _this17.containerOuter.addFocusState(); - _this17.showDropdown(true); - } - } - }; - - focusActions[this.passedElement.type](); - } - } - - /** - * Blur event - * @param {Object} e Event - * @return - * @private - */ - - }, { - key: '_onBlur', - value: function _onBlur(e) { - var _this18 = this; - - var target = e.target; - // If target is something that concerns us - if (this.containerOuter.element.contains(target) && !this.isScrollingOnIe) { - var activeItems = this.store.getItemsFilteredByActive(); - var hasHighlightedItems = activeItems.some(function (item) { - return item.highlighted; - }); - var blurActions = { - text: function text() { - if (target === _this18.input.element) { - // Remove the focus state - _this18.containerOuter.removeFocusState(); - // De-select any highlighted items - if (hasHighlightedItems) { - _this18.unhighlightAll(); - } - _this18.hideDropdown(); - } - }, - 'select-one': function selectOne() { - _this18.containerOuter.removeFocusState(); - if (target === _this18.containerOuter.element) { - // Hide dropdown if it is showing - if (!_this18.canSearch) { - _this18.hideDropdown(); - } - } - if (target === _this18.input.element) { - // Hide dropdown if it is showing - _this18.hideDropdown(); - } - }, - 'select-multiple': function selectMultiple() { - if (target === _this18.input.element) { - // Remove the focus state - _this18.containerOuter.removeFocusState(); - _this18.hideDropdown(); - // De-select any highlighted items - if (hasHighlightedItems) { - _this18.unhighlightAll(); - } - } - } - }; - - blurActions[this.passedElement.type](); - } else { - // On IE11, clicking the scollbar blurs our input and thus - // closes the dropdown. To stop this, we refocus our input - // if we know we are on IE *and* are scrolling. - this.isScrollingOnIe = false; - this.input.element.focus(); - } - } - - /** - * Scroll to an option element - * @param {HTMLElement} choice Option to scroll to - * @param {Number} direction Whether option is above or below - * @return - * @private - */ - - }, { - key: '_scrollToChoice', - value: function _scrollToChoice(choice, direction) { - var _this19 = this; - - if (!choice) { - return; - } - - var dropdownHeight = this.choiceList.height; - var choiceHeight = choice.offsetHeight; - // Distance from bottom of element to top of parent - var choicePos = choice.offsetTop + choiceHeight; - // Scroll position of dropdown - var containerScrollPos = this.choiceList.scrollPos + dropdownHeight; - // Difference between the choice and scroll position - var endPoint = direction > 0 ? this.choiceList.scrollPos + choicePos - containerScrollPos : choice.offsetTop; - - var animateScroll = function animateScroll() { - var strength = 4; - var choiceListScrollTop = _this19.choiceList.scrollPos; - var continueAnimation = false; - var easing = void 0; - var distance = void 0; - - if (direction > 0) { - easing = (endPoint - choiceListScrollTop) / strength; - distance = easing > 1 ? easing : 1; - - _this19.choiceList.scrollTo(choiceListScrollTop + distance); - if (choiceListScrollTop < endPoint) { - continueAnimation = true; - } - } else { - easing = (choiceListScrollTop - endPoint) / strength; - distance = easing > 1 ? easing : 1; - - _this19.choiceList.scrollTo(choiceListScrollTop - distance); - if (choiceListScrollTop > endPoint) { - continueAnimation = true; - } - } - - if (continueAnimation) { - requestAnimationFrame(function (time) { - animateScroll(time, endPoint, direction); - }); - } - }; - - requestAnimationFrame(function (time) { - animateScroll(time, endPoint, direction); - }); - } - - /** - * Highlight choice - * @param {HTMLElement} [el] Element to highlight - * @return - * @private - */ - - }, { - key: '_highlightChoice', - value: function _highlightChoice() { - var _this20 = this; - - var el = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; - - // Highlight first element in dropdown - var choices = Array.from(this.dropdown.element.querySelectorAll('[data-choice-selectable]')); - var passedEl = el; - - if (choices && choices.length) { - var highlightedChoices = Array.from(this.dropdown.element.querySelectorAll('.' + this.config.classNames.highlightedState)); - var hasActiveDropdown = this.dropdown.isActive; - - // Remove any highlighted choices - highlightedChoices.forEach(function (choice) { - choice.classList.remove(_this20.config.classNames.highlightedState); - choice.setAttribute('aria-selected', 'false'); - }); - - if (passedEl) { - this.highlightPosition = choices.indexOf(passedEl); - } else { - // Highlight choice based on last known highlight location - if (choices.length > this.highlightPosition) { - // If we have an option to highlight - passedEl = choices[this.highlightPosition]; - } else { - // Otherwise highlight the option before - passedEl = choices[choices.length - 1]; - } - - if (!passedEl) { - passedEl = choices[0]; - } - } - - // Highlight given option, and set accessiblity attributes - passedEl.classList.add(this.config.classNames.highlightedState); - passedEl.setAttribute('aria-selected', 'true'); - - if (hasActiveDropdown) { - // IE11 ignores aria-label and blocks virtual keyboard - // if aria-activedescendant is set without a dropdown - this.input.setActiveDescendant(passedEl.id); - this.containerOuter.setActiveDescendant(passedEl.id); - } - } - } - - /** - * Add item to store with correct value - * @param {String} value Value to add to store - * @param {String} [label] Label to add to store - * @param {Number} [choiceId=-1] ID of the associated choice that was selected - * @param {Number} [groupId=-1] ID of group choice is within. Negative number indicates no group - * @param {Object} [customProperties] Object containing user defined properties - * @return {Object} Class instance - * @public - */ - - }, { - key: '_addItem', - value: function _addItem(value) { - var label = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; - var choiceId = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : -1; - var groupId = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : -1; - var customProperties = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null; - var placeholder = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false; - var keyCode = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : null; - - var passedValue = (0, _utils.isType)('String', value) ? value.trim() : value; - var passedKeyCode = keyCode; - var items = this.store.getItems(); - var passedLabel = label || passedValue; - var passedOptionId = parseInt(choiceId, 10) || -1; - - // Get group if group ID passed - var group = groupId >= 0 ? this.store.getGroupById(groupId) : null; - - // Generate unique id - var id = items ? items.length + 1 : 1; - - // If a prepended value has been passed, prepend it - if (this.config.prependValue) { - passedValue = this.config.prependValue + passedValue.toString(); - } - - // If an appended value has been passed, append it - if (this.config.appendValue) { - passedValue += this.config.appendValue.toString(); - } - - this.store.dispatch((0, _actions.addItem)(passedValue, passedLabel, id, passedOptionId, groupId, customProperties, placeholder, passedKeyCode)); - - if (this.isSelectOneElement) { - this.removeActiveItems(id); - } - - // Trigger change event - if (group && group.value) { - (0, _utils.triggerEvent)(this.passedElement, 'addItem', { - id: id, - value: passedValue, - label: passedLabel, - groupValue: group.value, - keyCode: passedKeyCode - }); - } else { - (0, _utils.triggerEvent)(this.passedElement, 'addItem', { - id: id, - value: passedValue, - label: passedLabel, - keyCode: passedKeyCode - }); - } - - return this; - } - - /** - * Remove item from store - * @param {Object} item Item to remove - * @return {Object} Class instance - * @public - */ - - }, { - key: '_removeItem', - value: function _removeItem(item) { - if (!item || !(0, _utils.isType)('Object', item)) { - return this; - } - - var id = item.id; - var value = item.value; - var label = item.label; - var choiceId = item.choiceId; - var groupId = item.groupId; - var group = groupId >= 0 ? this.store.getGroupById(groupId) : null; - - this.store.dispatch((0, _actions.removeItem)(id, choiceId)); - - if (group && group.value) { - (0, _utils.triggerEvent)(this.passedElement, 'removeItem', { - id: id, - value: value, - label: label, - groupValue: group.value - }); - } else { - (0, _utils.triggerEvent)(this.passedElement, 'removeItem', { - id: id, - value: value, - label: label - }); - } - - return this; - } - - /** - * Add choice to dropdown - * @param {String} value Value of choice - * @param {String} [label] Label of choice - * @param {Boolean} [isSelected=false] Whether choice is selected - * @param {Boolean} [isDisabled=false] Whether choice is disabled - * @param {Number} [groupId=-1] ID of group choice is within. Negative number indicates no group - * @param {Object} [customProperties] Object containing user defined properties - * @return - * @private - */ - - }, { - key: '_addChoice', - value: function _addChoice(value) { - var label = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; - var isSelected = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; - var isDisabled = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; - var groupId = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : -1; - var customProperties = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : null; - var placeholder = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : false; - var keyCode = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : null; - - if (typeof value === 'undefined' || value === null) { - return; - } - - // Generate unique id - var choices = this.store.getChoices(); - var choiceLabel = label || value; - var choiceId = choices ? choices.length + 1 : 1; - var choiceElementId = this.baseId + '-' + this.idNames.itemChoice + '-' + choiceId; - - this.store.dispatch((0, _actions.addChoice)(value, choiceLabel, choiceId, groupId, isDisabled, choiceElementId, customProperties, placeholder, keyCode)); - - if (isSelected) { - this._addItem(value, choiceLabel, choiceId, undefined, customProperties, placeholder, keyCode); - } - } - - /** - * Clear all choices added to the store. - * @return - * @private - */ - - }, { - key: '_clearChoices', - value: function _clearChoices() { - this.store.dispatch((0, _actions.clearChoices)()); - } - - /** - * Add group to dropdown - * @param {Object} group Group to add - * @param {Number} id Group ID - * @param {String} [valueKey] name of the value property on the object - * @param {String} [labelKey] name of the label property on the object - * @return - * @private - */ - - }, { - key: '_addGroup', - value: function _addGroup(group, id) { - var _this21 = this; - - var valueKey = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'value'; - var labelKey = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'label'; - - var groupChoices = (0, _utils.isType)('Object', group) ? group.choices : Array.from(group.getElementsByTagName('OPTION')); - var groupId = id || Math.floor(new Date().valueOf() * Math.random()); - var isDisabled = group.disabled ? group.disabled : false; - - if (groupChoices) { - this.store.dispatch((0, _actions.addGroup)(group.label, groupId, true, isDisabled)); - - groupChoices.forEach(function (option) { - var isOptDisabled = option.disabled || option.parentNode && option.parentNode.disabled; - _this21._addChoice(option[valueKey], (0, _utils.isType)('Object', option) ? option[labelKey] : option.innerHTML, option.selected, isOptDisabled, groupId, option.customProperties, option.placeholder); - }); - } else { - this.store.dispatch((0, _actions.addGroup)(group.label, group.id, false, group.disabled)); - } - } - - /** - * Get template from name - * @param {String} template Name of template to get - * @param {...} args Data to pass to template - * @return {HTMLElement} Template - * @private - */ - - }, { - key: '_getTemplate', - value: function _getTemplate(template) { - if (!template) { - return null; - } - var templates = this.config.templates; - - for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { - args[_key - 1] = arguments[_key]; - } - - return templates[template].apply(templates, args); - } - - /** - * Create HTML element based on type and arguments - * @return - * @private - */ - - }, { - key: '_createTemplates', - value: function _createTemplates() { - var _this22 = this; - - var globalClasses = this.config.classNames; - var templates = { - containerOuter: function containerOuter(direction) { - var tabIndex = _this22.isSelectOneElement ? 'tabindex="0"' : ''; - var role = _this22.isSelectElement ? 'role="listbox"' : ''; - var ariaAutoComplete = ''; - - if (_this22.isSelectElement && _this22.config.searchEnabled) { - role = 'role="combobox"'; - ariaAutoComplete = 'aria-autocomplete="list"'; - } - - return (0, _utils.strToEl)('\n