From 278a693886ce9e8393709b9a5c026a182d9c95b6 Mon Sep 17 00:00:00 2001 From: Josh Johnson Date: Wed, 8 Jun 2016 14:45:29 +0100 Subject: [PATCH] Allow chaining + private/public function differentation + set/clear value methods --- assets/scripts/dist/choices.min.js | 4 +- assets/scripts/src/actions/index.js | 6 + assets/scripts/src/choices.js | 987 +++++++++++++++------------ assets/scripts/src/reducers/index.js | 17 +- build/config.gypi | 56 -- index.html | 4 +- 6 files changed, 573 insertions(+), 501 deletions(-) delete mode 100644 build/config.gypi diff --git a/assets/scripts/dist/choices.min.js b/assets/scripts/dist/choices.min.js index 883f291..875d4a9 100644 --- a/assets/scripts/dist/choices.min.js +++ b/assets/scripts/dist/choices.min.js @@ -1,2 +1,2 @@ -!function(t){function e(n){if(i[n])return i[n].exports;var s=i[n]={exports:{},id:n,loaded:!1};return t[n].call(s.exports,s,s.exports,e),s.loaded=!0,s.exports}var i={};return e.m=t,e.c=i,e.p="/assets/scripts/dist/",e(0)}([function(t,e,i){t.exports=i(1)},function(t,e,i){"use strict";function n(t){return t&&t.__esModule?t:{"default":t}}function s(t){if(Array.isArray(t)){for(var e=0,i=Array(t.length);e1)for(var s=1;s=1&&t!==i+" "){var n=e.store.getOptionsFiltedBySelectable(),s=t,o=new u.default(n,{keys:["label","value"],shouldSort:!0,include:"score"}),r=o.search(s);e.currentValue=t,e.highlightPosition=0,e.isSearching=!0,e.store.dispatch((0,a.filterOptions)(r))}};d()}else c&&(this.isSearching=!1,this.store.dispatch((0,a.activateOptions)()))}}}},{key:"onInput",value:function(t){"select-one"!==this.passedElement.type&&(this.input.style.width=(0,l.getWidthOfInput)(this.input))}},{key:"onMouseDown",value:function(t){var e=this;if(2!==t.button){var i=this.store.getItemsFilteredByActive();if(this.containerOuter.contains(t.target))!function(){t.preventDefault();var n=!!t.shiftKey;"text"===e.passedElement.type||e.dropdown.classList.contains(e.options.classNames.activeState)||e.showDropdown(),e.input!==document.activeElement&&e.input.focus(),t.target.hasAttribute("data-button")?e.options.removeItems&&e.options.removeButton&&!function(){var n=t.target.parentNode.getAttribute("data-id"),s=i.find(function(t){return t.id===parseInt(n)});e.removeItem(s)}():t.target.hasAttribute("data-item")?e.options.removeItems&&!function(){var s=t.target.getAttribute("data-id");i.forEach(function(t){t.id!==parseInt(s)||t.selected?n||e.deselectItem(t):e.selectItem(t)})}():t.target.hasAttribute("data-option")&&!function(){var i=e.store.getOptionsFilteredByActive(),n=t.target.getAttribute("data-id"),s=i.find(function(t){return t.id===parseInt(n)});s.selected||s.disabled||(e.addItem(s.value,s.label,s.id),"select-one"===e.passedElement.type&&(e.input.value="",e.isSearching=!1,e.store.dispatch((0,a.activateOptions)(!0)),e.toggleDropdown()))}()}();else{var n=this.dropdown.classList.contains(this.options.classNames.activeState),s=i.some(function(t){return t.selected===!0});s&&this.deselectAll(),this.containerOuter.classList.remove(this.options.classNames.focusState),n&&this.toggleDropdown()}}}},{key:"onPaste",value:function(t){t.target===this.input&&(this.options.allowPaste||t.preventDefault())}},{key:"onMouseOver",value:function(t){(t.target===this.dropdown||(0,l.findAncestor)(t.target,this.options.classNames.listDropdown))&&t.target.hasAttribute("data-option")&&this.highlightOption(t.target)}},{key:"onFocus",value:function(t){var e=this.dropdown.classList.contains(this.options.classNames.activeState);t.target!==this.input||e||(this.containerOuter.classList.add(this.options.classNames.focusState),"select-one"!==this.passedElement.type&&"select-multiple"!==this.passedElement.type||this.showDropdown())}},{key:"onBlur",value:function(t){var e=this.dropdown.classList.contains(this.options.classNames.activeState);t.target!==this.input||e?this.hideDropdown():this.containerOuter.classList.remove(this.options.classNames.focusState)}},{key:"clearInput",value:function(){this.input.value&&(this.input.value=""),"select-one"!==this.passedElement.type&&(this.input.style.width=(0,l.getWidthOfInput)(this.input))}},{key:"regexFilter",value:function(t){if(t){var e=new RegExp(this.options.regexFilter,"i");return e.test(t)}}},{key:"scrollToOption",value:function(t,e){var i=this;if(t){var n=this.optionList.offsetHeight,s=t.offsetHeight,o=t.offsetTop+s,r=this.optionList.scrollTop+n,a=e>0?this.optionList.scrollTop+o-r:t.offsetTop,l=function c(t,e,n){var s=!1,o=void 0,r=void 0,a=4;n>0?(o=(e-i.optionList.scrollTop)/a,r=o>1?o:1,i.optionList.scrollTop=i.optionList.scrollTop+r,i.optionList.scrollTop1?o:1,i.optionList.scrollTop=i.optionList.scrollTop-r,i.optionList.scrollTop>e&&(s=!0)),s&&requestAnimationFrame(function(t){c(t,e,n)})};requestAnimationFrame(function(t){l(t,a,e)})}}},{key:"highlightOption",value:function(t){var e=this,i=Array.from(this.dropdown.querySelectorAll("[data-option-selectable]"));if(i.length){var n=Array.from(this.dropdown.querySelectorAll("."+this.options.classNames.highlightedState));if(n.forEach(function(t){t.classList.remove(e.options.classNames.highlightedState)}),t)t.classList.add(this.options.classNames.highlightedState),this.highlightPosition=i.indexOf(t);else{var s=void 0;s=i.length>this.highlightPosition?i[this.highlightPosition]:i[i.length-1],s||(s=i[0]),s.classList.add(this.options.classNames.highlightedState)}}}},{key:"selectItem",value:function(t){if(t){var e=t.id;this.store.dispatch((0,a.selectItem)(e,!0))}}},{key:"deselectItem",value:function(t){if(t){var e=t.id;this.store.dispatch((0,a.selectItem)(e,!1))}}},{key:"selectAll",value:function(){var t=this,e=this.store.getItems();e.forEach(function(e){t.selectItem(e)})}},{key:"deselectAll",value:function(){var t=this,e=this.store.getItems();e.forEach(function(e){t.deselectItem(e)})}},{key:"addItem",value:function(t,e){var i=arguments.length<=2||void 0===arguments[2]?-1:arguments[2],n=arguments.length<=3||void 0===arguments[3]?this.options.callbackOnAddItem:arguments[3],s=this.store.getItems(),o=t.trim(),r=e||o,c=i||-1;this.options.prependValue&&(o=this.options.prependValue+o.toString()),this.options.appendValue&&(o+=this.options.appendValue.toString());var u=s?s.length+1:1;this.store.dispatch((0,a.addItem)(o,r,u,c)),"select-one"===this.passedElement.type&&this.removeActiveItems(u),n&&((0,l.isType)("Function",n)?n(u,o,this.passedElement):console.error("callbackOnAddItem: Callback is not a function"))}},{key:"removeItem",value:function(t){var e=arguments.length<=1||void 0===arguments[1]?this.options.callbackOnRemoveItem:arguments[1];if(!t||!(0,l.isType)("Object",t))return void console.error("removeItem: No item object was passed to be removed");var i=t.id,n=(t.value,t.optionId);return this.store.dispatch((0,a.removeItem)(i,n)),e?void((0,l.isType)("Function",e)||console.error("callbackOnRemoveItem: Callback is not a function")):void 0}},{key:"removeItemsByValue",value:function(t){return void(t&&(0,l.isType)("String",t)||console.error("removeItemsByValue: No value was passed to be removed"))}},{key:"removeActiveItems",value:function(t){var e=this,i=this.store.getItemsFilteredByActive();i.forEach(function(i){i.active&&t!==i.id&&e.removeItem(i)})}},{key:"removeSelectedItems",value:function(){var t=this,e=this.store.getItemsFilteredByActive();e.forEach(function(e){e.selected&&e.active&&t.removeItem(e)})}},{key:"addOption",value:function(t,e,i){var n=arguments.length<=3||void 0===arguments[3]?-1:arguments[3];if(e){i||(i=e);var s=this.store.getOptions(),o=s.length+1,r=t&&(t.disabled||t.parentNode.disabled);this.store.dispatch((0,a.addOption)(e,i,o,n,r)),t&&t.selected&&!r&&this.addItem(e,i,o)}}},{key:"addGroup",value:function(t,e,i){var n=this,s=Array.from(t.getElementsByTagName("OPTION")),o=e;s?(this.store.dispatch((0,a.addGroup)(t.label,o,!0,t.disabled)),s.forEach(function(t,e){n.addOption(t,t.value,t.innerHTML,o)})):this.store.dispatch((0,a.addGroup)(t.label,t.id,!1,t.disabled))}},{key:"showDropdown",value:function(){this.containerOuter.classList.add(this.options.classNames.openState),this.dropdown.classList.add(this.options.classNames.activeState);var t=this.dropdown.getBoundingClientRect(),e=t.top+t.height>=document.body.offsetHeight;e?this.containerOuter.classList.add(this.options.classNames.flippedState):this.containerOuter.classList.remove(this.options.classNames.flippedState)}},{key:"hideDropdown",value:function(){var t=this.containerOuter.classList.contains(this.options.classNames.flippedState);this.containerOuter.classList.remove(this.options.classNames.openState),this.dropdown.classList.remove(this.options.classNames.activeState),t&&this.containerOuter.classList.remove(this.options.classNames.flippedState)}},{key:"toggleDropdown",value:function(){var t=this.dropdown.classList.contains(this.options.classNames.activeState);t?this.hideDropdown():this.showDropdown()}},{key:"setValue",value:function(t){var e=this,i=[].concat(s(t));i.forEach(function(t,i){if((0,l.isType)("Object",t)){if(!t.value)return;e.addItem(t.value,t.label,t.id)}else(0,l.isType)("String",t)&&e.addItem(t)})}},{key:"clearValue",value:function(){}},{key:"disable",value:function(){this.passedElement.disabled=!0,this.initialised&&(this.input.disabled=!0,this.containerOuter.classList.add(this.options.classNames.disabledState))}},{key:"ajax",value:function(t){var e=this;this.containerOuter.classList.add("is-loading");var i=this.getTemplate("item",{id:-1,value:"Loading",label:this.options.loadingText,active:!0});this.itemList.appendChild(i);var n=function(t,i,n){t&&t.length&&(e.containerOuter.classList.remove("is-loading"),e.input.placeholder="",t.forEach(function(t,s){0===s&&e.addItem(t[i],t[n],s),e.addOption(null,t[i],t[n])}))};t(n)}},{key:"getTemplate",value:function(t){if(t){for(var e=this.options.templates,i=arguments.length,n=Array(i>1?i-1:0),s=1;i>s;s++)n[s-1]=arguments[s];return e[t].apply(e,n)}}},{key:"createTemplates",value:function(){var t=this,e=this.options.classNames,i={containerOuter:function(){return(0,l.strToEl)('
')},containerInner:function(){return(0,l.strToEl)('
')},itemList:function(){return(0,l.strToEl)('
')},optionList:function(){return(0,l.strToEl)('
')},input:function(){return(0,l.strToEl)('')},dropdown:function(){return(0,l.strToEl)('
')},notice:function(t,i){return(0,l.strToEl)('
'+t+"
")},selectOption:function(t){return(0,l.strToEl)('")},option:function(t){return(0,l.strToEl)('\n
\n '+t.label+"\n
\n ")},optgroup:function(t){return(0,l.strToEl)('\n
\n
'+t.value+"
\n
\n ")},item:function(i){return t.options.removeButton?(0,l.strToEl)('\n
\n '+i.label+'\n \n
\n '):(0,l.strToEl)('\n
\n '+i.label+"\n
\n ")}};this.options.templates=(0,l.extend)(this.options.templates,i)}},{key:"generateInput",value:function(){var t=this,e=this.getTemplate("containerOuter"),i=this.getTemplate("containerInner"),n=this.getTemplate("itemList"),s=this.getTemplate("optionList"),o=this.getTemplate("input"),r=this.getTemplate("dropdown");if(this.containerOuter=e,this.containerInner=i,this.input=o,this.optionList=s,this.itemList=n,this.dropdown=r,this.passedElement.classList.add(this.options.classNames.input,this.options.classNames.hiddenState),this.passedElement.tabIndex="-1",this.passedElement.setAttribute("style","display:none;"),this.passedElement.setAttribute("aria-hidden","true"),this.passedElement.removeAttribute("data-choice"),(0,l.wrap)(this.passedElement,i),(0,l.wrap)(i,e),this.options.placeholder&&(this.options.placeholderValue||this.passedElement.placeholder)){var a=this.options.placeholderValue||this.passedElement.placeholder;o.placeholder=a,"select-one"!==this.passedElement.type&&(o.style.width=(0,l.getWidthOfInput)(o))}if(this.options.addItems||this.disable(),e.appendChild(i),e.appendChild(r),i.appendChild(n),r.appendChild(s),"select-multiple"===this.passedElement.type||"text"===this.passedElement.type?i.appendChild(o):this.options.allowSearch&&r.insertBefore(o,r.firstChild),"select-multiple"===this.passedElement.type||"select-one"===this.passedElement.type){this.highlightPosition=0;var c=Array.from(this.passedElement.getElementsByTagName("OPTGROUP"));if(this.isSearching=!1,c&&c.length)c.forEach(function(e,i){var n=0===i;t.addGroup(e,i,n)});else{var u=Array.from(this.passedElement.options);u.forEach(function(e){t.addOption(e,e.value,e.innerHTML)})}}else"text"===this.passedElement.type&&this.presetItems.forEach(function(e){if((0,l.isType)("Object",e)){if(!e.value)return;t.addItem(e.value,e.label,e.id)}else(0,l.isType)("String",e)&&t.addItem(e)})}},{key:"renderGroups",value:function(t,e,i){var n=this,s=i||document.createDocumentFragment();return t.forEach(function(t,i){var o=e.filter(function(e){return"select-one"===n.passedElement.type?e.groupId===t.id:e.groupId===t.id&&!e.selected});if(o.length>=1){var r=n.getTemplate("optgroup",t);s.appendChild(r),n.renderOptions(o,s)}}),s}},{key:"renderOptions",value:function(t,e){var i=this,n=e||document.createDocumentFragment();return t.forEach(function(t,e){var s=i.getTemplate("option",t);"select-one"===i.passedElement.type?n.appendChild(s):t.selected||n.appendChild(s)}),n}},{key:"renderItems",value:function(t,e){var i=this,n=e||document.createDocumentFragment(),s=this.store.getItemsReducedToValues(t);"text"===this.passedElement.type?this.passedElement.setAttribute("value",s.join(this.options.delimiter)):!function(){var e=document.createDocumentFragment();t.forEach(function(t){var n=i.getTemplate("selectOption",t);e.appendChild(n)}),i.passedElement.innerHTML="",i.passedElement.appendChild(e)}(),t.forEach(function(t){var e=i.getTemplate("item",t);n.appendChild(e)}),this.itemList.innerHTML="",this.itemList.appendChild(n)}},{key:"render",value:function(){if(this.currentState=this.store.getState(),this.currentState!==this.prevState){if(!(this.currentState.options===this.prevState.options&&this.currentState.groups===this.prevState.groups||"select-multiple"!==this.passedElement.type&&"select-one"!==this.passedElement.type)){var t=this.store.getGroupsFilteredByActive(),e=this.store.getOptionsFilteredByActive(),i=document.createDocumentFragment();if(this.optionList.innerHTML="",t.length>=1&&this.isSearching!==!0?this.renderGroups(t,e,i):e.length>=1&&this.renderOptions(e,i),i.children.length)this.optionList.appendChild(i),this.highlightOption();else{var n=this.isSearching?this.getTemplate("notice","No results found"):this.getTemplate("notice","No options to select");this.optionList.appendChild(n)}}if(this.currentState.items!==this.prevState.items){var s=this.store.getItemsFilteredByActive();s&&this.renderItems(s)}this.prevState=this.currentState}}},{key:"addEventListeners",value:function(){document.addEventListener("keyup",this.onKeyUp),document.addEventListener("keydown",this.onKeyDown),document.addEventListener("mousedown",this.onMouseDown),document.addEventListener("mouseover",this.onMouseOver),this.input.addEventListener("input",this.onInput),this.input.addEventListener("paste",this.onPaste),this.input.addEventListener("focus",this.onFocus),this.input.addEventListener("blur",this.onBlur)}},{key:"removeEventListeners",value:function(){document.removeEventListener("keyup",this.onKeyUp),document.removeEventListener("keydown",this.onKeyDown),document.removeEventListener("mousedown",this.onMouseDown),document.removeEventListener("mouseover",this.onMouseOver),this.input.removeEventListener("input",this.onInput),this.input.removeEventListener("paste",this.onPaste),this.input.removeEventListener("focus",this.onFocus),this.input.removeEventListener("blur",this.onBlur)}},{key:"init",value:function(t){this.initialised!==!0&&(this.initialised=!0,this.createTemplates(),this.generateInput(),this.store.subscribe(this.render),this.render(),this.addEventListeners(),(t=this.options.callbackOnInit)&&((0,l.isType)("Function",t)?t():console.error("callbackOnInit: Callback is not a function")))}},{key:"destroy",value:function(){this.passedElement.classList.remove(this.options.classNames.input,this.options.classNames.hiddenState),this.passedElement.tabIndex="",this.passedElement.removeAttribute("style","display:none;"),this.passedElement.removeAttribute("aria-hidden"),this.containerOuter.outerHTML=this.passedElement.outerHTML,this.passedElement=null,this.userOptions=null,this.options=null,this.store=null,this.removeEventListeners()}}]),t}();window.Choices=t.exports=p},function(t,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0});e.addItem=function(t,e,i,n){return{type:"ADD_ITEM",value:t,label:e,id:i,optionId:n}},e.removeItem=function(t,e){return{type:"REMOVE_ITEM",id:t,optionId:e}},e.selectItem=function(t,e){return{type:"SELECT_ITEM",id:t,selected:e}},e.addOption=function(t,e,i,n,s){return{type:"ADD_OPTION",value:t,label:e,id:i,groupId:n,disabled:s}},e.filterOptions=function(t){return{type:"FILTER_OPTIONS",results:t}},e.activateOptions=function(){var t=arguments.length<=0||void 0===arguments[0]?!0:arguments[0];return{type:"ACTIVATE_OPTIONS",active:t}},e.addGroup=function(t,e,i,n){return{type:"ADD_GROUP",value:t,id:e,active:i,disabled:n}}},function(t,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var i=(e.hasClass=function(t,e){return new RegExp(" "+e+" ").test(" "+t.className+" ")},e.capitalise=function(t){return t.replace(/\w\S*/g,function(t){return t.charAt(0).toUpperCase()+t.substr(1).toLowerCase()})},e.isType=function(t,e){var i=Object.prototype.toString.call(e).slice(8,-1);return void 0!==e&&null!==e&&i===t}),n=(e.extend=function o(){for(var t={},e=!1,n=arguments.length,s=function(n){for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(e&&i("Object",n[s])?t[s]=o(!0,t[s],n[s]):t[s]=n[s])},r=0;n>r;r++){var a=arguments[r];i("Object",a)?s(a):console.error("Custom options must be an object")}return t},e.whichTransitionEvent=function(){var t,e=document.createElement("fakeelement"),i={transition:"transitionend",OTransition:"oTransitionEnd",MozTransition:"transitionend",WebkitTransition:"webkitTransitionEnd"};for(t in i)if(void 0!==e.style[t])return i[t]},e.whichAnimationEvent=function(){var t,e=document.createElement("fakeelement"),i={animation:"animationend",OAnimation:"oAnimationEnd",MozAnimation:"animationend",WebkitAnimation:"webkitAnimationEnd"};for(t in i)if(void 0!==e.style[t])return i[t]}),s=(e.getParentsUntil=function(t,e,i){for(var n=[];t&&t!==document;t=t.parentNode){if(e){var s=e.charAt(0);if("."===s&&t.classList.contains(e.substr(1)))break;if("#"===s&&t.id===e.substr(1))break;if("["===s&&t.hasAttribute(e.substr(1,e.length-1)))break;if(t.tagName.toLowerCase()===e)break}if(i){var o=i.charAt(0);"."===o&&t.classList.contains(i.substr(1))&&n.push(t),"#"===o&&t.id===i.substr(1)&&n.push(t),"["===o&&t.hasAttribute(i.substr(1,i.length-1))&&n.push(t),t.tagName.toLowerCase()===i&&n.push(t)}else n.push(t)}return 0===n.length?null:n},e.wrap=function(t,e){return e=e||document.createElement("div"),t.nextSibling?t.parentNode.insertBefore(e,t.nextSibling):t.parentNode.appendChild(e),e.appendChild(t)},e.getSiblings=function(t){for(var e=[],i=t.parentNode.firstChild;i;i=i.nextSibling)1===i.nodeType&&i!==t&&e.push(i);return e},e.findAncestor=function(t,e){for(;(t=t.parentElement)&&!t.classList.contains(e););return t},e.debounce=function(t,e,i){var n;return function(){var s=this,o=arguments,r=function(){n=null,i||t.apply(s,o)},a=i&&!n;clearTimeout(n),n=setTimeout(r,e),a&&t.apply(s,o)}},e.getElemDistance=function(t){var e=0;if(t.offsetParent)do e+=t.offsetTop,t=t.offsetParent;while(t);return e>=0?e:0},e.getElementOffset=function(t,e){var i=e;return i>1&&(i=1),i>0&&(i=0),Math.max(t.offsetHeight*i)},e.getAdjacentEl=function(t,e){var i=arguments.length<=2||void 0===arguments[2]?1:arguments[2];if(t&&e){var n=t.parentNode.parentNode,s=Array.from(n.querySelectorAll(e)),o=s.indexOf(t),r=i>0?1:-1;return s[o+r]}},e.getScrollPosition=function(t){return"bottom"===t?Math.max((window.scrollY||window.pageYOffset)+(window.innerHeight||document.documentElement.clientHeight)):window.scrollY||window.pageYOffset},e.isInView=function(t,e,i){return this.getScrollPosition(e)>this.getElemDistance(t)+this.getElementOffset(t,i)},e.isScrolledIntoView=function(t,e){var i=arguments.length<=2||void 0===arguments[2]?1:arguments[2];if(t){var n=void 0;return n=i>0?e.scrollTop+e.offsetHeight>=t.offsetTop+t.offsetHeight:t.offsetTop>=e.scrollTop}},e.stripHTML=function(t){var e=document.createElement("DIV");return e.innerHTML=t,e.textContent||e.innerText||""},e.addAnimation=function(t,e){var i=n(),s=function o(){t.classList.remove(e),t.removeEventListener(i,o,!1)};t.classList.add(e),t.addEventListener(i,s,!1)},e.getRandomNumber=function(t,e){return Math.floor(Math.random()*(e-t)+t)},e.strToEl=function(){var t=document.createElement("div");return function(e){var i;for(t.innerHTML=e,i=t.children[0];t.firstChild;)t.removeChild(t.firstChild);return i}}());e.getWidthOfInput=function(t){var e=t.value||t.placeholder,i=t.offsetWidth;if(e){var n=s(""+e+"");n.style.position="absolute",n.style.padding="0",n.style.top="-9999px",n.style.left="-9999px",n.style.width="auto",n.style.whiteSpace="pre",document.body.appendChild(n),e&&n.offsetWidth!==t.offsetWidth&&(i=n.offsetWidth+4),document.body.removeChild(n)}return i+"px"}},function(t,e,i){!function(e){"use strict";function i(){console.log.apply(console,arguments)}function n(t,e){var i,n,s,o;for(this.list=t,this.options=e=e||{},i=0,o=["sort","shouldSort","verbose","tokenize"],n=o.length;n>i;i++)s=o[i],this.options[s]=s in e?e[s]:l[s];for(i=0,o=["searchFn","sortFn","keys","getFn","include"],n=o.length;n>i;i++)s=o[i],this.options[s]=e[s]||l[s]}function s(t,e,i){var n,r,a,l,c,u;if(e){if(a=e.indexOf("."),-1!==a?(n=e.slice(0,a),r=e.slice(a+1)):n=e,l=t[n],null!==l&&void 0!==l)if(r||"string"!=typeof l&&"number"!=typeof l)if(o(l))for(c=0,u=l.length;u>c;c++)s(l[c],r,i);else r&&s(l,r,i);else i.push(l)}else i.push(t);return i}function o(t){return"[object Array]"===Object.prototype.toString.call(t)}function r(t,e){e=e||{},this.options=e,this.options.location=e.location||r.defaultOptions.location,this.options.distance="distance"in e?e.distance:r.defaultOptions.distance,this.options.threshold="threshold"in e?e.threshold:r.defaultOptions.threshold,this.options.maxPatternLength=e.maxPatternLength||r.defaultOptions.maxPatternLength,this.pattern=e.caseSensitive?t:t.toLowerCase(),this.patternLen=t.length,this.patternLen<=this.options.maxPatternLength&&(this.matchmask=1<s;s++)this.tokenSearchers.push(new i(n[s],t));this.fullSeacher=new i(e,t)},n.prototype._startSearch=function(){var t,e,i,n,s=this.options,o=s.getFn,r=this.list,a=r.length,l=this.options.keys,c=l.length,u=null;if("string"==typeof r[0])for(i=0;a>i;i++)this._analyze("",r[i],i,i);else for(this._keyMap={},i=0;a>i;i++)for(u=r[i],n=0;c>n;n++){if(t=l[n],"string"!=typeof t){if(e=1-t.weight||1,this._keyMap[t.name]={weight:e},t.weight<=0||t.weight>1)throw new Error("Key weight has to be > 0 and <= 1");t=t.name}else this._keyMap[t]={weight:1};this._analyze(t,o(u,t,[]),u,i)}},n.prototype._analyze=function(t,e,n,s){var r,l,c,u,d,h,p,f,v,m,g,y,b,E,w,I=this.options,S=!1;if(void 0!==e&&null!==e)if(l=[],"string"==typeof e){if(r=e.split(a),I.verbose&&i("---------\nKey:",t),I.verbose&&i("Record:",r),this.options.tokenize){for(c=this.tokenSearchers,u=c.length,E=0;EE;E++)h+=l[E];h/=f,I.verbose&&i("Token score average:",h)}v=this.fullSeacher.search(e),I.verbose&&i("Full text score:",v.score),p=v.score,void 0!==h&&(p=(p+h)/2),I.verbose&&i("Score average:",p),(S||v.isMatch)&&(d=this.resultMap[s],d?d.output.push({key:t,score:p,matchedIndices:v.matchedIndices}):(this.resultMap[s]={item:n,output:[{key:t,score:p,matchedIndices:v.matchedIndices -}]},this.results.push(this.resultMap[s])))}else if(o(e))for(E=0;Ee;e++)r=s[e].score,a=u?u[s[e].key].weight:1,c=r*a,1!==a?l=Math.min(l,c):(n+=c,s[e].nScore=c);1===l?d[t].score=n/o:d[t].score=l,this.options.verbose&&i(d[t])}},n.prototype._sort=function(){var t=this.options;t.shouldSort&&(t.verbose&&i("\n\nSorting...."),this.results.sort(t.sortFn))},n.prototype._format=function(){var t,e,n,s,o,r=this.options,a=r.getFn,l=[],c=this.results,u=r.include;for(r.verbose&&i("\n\nOutput:\n\n",c),s=r.id?function(t){c[t].item=a(c[t].item,r.id,[])[0]}:function(){},o=function(t){var e,i,n,s,o,r=c[t];if(u.length>0){if(e={item:r.item},-1!==u.indexOf("matches"))for(n=r.output,e.matches=[],i=0;ie;e++)s(e),t=o(e),l.push(t);return l},r.defaultOptions={location:0,distance:100,threshold:.6,maxPatternLength:32},r.prototype._calculatePatternAlphabet=function(){var t={},e=0;for(e=0;eO.maxPatternLength){if(y=t.match(new RegExp(this.pattern.replace(a,"|"))),b=!!y)for(w=[],e=0,I=y.length;I>e;e++)S=y[e],w.push([t.indexOf(S),S.length-1]);return{isMatch:b,score:b?.5:1,matchedIndices:w}}for(s=O.location,n=t.length,o=O.threshold,r=t.indexOf(this.pattern,s),E=[],e=0;n>e;e++)E[e]=0;for(-1!=r&&(o=Math.min(this._bitapScore(0,r),o),r=t.lastIndexOf(this.pattern,s+this.patternLen),-1!=r&&(o=Math.min(this._bitapScore(0,r),o))),r=-1,m=1,g=[],u=this.patternLen+n,e=0;el;)this._bitapScore(e,s+c)<=o?l=c:u=c,c=Math.floor((u-l)/2+l);for(u=c,d=Math.max(1,s-c+1),h=Math.min(s+c,n)+this.patternLen,p=Array(h+2),p[h+1]=(1<=d;i--)if(v=this.patternAlphabet[t.charAt(i-1)],v&&(E[i-1]=1),0===e?p[i]=(p[i+1]<<1|1)&v:p[i]=(p[i+1]<<1|1)&v|((f[i+1]|f[i])<<1|1)|f[i+1],p[i]&this.matchmask&&(m=this._bitapScore(e,i-1),o>=m)){if(o=m,r=i-1,g.push(r),!(r>s))break;d=Math.max(1,2*s-r)}if(this._bitapScore(e+1,s)>o)break;f=p}return w=this._getMatchedIndices(E),{isMatch:r>=0,score:0===m?.001:m,matchedIndices:w}},r.prototype._getMatchedIndices=function(t){for(var e,i=[],n=-1,s=-1,o=0,r=r=t.length;r>o;o++)e=t[o],e&&-1===n?n=o:e||-1===n||(s=o-1,i.push([n,s]),n=-1);return t[o-1]&&i.push([n,o-1]),i},t.exports=n}(this)},function(t,e,i){"use strict";function n(t){return t&&t.__esModule?t:{"default":t}}function s(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(e,"__esModule",{value:!0}),e.Store=void 0;var o=function(){function t(t,e){for(var i=0;ii;i++)e[i]=arguments[i];return function(t){return function(i,n,s){var r=t(i,n,s),l=r.dispatch,c=[],u={getState:r.getState,dispatch:function(t){return l(t)}};return c=e.map(function(t){return t(u)}),l=a.default.apply(void 0,c)(r.dispatch),o({},r,{dispatch:l})}}}e.__esModule=!0;var o=Object.assign||function(t){for(var e=1;ei;i++)e[i]=arguments[i];if(0===e.length)return function(t){return t};var n=function(){var t=e[e.length-1],i=e.slice(0,-1);return{v:function(){return i.reduceRight(function(t,e){return e(t)},t.apply(void 0,arguments))}}}();return"object"==typeof n?n.v:void 0}e.__esModule=!0,e.default=i},function(t,e,i){"use strict";function n(t){return t&&t.__esModule?t:{"default":t}}Object.defineProperty(e,"__esModule",{value:!0});var s=i(6),o=i(20),r=n(o),a=i(21),l=n(a),c=i(22),u=n(c),d=(0,s.combineReducers)({items:r.default,groups:l.default,options:u.default});e.default=d},function(t,e){"use strict";function i(t){if(Array.isArray(t)){for(var e=0,i=Array(t.length);e-1?t.map(function(t){return t.id===parseInt(e.optionId)&&(t.selected=!0),t}):t;case"REMOVE_ITEM":return e.optionId>-1?t.map(function(t){return t.id===parseInt(e.optionId)&&(t.selected=!1),t}):t;case"FILTER_OPTIONS":var n=e.results,s=t.map(function(t,e){return t.active=n.some(function(e){return e.item.id===t.id?(t.score=e.score,!0):void 0}),t}).sort(function(t,e){return t.score-e.score});return s;case"ACTIVATE_OPTIONS":return t.map(function(t){return t.active=e.active,t});default:return t}};e.default=n}]); \ No newline at end of file +!function(t){function e(n){if(i[n])return i[n].exports;var s=i[n]={exports:{},id:n,loaded:!1};return t[n].call(s.exports,s,s.exports,e),s.loaded=!0,s.exports}var i={};return e.m=t,e.c=i,e.p="/assets/scripts/dist/",e(0)}([function(t,e,i){t.exports=i(1)},function(t,e,i){"use strict";function n(t){return t&&t.__esModule?t:{"default":t}}function s(t){if(Array.isArray(t)){for(var e=0,i=Array(t.length);e1)for(var s=1;s=document.body.offsetHeight;return e?this.containerOuter.classList.add(this.options.classNames.flippedState):this.containerOuter.classList.remove(this.options.classNames.flippedState),this}},{key:"hideDropdown",value:function(){var t=this.containerOuter.classList.contains(this.options.classNames.flippedState);return this.containerOuter.classList.remove(this.options.classNames.openState),this.dropdown.classList.remove(this.options.classNames.activeState),t&&this.containerOuter.classList.remove(this.options.classNames.flippedState),this}},{key:"toggleDropdown",value:function(){var t=this.dropdown.classList.contains(this.options.classNames.activeState);return t?this.hideDropdown():this.showDropdown(),this}},{key:"setValue",value:function(t){var e=this,i=[].concat(s(t));return i.forEach(function(t,i){if((0,l.isType)("Object",t)){if(!t.value)return;"text"!==e.passedElement.type?e._addOption(!0,!1,t.value,t.label,-1):e.addItem(t.value,t.label,t.id)}else(0,l.isType)("String",t)&&("text"!==e.passedElement.type?e._addOption(!0,!1,t,t,-1):e.addItem(t))}),this}},{key:"clearValue",value:function(){return this.store.dispatch((0,a.clearAll)()),this}},{key:"disable",value:function(){return this.passedElement.disabled=!0,this.initialised&&(this.input.disabled=!0,this.containerOuter.classList.add(this.options.classNames.disabledState)),this}},{key:"ajax",value:function(t){var e=this;this.containerOuter.classList.add("is-loading");var i=this._getTemplate("item",{id:-1,value:"Loading",label:this.options.loadingText,active:!0});this.itemList.appendChild(i);var n=function(t,i,n){t&&t.length&&(e.containerOuter.classList.remove("is-loading"),e.input.placeholder="",t.forEach(function(t,s){0===s&&e.addItem(t[i],t[n],s),e._addOption(!1,!1,t[i],t[n])}))};return t(n),this}},{key:"clearInput",value:function(){return this.input.value&&(this.input.value=""),"select-one"!==this.passedElement.type&&(this.input.style.width=(0,l.getWidthOfInput)(this.input)),this}},{key:"_handleEnter",value:function(t,e){var i=!0;if(this.options.addItems?this.options.maxItems&&this.options.maxItems<=this.itemList.children.length?i=!1:this.options.allowDuplicates===!1&&this.passedElement.value&&(i=!t.some(function(t){return t.value===e})):i=!1,i){var n=!0;this.options._regexFilter&&(n=this._regexFilter(e)),n&&(this.toggleDropdown(),this.addItem(e),this.clearInput(this.passedElement))}}},{key:"_handleBackspace",value:function(t){if(this.options.removeItems&&t){var e=t[t.length-1],i=t.some(function(t){return t.selected===!0});this.options.editItems&&!i&&e?(this.input.value=e.value,this.removeItem(e)):(i||this.selectItem(e),this.removeSelectedItems())}}},{key:"_onKeyDown",value:function(t){if(t.target===this.input){var e=t.ctrlKey||t.metaKey,i=46,n=8,s=13,o=65,r=27,c=38,u=40,d=this.store.getItemsFilteredByActive(),h=(this.store.getOptionsFilteredByActive(),this.input===document.activeElement),p=this.dropdown.classList.contains(this.options.classNames.activeState),f=this.itemList&&this.itemList.children,v=String.fromCharCode(event.keyCode);switch("text"!==this.passedElement.type&&/[a-zA-Z0-9-_ ]/.test(v)&&!p&&this.showDropdown(),this.canSearch=this.options.allowSearch,t.keyCode){case o:e&&f&&(this.canSearch=!1,this.options.removeItems&&!this.input.value&&this.options.selectAll&&this.input===document.activeElement&&this.selectAll(this.itemList.children));break;case s:if(t.target.value&&"text"===this.passedElement.type){var m=this.input.value;this._handleEnter(d,m)}if(p){var g=this.dropdown.querySelector("."+this.options.classNames.highlightedState);if(g){var y=g.getAttribute("data-value"),b=g.innerHTML,_=g.getAttribute("data-id");this.addItem(y,b,_),this.clearInput(this.passedElement),"select-one"===this.passedElement.type&&(this.isSearching=!1,this.store.dispatch((0,a.activateOptions)()),this.toggleDropdown())}}break;case r:p&&this.toggleDropdown();break;case u:case c:if(p){var E=this.dropdown.querySelector("."+this.options.classNames.highlightedState),w=t.keyCode===u?1:-1,I=void 0;this.canSearch=!1,I=E?(0,l.getAdjacentEl)(E,"[data-option-selectable]",w):this.dropdown.querySelector("[data-option-selectable]"),I&&((0,l.isScrolledIntoView)(I,this.optionList,w)||this._scrollToOption(I,w),this._highlightOption(I)),t.preventDefault()}break;case i:case n:h&&!t.target.value&&"select-one"!==this.passedElement.type&&(this._handleBackspace(d),t.preventDefault())}}}},{key:"_onKeyUp",value:function(t){var e=this;if(t.target===this.input){var i=String.fromCharCode(event.keyCode);if("text"===this.passedElement.type){var n=this.dropdown.classList.contains(this.options.classNames.activeState),s=void 0;if(this.input.value){var o=this.store.getItemsFilteredByActive(),r=!o.some(function(t){return t.value===e.input.value});s=this.options.maxItems&&this.options.maxItems<=this.itemList.children.length?this._getTemplate("notice","Only "+this.options.maxItems+" options can be added."):this.options.allowDuplicates||r?this._getTemplate("notice",'Add "'+this.input.value+'"'):this._getTemplate("notice","Only unique values can be added."),(this.options._regexFilter&&this._regexFilter(this.input.value)||!this.options._regexFilter)&&(this.dropdown.innerHTML=s.outerHTML,this.dropdown.classList.contains(this.options.classNames.activeState)||this.showDropdown())}else n&&this.hideDropdown()}if(this.canSearch&&this.input===document.activeElement){var l=this.store.getOptions(),c=l.some(function(t){return t.active!==!0});if(this.input.value&&l.length&&/[a-zA-Z0-9-_ ]/.test(i)){var d=function(){var t=e.input.value.trim(),i=e.currentValue.trim();if(t.length>=1&&t!==i+" "){var n=e.store.getOptionsFiltedBySelectable(),s=t,o=new u.default(n,{keys:["label","value"],shouldSort:!0,include:"score"}),r=o.search(s);e.currentValue=t,e.highlightPosition=0,e.isSearching=!0,e.store.dispatch((0,a.filterOptions)(r))}};d()}else c&&(this.isSearching=!1,this.store.dispatch((0,a.activateOptions)()))}}}},{key:"_onInput",value:function(t){"select-one"!==this.passedElement.type&&(this.input.style.width=(0,l.getWidthOfInput)(this.input))}},{key:"_onMouseDown",value:function(t){var e=this;if(2!==t.button){var i=this.store.getItemsFilteredByActive();if(this.containerOuter.contains(t.target))!function(){t.preventDefault();var n=!!t.shiftKey;"text"===e.passedElement.type||e.dropdown.classList.contains(e.options.classNames.activeState)||e.showDropdown(),e.input!==document.activeElement&&e.input.focus(),t.target.hasAttribute("data-button")?e.options.removeItems&&e.options.removeButton&&!function(){var n=t.target.parentNode.getAttribute("data-id"),s=i.find(function(t){return t.id===parseInt(n)});e.removeItem(s)}():t.target.hasAttribute("data-item")?e.options.removeItems&&!function(){var s=t.target.getAttribute("data-id");i.forEach(function(t){t.id!==parseInt(s)||t.selected?n||e.deselectItem(t):e.selectItem(t)})}():t.target.hasAttribute("data-option")&&!function(){var i=e.store.getOptionsFilteredByActive(),n=t.target.getAttribute("data-id"),s=i.find(function(t){return t.id===parseInt(n)});s.selected||s.disabled||(e.addItem(s.value,s.label,s.id),"select-one"===e.passedElement.type&&(e.input.value="",e.isSearching=!1,e.store.dispatch((0,a.activateOptions)(!0)),e.toggleDropdown()))}()}();else{var n=this.dropdown.classList.contains(this.options.classNames.activeState),s=i.some(function(t){return t.selected===!0});s&&this.deselectAll(),this.containerOuter.classList.remove(this.options.classNames.focusState),n&&this.toggleDropdown()}}}},{key:"_onMouseOver",value:function(t){(t.target===this.dropdown||(0,l.findAncestor)(t.target,this.options.classNames.listDropdown))&&t.target.hasAttribute("data-option")&&this._highlightOption(t.target)}},{key:"_onPaste",value:function(t){t.target===this.input&&(this.options.allowPaste||t.preventDefault())}},{key:"_onFocus",value:function(t){var e=this.dropdown.classList.contains(this.options.classNames.activeState);t.target!==this.input||e||(this.containerOuter.classList.add(this.options.classNames.focusState),"select-one"!==this.passedElement.type&&"select-multiple"!==this.passedElement.type||this.showDropdown())}},{key:"_onBlur",value:function(t){var e=this.dropdown.classList.contains(this.options.classNames.activeState);t.target!==this.input||e?this.hideDropdown():this.containerOuter.classList.remove(this.options.classNames.focusState)}},{key:"_regexFilter",value:function(t){if(t){var e=new RegExp(this.options._regexFilter,"i");return e.test(t)}}},{key:"_scrollToOption",value:function(t,e){var i=this;if(t){var n=this.optionList.offsetHeight,s=t.offsetHeight,o=t.offsetTop+s,r=this.optionList.scrollTop+n,a=e>0?this.optionList.scrollTop+o-r:t.offsetTop,l=function c(t,e,n){var s=!1,o=void 0,r=void 0,a=4;n>0?(o=(e-i.optionList.scrollTop)/a,r=o>1?o:1,i.optionList.scrollTop=i.optionList.scrollTop+r,i.optionList.scrollTop1?o:1,i.optionList.scrollTop=i.optionList.scrollTop-r,i.optionList.scrollTop>e&&(s=!0)),s&&requestAnimationFrame(function(t){c(t,e,n)})};requestAnimationFrame(function(t){l(t,a,e)})}}},{key:"_highlightOption",value:function(t){var e=this,i=Array.from(this.dropdown.querySelectorAll("[data-option-selectable]"));if(i.length){var n=Array.from(this.dropdown.querySelectorAll("."+this.options.classNames.highlightedState));if(n.forEach(function(t){t.classList.remove(e.options.classNames.highlightedState)}),t)t.classList.add(this.options.classNames.highlightedState),this.highlightPosition=i.indexOf(t);else{var s=void 0;s=i.length>this.highlightPosition?i[this.highlightPosition]:i[i.length-1],s||(s=i[0]),s.classList.add(this.options.classNames.highlightedState)}}}},{key:"_addOption",value:function(t,e,i,n){var s=arguments.length<=4||void 0===arguments[4]?-1:arguments[4];if(i){n||(n=i);var o=this.store.getOptions(),r=o.length+1;this.store.dispatch((0,a.addOption)(i,n,r,s,e)),t&&!e&&this.addItem(i,n,r)}}},{key:"_addGroup",value:function(t,e,i){var n=this,s=Array.from(t.getElementsByTagName("OPTION")),o=e;s?(this.store.dispatch((0,a.addGroup)(t.label,o,!0,t.disabled)),s.forEach(function(t,e){var i=t.disabled||t.parentNode.disabled;n._addOption(t.selected,i,t.value,t.innerHTML,o)})):this.store.dispatch((0,a.addGroup)(t.label,t.id,!1,t.disabled))}},{key:"_getTemplate",value:function(t){if(t){for(var e=this.options.templates,i=arguments.length,n=Array(i>1?i-1:0),s=1;i>s;s++)n[s-1]=arguments[s];return e[t].apply(e,n)}}},{key:"_createTemplates",value:function(){var t=this,e=this.options.classNames,i={containerOuter:function(){return(0,l.strToEl)('
')},containerInner:function(){return(0,l.strToEl)('
')},itemList:function(){return(0,l.strToEl)('
')},optionList:function(){return(0,l.strToEl)('
')},input:function(){return(0,l.strToEl)('')},dropdown:function(){return(0,l.strToEl)('
')},notice:function(t,i){return(0,l.strToEl)('
'+t+"
")},selectOption:function(t){return(0,l.strToEl)('")},option:function(t){return(0,l.strToEl)('\n
\n '+t.label+"\n
\n ")},optgroup:function(t){return(0,l.strToEl)('\n
\n
'+t.value+"
\n
\n ")},item:function(i){return t.options.removeButton?(0,l.strToEl)('\n
\n '+i.label+'\n \n
\n '):(0,l.strToEl)('\n
\n '+i.label+"\n
\n ")}};this.options.templates=(0,l.extend)(this.options.templates,i)}},{key:"_createInput",value:function(){var t=this,e=this._getTemplate("containerOuter"),i=this._getTemplate("containerInner"),n=this._getTemplate("itemList"),s=this._getTemplate("optionList"),o=this._getTemplate("input"),r=this._getTemplate("dropdown");if(this.containerOuter=e,this.containerInner=i,this.input=o,this.optionList=s,this.itemList=n,this.dropdown=r,this.passedElement.classList.add(this.options.classNames.input,this.options.classNames.hiddenState),this.passedElement.tabIndex="-1",this.passedElement.setAttribute("style","display:none;"),this.passedElement.setAttribute("aria-hidden","true"),this.passedElement.removeAttribute("data-choice"),(0,l.wrap)(this.passedElement,i),(0,l.wrap)(i,e),this.options.placeholder&&(this.options.placeholderValue||this.passedElement.placeholder)){var a=this.options.placeholderValue||this.passedElement.placeholder;o.placeholder=a,"select-one"!==this.passedElement.type&&(o.style.width=(0,l.getWidthOfInput)(o))}if(this.options.addItems||this.disable(),e.appendChild(i),e.appendChild(r),i.appendChild(n),r.appendChild(s),"select-multiple"===this.passedElement.type||"text"===this.passedElement.type?i.appendChild(o):this.options.allowSearch&&r.insertBefore(o,r.firstChild),"select-multiple"===this.passedElement.type||"select-one"===this.passedElement.type){this.highlightPosition=0;var c=Array.from(this.passedElement.getElementsByTagName("OPTGROUP"));if(this.isSearching=!1,c&&c.length)c.forEach(function(e,i){var n=0===i;t._addGroup(e,i,n)});else{var u=Array.from(this.passedElement.options);u.forEach(function(e){var i=e.disabled||e.parentNode.disabled;t._addOption(e.selected,i,e.value,e.innerHTML)})}}else"text"===this.passedElement.type&&this.presetItems.forEach(function(e){if((0,l.isType)("Object",e)){if(!e.value)return;t.addItem(e.value,e.label,e.id)}else(0,l.isType)("String",e)&&t.addItem(e)})}},{key:"_renderGroups",value:function(t,e,i){var n=this,s=i||document.createDocumentFragment();return t.forEach(function(t,i){var o=e.filter(function(e){return"select-one"===n.passedElement.type?e.groupId===t.id:e.groupId===t.id&&!e.selected});if(o.length>=1){var r=n._getTemplate("optgroup",t);s.appendChild(r),n._renderOptions(o,s)}}),s}},{key:"_renderOptions",value:function(t,e){var i=this,n=e||document.createDocumentFragment();return t.forEach(function(t,e){var s=i._getTemplate("option",t);"select-one"===i.passedElement.type?n.appendChild(s):t.selected||n.appendChild(s)}),n}},{key:"_renderItems",value:function(t,e){var i=this,n=e||document.createDocumentFragment(),s=this.store.getItemsReducedToValues(t);return"text"===this.passedElement.type?this.passedElement.setAttribute("value",s.join(this.options.delimiter)):!function(){var e=document.createDocumentFragment();t.forEach(function(t){var n=i._getTemplate("selectOption",t);e.appendChild(n)}),i.passedElement.innerHTML="",i.passedElement.appendChild(e)}(),t.forEach(function(t){var e=i._getTemplate("item",t);n.appendChild(e)}),n}},{key:"_render",value:function(){if(this.currentState=this.store.getState(),this.currentState!==this.prevState){if(!(this.currentState.options===this.prevState.options&&this.currentState.groups===this.prevState.groups||"select-multiple"!==this.passedElement.type&&"select-one"!==this.passedElement.type)){var t=this.store.getGroupsFilteredByActive(),e=this.store.getOptionsFilteredByActive(),i=document.createDocumentFragment();if(this.optionList.innerHTML="",t.length>=1&&this.isSearching!==!0?i=this._renderGroups(t,e,i):e.length>=1&&(i=this._renderOptions(e,i)),i.children.length)this.optionList.appendChild(i),this._highlightOption();else{var n=this.isSearching?this._getTemplate("notice","No results found"):this._getTemplate("notice","No options to select");this.optionList.appendChild(n)}}if(this.currentState.items!==this.prevState.items){var s=this.store.getItemsFilteredByActive();if(s){var o=this._renderItems(s);this.itemList.innerHTML="",o.children.length&&this.itemList.appendChild(o)}}this.prevState=this.currentState}}},{key:"_addEventListeners",value:function(){document.addEventListener("keyup",this._onKeyUp),document.addEventListener("keydown",this._onKeyDown),document.addEventListener("mousedown",this._onMouseDown),document.addEventListener("mouseover",this._onMouseOver),this.input.addEventListener("input",this._onInput),this.input.addEventListener("paste",this._onPaste),this.input.addEventListener("focus",this._onFocus),this.input.addEventListener("blur",this._onBlur)}},{key:"_removeEventListeners",value:function(){document.removeEventListener("keyup",this._onKeyUp),document.removeEventListener("keydown",this._onKeyDown),document.removeEventListener("mousedown",this._onMouseDown),document.removeEventListener("mouseover",this._onMouseOver),this.input.removeEventListener("input",this._onInput),this.input.removeEventListener("paste",this._onPaste),this.input.removeEventListener("focus",this._onFocus),this.input.removeEventListener("blur",this._onBlur)}}]),t}();window.Choices=t.exports=p},function(t,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0});e.addItem=function(t,e,i,n){return{type:"ADD_ITEM",value:t,label:e,id:i,optionId:n}},e.removeItem=function(t,e){return{type:"REMOVE_ITEM",id:t,optionId:e}},e.selectItem=function(t,e){return{type:"SELECT_ITEM",id:t,selected:e}},e.addOption=function(t,e,i,n,s){return{type:"ADD_OPTION",value:t,label:e,id:i,groupId:n,disabled:s}},e.filterOptions=function(t){return{type:"FILTER_OPTIONS",results:t}},e.activateOptions=function(){var t=arguments.length<=0||void 0===arguments[0]?!0:arguments[0];return{type:"ACTIVATE_OPTIONS",active:t}},e.addGroup=function(t,e,i,n){return{type:"ADD_GROUP",value:t,id:e,active:i,disabled:n}},e.clearAll=function(){return{type:"CLEAR_ALL"}}},function(t,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var i=(e.hasClass=function(t,e){return new RegExp(" "+e+" ").test(" "+t.className+" ")},e.capitalise=function(t){return t.replace(/\w\S*/g,function(t){return t.charAt(0).toUpperCase()+t.substr(1).toLowerCase()})},e.isType=function(t,e){var i=Object.prototype.toString.call(e).slice(8,-1);return void 0!==e&&null!==e&&i===t}),n=(e.extend=function o(){for(var t={},e=!1,n=arguments.length,s=function(n){for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(e&&i("Object",n[s])?t[s]=o(!0,t[s],n[s]):t[s]=n[s])},r=0;n>r;r++){var a=arguments[r];i("Object",a)?s(a):console.error("Custom options must be an object")}return t},e.whichTransitionEvent=function(){var t,e=document.createElement("fakeelement"),i={transition:"transitionend",OTransition:"oTransitionEnd",MozTransition:"transitionend",WebkitTransition:"webkitTransitionEnd"};for(t in i)if(void 0!==e.style[t])return i[t]},e.whichAnimationEvent=function(){var t,e=document.createElement("fakeelement"),i={animation:"animationend",OAnimation:"oAnimationEnd",MozAnimation:"animationend",WebkitAnimation:"webkitAnimationEnd"};for(t in i)if(void 0!==e.style[t])return i[t]}),s=(e.getParentsUntil=function(t,e,i){for(var n=[];t&&t!==document;t=t.parentNode){if(e){var s=e.charAt(0);if("."===s&&t.classList.contains(e.substr(1)))break;if("#"===s&&t.id===e.substr(1))break;if("["===s&&t.hasAttribute(e.substr(1,e.length-1)))break;if(t.tagName.toLowerCase()===e)break}if(i){var o=i.charAt(0);"."===o&&t.classList.contains(i.substr(1))&&n.push(t),"#"===o&&t.id===i.substr(1)&&n.push(t),"["===o&&t.hasAttribute(i.substr(1,i.length-1))&&n.push(t),t.tagName.toLowerCase()===i&&n.push(t)}else n.push(t)}return 0===n.length?null:n},e.wrap=function(t,e){return e=e||document.createElement("div"),t.nextSibling?t.parentNode.insertBefore(e,t.nextSibling):t.parentNode.appendChild(e),e.appendChild(t)},e.getSiblings=function(t){for(var e=[],i=t.parentNode.firstChild;i;i=i.nextSibling)1===i.nodeType&&i!==t&&e.push(i);return e},e.findAncestor=function(t,e){for(;(t=t.parentElement)&&!t.classList.contains(e););return t},e.debounce=function(t,e,i){var n;return function(){var s=this,o=arguments,r=function(){n=null,i||t.apply(s,o)},a=i&&!n;clearTimeout(n),n=setTimeout(r,e),a&&t.apply(s,o)}},e.getElemDistance=function(t){var e=0;if(t.offsetParent)do e+=t.offsetTop,t=t.offsetParent;while(t);return e>=0?e:0},e.getElementOffset=function(t,e){var i=e;return i>1&&(i=1),i>0&&(i=0),Math.max(t.offsetHeight*i)},e.getAdjacentEl=function(t,e){var i=arguments.length<=2||void 0===arguments[2]?1:arguments[2];if(t&&e){var n=t.parentNode.parentNode,s=Array.from(n.querySelectorAll(e)),o=s.indexOf(t),r=i>0?1:-1;return s[o+r]}},e.getScrollPosition=function(t){return"bottom"===t?Math.max((window.scrollY||window.pageYOffset)+(window.innerHeight||document.documentElement.clientHeight)):window.scrollY||window.pageYOffset},e.isInView=function(t,e,i){return this.getScrollPosition(e)>this.getElemDistance(t)+this.getElementOffset(t,i)},e.isScrolledIntoView=function(t,e){var i=arguments.length<=2||void 0===arguments[2]?1:arguments[2];if(t){var n=void 0;return n=i>0?e.scrollTop+e.offsetHeight>=t.offsetTop+t.offsetHeight:t.offsetTop>=e.scrollTop}},e.stripHTML=function(t){var e=document.createElement("DIV");return e.innerHTML=t,e.textContent||e.innerText||""},e.addAnimation=function(t,e){var i=n(),s=function o(){t.classList.remove(e),t.removeEventListener(i,o,!1)};t.classList.add(e),t.addEventListener(i,s,!1)},e.getRandomNumber=function(t,e){return Math.floor(Math.random()*(e-t)+t)},e.strToEl=function(){var t=document.createElement("div");return function(e){var i;for(t.innerHTML=e,i=t.children[0];t.firstChild;)t.removeChild(t.firstChild);return i}}());e.getWidthOfInput=function(t){var e=t.value||t.placeholder,i=t.offsetWidth;if(e){var n=s(""+e+"");n.style.position="absolute",n.style.padding="0",n.style.top="-9999px",n.style.left="-9999px",n.style.width="auto",n.style.whiteSpace="pre",document.body.appendChild(n),e&&n.offsetWidth!==t.offsetWidth&&(i=n.offsetWidth+4),document.body.removeChild(n)}return i+"px"}},function(t,e,i){!function(e){"use strict";function i(){console.log.apply(console,arguments)}function n(t,e){var i,n,s,o;for(this.list=t,this.options=e=e||{},i=0,o=["sort","shouldSort","verbose","tokenize"],n=o.length;n>i;i++)s=o[i],this.options[s]=s in e?e[s]:l[s];for(i=0,o=["searchFn","sortFn","keys","getFn","include"],n=o.length;n>i;i++)s=o[i],this.options[s]=e[s]||l[s]}function s(t,e,i){var n,r,a,l,c,u;if(e){if(a=e.indexOf("."),-1!==a?(n=e.slice(0,a),r=e.slice(a+1)):n=e,l=t[n],null!==l&&void 0!==l)if(r||"string"!=typeof l&&"number"!=typeof l)if(o(l))for(c=0,u=l.length;u>c;c++)s(l[c],r,i);else r&&s(l,r,i);else i.push(l)}else i.push(t);return i}function o(t){return"[object Array]"===Object.prototype.toString.call(t)}function r(t,e){e=e||{},this.options=e,this.options.location=e.location||r.defaultOptions.location,this.options.distance="distance"in e?e.distance:r.defaultOptions.distance,this.options.threshold="threshold"in e?e.threshold:r.defaultOptions.threshold,this.options.maxPatternLength=e.maxPatternLength||r.defaultOptions.maxPatternLength,this.pattern=e.caseSensitive?t:t.toLowerCase(),this.patternLen=t.length,this.patternLen<=this.options.maxPatternLength&&(this.matchmask=1<s;s++)this.tokenSearchers.push(new i(n[s],t));this.fullSeacher=new i(e,t)},n.prototype._startSearch=function(){var t,e,i,n,s=this.options,o=s.getFn,r=this.list,a=r.length,l=this.options.keys,c=l.length,u=null;if("string"==typeof r[0])for(i=0;a>i;i++)this._analyze("",r[i],i,i);else for(this._keyMap={},i=0;a>i;i++)for(u=r[i],n=0;c>n;n++){if(t=l[n],"string"!=typeof t){if(e=1-t.weight||1,this._keyMap[t.name]={weight:e},t.weight<=0||t.weight>1)throw new Error("Key weight has to be > 0 and <= 1");t=t.name}else this._keyMap[t]={weight:1};this._analyze(t,o(u,t,[]),u,i)}},n.prototype._analyze=function(t,e,n,s){var r,l,c,u,d,h,p,f,v,m,g,y,b,_,E,w=this.options,I=!1;if(void 0!==e&&null!==e)if(l=[],"string"==typeof e){if(r=e.split(a),w.verbose&&i("---------\nKey:",t),w.verbose&&i("Record:",r),this.options.tokenize){for(c=this.tokenSearchers,u=c.length,_=0;__;_++)h+=l[_];h/=f,w.verbose&&i("Token score average:",h)}v=this.fullSeacher.search(e),w.verbose&&i("Full text score:",v.score),p=v.score,void 0!==h&&(p=(p+h)/2),w.verbose&&i("Score average:",p),(I||v.isMatch)&&(d=this.resultMap[s],d?d.output.push({key:t,score:p,matchedIndices:v.matchedIndices}):(this.resultMap[s]={item:n,output:[{key:t,score:p,matchedIndices:v.matchedIndices}]},this.results.push(this.resultMap[s])))}else if(o(e))for(_=0;_e;e++)r=s[e].score,a=u?u[s[e].key].weight:1,c=r*a,1!==a?l=Math.min(l,c):(n+=c,s[e].nScore=c);1===l?d[t].score=n/o:d[t].score=l,this.options.verbose&&i(d[t])}},n.prototype._sort=function(){var t=this.options;t.shouldSort&&(t.verbose&&i("\n\nSorting...."),this.results.sort(t.sortFn))},n.prototype._format=function(){var t,e,n,s,o,r=this.options,a=r.getFn,l=[],c=this.results,u=r.include;for(r.verbose&&i("\n\nOutput:\n\n",c),s=r.id?function(t){c[t].item=a(c[t].item,r.id,[])[0]}:function(){},o=function(t){var e,i,n,s,o,r=c[t];if(u.length>0){if(e={item:r.item},-1!==u.indexOf("matches"))for(n=r.output,e.matches=[],i=0;ie;e++)s(e),t=o(e),l.push(t);return l},r.defaultOptions={location:0,distance:100,threshold:.6,maxPatternLength:32},r.prototype._calculatePatternAlphabet=function(){var t={},e=0;for(e=0;eS.maxPatternLength){if(y=t.match(new RegExp(this.pattern.replace(a,"|"))),b=!!y)for(E=[],e=0,w=y.length;w>e;e++)I=y[e],E.push([t.indexOf(I),I.length-1]);return{isMatch:b,score:b?.5:1,matchedIndices:E}}for(s=S.location,n=t.length,o=S.threshold,r=t.indexOf(this.pattern,s),_=[],e=0;n>e;e++)_[e]=0;for(-1!=r&&(o=Math.min(this._bitapScore(0,r),o),r=t.lastIndexOf(this.pattern,s+this.patternLen),-1!=r&&(o=Math.min(this._bitapScore(0,r),o))),r=-1,m=1,g=[],u=this.patternLen+n,e=0;el;)this._bitapScore(e,s+c)<=o?l=c:u=c,c=Math.floor((u-l)/2+l);for(u=c,d=Math.max(1,s-c+1),h=Math.min(s+c,n)+this.patternLen,p=Array(h+2),p[h+1]=(1<=d;i--)if(v=this.patternAlphabet[t.charAt(i-1)],v&&(_[i-1]=1),0===e?p[i]=(p[i+1]<<1|1)&v:p[i]=(p[i+1]<<1|1)&v|((f[i+1]|f[i])<<1|1)|f[i+1],p[i]&this.matchmask&&(m=this._bitapScore(e,i-1),o>=m)){if(o=m,r=i-1,g.push(r),!(r>s))break;d=Math.max(1,2*s-r)}if(this._bitapScore(e+1,s)>o)break;f=p}return E=this._getMatchedIndices(_),{isMatch:r>=0,score:0===m?.001:m,matchedIndices:E}},r.prototype._getMatchedIndices=function(t){for(var e,i=[],n=-1,s=-1,o=0,r=r=t.length;r>o;o++)e=t[o],e&&-1===n?n=o:e||-1===n||(s=o-1,i.push([n,s]),n=-1);return t[o-1]&&i.push([n,o-1]),i},t.exports=n}(this)},function(t,e,i){"use strict";function n(t){return t&&t.__esModule?t:{"default":t}}function s(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(e,"__esModule",{value:!0}),e.Store=void 0;var o=function(){function t(t,e){for(var i=0;ii;i++)e[i]=arguments[i];return function(t){return function(i,n,s){var r=t(i,n,s),l=r.dispatch,c=[],u={getState:r.getState,dispatch:function(t){return l(t)}};return c=e.map(function(t){return t(u)}),l=a.default.apply(void 0,c)(r.dispatch),o({},r,{dispatch:l})}}}e.__esModule=!0;var o=Object.assign||function(t){for(var e=1;ei;i++)e[i]=arguments[i];if(0===e.length)return function(t){return t};var n=function(){var t=e[e.length-1],i=e.slice(0,-1);return{v:function(){return i.reduceRight(function(t,e){return e(t)},t.apply(void 0,arguments))}}}();return"object"==typeof n?n.v:void 0}e.__esModule=!0,e.default=i},function(t,e,i){"use strict";function n(t){return t&&t.__esModule?t:{"default":t}}Object.defineProperty(e,"__esModule",{value:!0});var s=i(6),o=i(20),r=n(o),a=i(21),l=n(a),c=i(22),u=n(c),d=(0,s.combineReducers)({items:r.default,groups:l.default,options:u.default}),h=function(t,e){return"CLEAR_ALL"===e.type&&(t=void 0),d(t,e)};e.default=h},function(t,e){"use strict";function i(t){if(Array.isArray(t)){for(var e=0,i=Array(t.length);e-1?t.map(function(t){return t.id===parseInt(e.optionId)&&(t.selected=!0),t}):t;case"REMOVE_ITEM":return e.optionId>-1?t.map(function(t){return t.id===parseInt(e.optionId)&&(t.selected=!1),t}):t;case"FILTER_OPTIONS":var n=e.results,s=t.map(function(t,e){return t.active=n.some(function(e){return e.item.id===t.id?(t.score=e.score,!0):void 0}),t}).sort(function(t,e){return t.score-e.score});return s;case"ACTIVATE_OPTIONS":return t.map(function(t){return t.active=e.active,t});default:return t}};e.default=n}]); \ No newline at end of file diff --git a/assets/scripts/src/actions/index.js b/assets/scripts/src/actions/index.js index 73a68cc..bcff521 100644 --- a/assets/scripts/src/actions/index.js +++ b/assets/scripts/src/actions/index.js @@ -57,4 +57,10 @@ export const addGroup = (value, id, active, disabled) => { active, disabled, } +}; + +export const clearAll = () => { + return { + type: 'CLEAR_ALL', + } }; \ No newline at end of file diff --git a/assets/scripts/src/choices.js b/assets/scripts/src/choices.js index 2e05f52..afb140e 100644 --- a/assets/scripts/src/choices.js +++ b/assets/scripts/src/choices.js @@ -1,6 +1,6 @@ 'use strict'; -import { addItem, removeItem, selectItem, addOption, filterOptions, activateOptions, addGroup } from './actions/index'; +import { addItem, removeItem, selectItem, addOption, filterOptions, activateOptions, addGroup, clearAll } from './actions/index'; import { isScrolledIntoView, getAdjacentEl, findAncestor, wrap, isType, strToEl, extend, getWidthOfInput, debounce } from './lib/utils.js'; import Fuse from 'fuse.js'; import Store from './store/index.js'; @@ -38,7 +38,7 @@ export class Choices { allowDuplicates: true, allowPaste: true, allowSearch: true, - regexFilter: false, + _regexFilter: false, placeholder: true, placeholderValue: '', prependValue: false, @@ -80,7 +80,7 @@ export class Choices { this.options = extend(defaultOptions, userOptions); // Create data store - this.store = new Store(this.render); + this.store = new Store(this._render); // State tracking this.initialised = false; @@ -103,27 +103,26 @@ export class Choices { // Bind methods this.init = this.init.bind(this); - this.render = this.render.bind(this); + this._render = this._render.bind(this); this.destroy = this.destroy.bind(this); this.disable = this.disable.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.onMouseDown = this.onMouseDown.bind(this); - this.onMouseOver = this.onMouseOver.bind(this); - this.onPaste = this.onPaste.bind(this); - this.onInput = this.onInput.bind(this); + 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._onMouseDown = this._onMouseDown.bind(this); + this._onMouseOver = this._onMouseOver.bind(this); + this._onPaste = this._onPaste.bind(this); + this._onInput = this._onInput.bind(this); // Cutting the mustard const cuttingTheMustard = 'querySelector' in document && 'addEventListener' in document && 'classList' in document.createElement("div"); if (!cuttingTheMustard) console.error('Choices: Your browser doesn\'t support Choices'); // Input type check - const inputTypes = ['select-one', 'select-multiple', 'text']; - const canInit = this.passedElement && inputTypes.includes(this.passedElement.type); + const canInit = this.passedElement && ['select-one', 'select-multiple', 'text'].includes(this.passedElement.type); if(canInit) { // Let's have it large @@ -132,13 +131,408 @@ export class Choices { console.error('Choices: Incompatible input passed'); } } + + /** + * Initialise Choices + * @return + * @public + */ + init(callback) { + if(this.initialised !== true) { + + this.initialised = true; + + // Create required elements + this._createTemplates(); + + // Generate input markup + this._createInput(); + + this.store.subscribe(this._render); + + // Render any items + this._render(); + + // Trigger event listeners + this._addEventListeners(); + + // Run callback if it is a function + if(callback = this.options.callbackOnInit){ + if(isType('Function', callback)) { + callback(); + } else { + console.error('callbackOnInit: Callback is not a function'); + } + } + } + } + /** + * Destroy Choices and nullify values + * @return + * @public + */ + destroy() { + this.passedElement.classList.remove(this.options.classNames.input, this.options.classNames.hiddenState); + this.passedElement.tabIndex = ''; + this.passedElement.removeAttribute('style', 'display:none;'); + this.passedElement.removeAttribute('aria-hidden'); + + this.containerOuter.outerHTML = this.passedElement.outerHTML; + + this.passedElement = null; + this.userOptions = null; + this.options = null; + this.store = null; + + this._removeEventListeners(); + } + + /** + * Select item (a selected item can be deleted) + * @param {Element} item Element to select + * @return {Object} Class instance + * @public + */ + selectItem(item) { + if(!item) return; + const id = item.id; + this.store.dispatch(selectItem(id, true)); + + return this; + } + + /** + * Deselect item + * @param {Element} item Element to de-select + * @return {Object} Class instance + * @public + */ + deselectItem(item) { + if(!item) return; + const id = item.id; + this.store.dispatch(selectItem(id, false)); + + return this; + } + + /** + * Select items within store + * @return {Object} Class instance + * @public + */ + selectAll() { + const items = this.store.getItems(); + items.forEach((item) => { + this.selectItem(item); + }); + + return this; + } + + /** + * Deselect items within store + * @return {Object} Class instance + * @public + */ + deselectAll() { + const items = this.store.getItems(); + items.forEach((item) => { + this.deselectItem(item); + }); + + return this; + } + + /** + * Add item to store with correct value + * @param {String} value Value to add to store + * @return {Object} Class instance + * @public + */ + addItem(value, label, optionId = -1, callback = this.options.callbackOnAddItem) { + const items = this.store.getItems(); + let passedValue = value.trim(); + let passedLabel = label || passedValue; + let passedOptionId = optionId || -1; + + // If a prepended value has been passed, prepend it + if(this.options.prependValue) { + passedValue = this.options.prependValue + passedValue.toString(); + } + + // If an appended value has been passed, append it + if(this.options.appendValue) { + passedValue = passedValue + this.options.appendValue.toString(); + } + + // Generate unique id + const id = items ? items.length + 1 : 1; + + this.store.dispatch(addItem(passedValue, passedLabel, id, passedOptionId)); + + if(this.passedElement.type === 'select-one') { + this.removeActiveItems(id); + } + + // Run callback if it is a function + if(callback){ + if(isType('Function', callback)) { + callback(id, passedValue, this.passedElement); + } else { + console.error('callbackOnAddItem: Callback is not a function'); + } + } + + return this; + } + + /** + * Remove item from store + * @param + * @return {Object} Class instance + * @public + */ + removeItem(item, callback = this.options.callbackOnRemoveItem) { + if(!item || !isType('Object', item)) { + console.error('removeItem: No item object was passed to be removed'); + return; + } + + const id = item.id; + const value = item.value; + const optionId = item.optionId; + + this.store.dispatch(removeItem(id, optionId)); + + // Run callback + if(callback){ + if(!isType('Function', callback)) console.error('callbackOnRemoveItem: Callback is not a function'); return; + callback(id, value, this.passedElement); + } + + return this; + } + + /** + * Remove an item from the store by its value + * @param {String} value Value to search for + * @return {Object} Class instance + * @public + */ + removeItemsByValue(value) { + if(!value || !isType('String', value)) console.error('removeItemsByValue: No value was passed to be removed'); return; + + const items = this.store.getItemsFilteredByActive(); + + items.forEach((item) => { + if(item.value === value) { + this.removeItem(item); + } + }); + + return this; + } + + /** + * Remove all items from store array + * Note: removed items are soft deleted + * @param {Boolean} selectedOnly Optionally remove only selected items + * @return {Object} Class instance + * @public + */ + removeActiveItems(excludedId) { + const items = this.store.getItemsFilteredByActive(); + + items.forEach((item) => { + if(item.active && excludedId !== item.id) { + this.removeItem(item); + } + }); + + return this; + } + + /** + * Remove all selected items from store + * Note: removed items are soft deleted + * @return {Object} Class instance + * @public + */ + removeSelectedItems() { + const items = this.store.getItemsFilteredByActive(); + + items.forEach((item) => { + if(item.selected && item.active) { + this.removeItem(item); + } + }); + + return this; + } + + /** + * Show dropdown to user by adding active state class + * @return {Object} Class instance + * @public + */ + showDropdown() { + this.containerOuter.classList.add(this.options.classNames.openState); + this.dropdown.classList.add(this.options.classNames.activeState); + + const dimensions = this.dropdown.getBoundingClientRect(); + const shouldFlip = dimensions.top + dimensions.height >= document.body.offsetHeight; + + // Whether or not the dropdown should appear above or below input + if(shouldFlip) { + this.containerOuter.classList.add(this.options.classNames.flippedState); + } else { + this.containerOuter.classList.remove(this.options.classNames.flippedState); + } + + return this; + } + + /** + * Hide dropdown from user + * @return {Object} Class instance + * @public + */ + hideDropdown() { + // A dropdown flips if it does not have space below the input + const isFlipped = this.containerOuter.classList.contains(this.options.classNames.flippedState); + + this.containerOuter.classList.remove(this.options.classNames.openState); + this.dropdown.classList.remove(this.options.classNames.activeState); + + if(isFlipped) { + this.containerOuter.classList.remove(this.options.classNames.flippedState); + } + + return this; + } + + /** + * Determine whether to hide or show dropdown based on its current state + * @return {Object} Class instance + * @public + */ + toggleDropdown() { + const isActive = this.dropdown.classList.contains(this.options.classNames.activeState); + + isActive ? this.hideDropdown() : this.showDropdown(); + + return this; + } + + /** + * Set value of input + * @param {Array} args Array of value objects or value strings + * @return {Object} Class instance + * @public + */ + setValue(args) { + // Convert args to an itterable array + const values = [...args]; + + values.forEach((item, index) => { + if(isType('Object', item)) { + 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(this.passedElement.type !== 'text') { + this._addOption(true, false, item.value, item.label, -1); + } else { + this.addItem(item.value, item.label, item.id); + } + } else if(isType('String', item)) { + if(this.passedElement.type !== 'text') { + this._addOption(true, false, item, item, -1); + } else { + this.addItem(item); + } + } + }); + + return this; + } + + /** + * Clear value of inputs + * @return {Object} Class instance + * @public + */ + clearValue() { + this.store.dispatch(clearAll()); + return this; + } + + /** + * Disable + * @return {Object} Class instance + * @public + */ + disable() { + this.passedElement.disabled = true; + if(this.initialised) { + this.input.disabled = true; + this.containerOuter.classList.add(this.options.classNames.disabledState); + } + return this; + } + + /** + * Populate options via ajax callback + * @param {Function} fn Passed + * @return {Object} Class instance + * @public + */ + ajax(fn) { + this.containerOuter.classList.add('is-loading'); + // this.input.placeholder = this.options.loadingText; + + const placeholderItem = this._getTemplate('item', { id: -1, value: 'Loading', label: this.options.loadingText, active: true}); + this.itemList.appendChild(placeholderItem); + + const callback = (results, value, label) => { + if(results && results.length) { + this.containerOuter.classList.remove('is-loading'); + this.input.placeholder = ""; + results.forEach((result, index) => { + // Add each result to option dropdown + if(index === 0) { + this.addItem(result[value], result[label], index); + } + this._addOption(false, false, result[value], result[label]); + }); + } + }; + + fn(callback); + return this; + } + + /** + * Set value of input to blank + * @return {Object} Class instance + * @public + */ + clearInput() { + if (this.input.value) this.input.value = ''; + if(this.passedElement.type !== 'select-one') { + this.input.style.width = getWidthOfInput(this.input); + } + + return this; + } + /** * Process enter key event * @param {Array} activeItems Items that are currently active * @return + * @private */ - handleEnter(activeItems, value) { + _handleEnter(activeItems, value) { let canUpdate = true; if(this.options.addItems) { @@ -159,10 +553,10 @@ export class Choices { let canAddItem = true; // If a user has supplied a regular expression filter - if(this.options.regexFilter) { + if(this.options._regexFilter) { // Determine whether we can update based on whether // our regular expression passes - canAddItem = this.regexFilter(value); + canAddItem = this._regexFilter(value); } // All is good, add @@ -178,8 +572,9 @@ export class Choices { * Process back space event * @param {Array} Active items * @return + * @private */ - handleBackspace(activeItems) { + _handleBackspace(activeItems) { if(this.options.removeItems && activeItems) { const lastItem = activeItems[activeItems.length - 1]; const hasSelectedItems = activeItems.some((item) => item.selected === true); @@ -201,7 +596,7 @@ export class Choices { * @param {Object} e Event * @return */ - onKeyDown(e) { + _onKeyDown(e) { if(e.target !== this.input) return; const ctrlDownKey = e.ctrlKey || e.metaKey; @@ -243,7 +638,7 @@ export class Choices { // If enter key is pressed and the input has a value if(e.target.value && this.passedElement.type === 'text') { const value = this.input.value; - this.handleEnter(activeItems, value); + this._handleEnter(activeItems, value); } if(hasActiveDropdown) { @@ -291,9 +686,9 @@ export class Choices { // We prevent default to stop the cursor moving // when pressing the arrow if(!isScrolledIntoView(nextEl, this.optionList, directionInt)) { - this.scrollToOption(nextEl, directionInt); + this._scrollToOption(nextEl, directionInt); } - this.highlightOption(nextEl); + this._highlightOption(nextEl); } // Prevent default to maintain cursor position whilst @@ -306,7 +701,7 @@ export class Choices { case deleteKey: // If backspace or delete key is pressed and the input has no value if(hasFocusedInput && !e.target.value && this.passedElement.type !== 'select-one') { - this.handleBackspace(activeItems); + this._handleBackspace(activeItems); e.preventDefault(); } break; @@ -320,8 +715,9 @@ export class Choices { * Key up event * @param {Object} e Event * @return + * @private */ - onKeyUp(e) { + _onKeyUp(e) { if(e.target !== this.input) return; const keyString = String.fromCharCode(event.keyCode); @@ -335,14 +731,14 @@ export class Choices { const isUnique = !activeItems.some((item) => item.value === this.input.value); if (this.options.maxItems && this.options.maxItems <= this.itemList.children.length) { - dropdownItem = this.getTemplate('notice', `Only ${ this.options.maxItems } options can be added.`); + dropdownItem = this._getTemplate('notice', `Only ${ this.options.maxItems } options can be added.`); } else if(!this.options.allowDuplicates && !isUnique) { - dropdownItem = this.getTemplate('notice', `Only unique values can be added.`); + dropdownItem = this._getTemplate('notice', `Only unique values can be added.`); } else { - dropdownItem = this.getTemplate('notice', `Add "${ this.input.value }"`); + dropdownItem = this._getTemplate('notice', `Add "${ this.input.value }"`); } - if((this.options.regexFilter && this.regexFilter(this.input.value)) || !this.options.regexFilter) { + if((this.options._regexFilter && this._regexFilter(this.input.value)) || !this.options._regexFilter) { this.dropdown.innerHTML = dropdownItem.outerHTML; if(!this.dropdown.classList.contains(this.options.classNames.activeState)) { this.showDropdown(); @@ -397,8 +793,9 @@ export class Choices { * Input event * @param {Object} e Event * @return + * @private */ - onInput(e) { + _onInput(e) { if(this.passedElement.type !== 'select-one') { this.input.style.width = getWidthOfInput(this.input); } @@ -408,8 +805,9 @@ export class Choices { * Click event * @param {Object} e Event * @return + * @private */ - onMouseDown(e) { + _onMouseDown(e) { // If not a right click if(e.button !== 2) { const activeItems = this.store.getItemsFilteredByActive(); @@ -489,13 +887,28 @@ export class Choices { } } + /** + * Mouse over (hover) event + * @param {Object} e Event + * @return + * @private + */ + _onMouseOver(e) { + // If the dropdown is either the target or one of its children is the target + if((e.target === this.dropdown || findAncestor(e.target, this.options.classNames.listDropdown))) { + if(e.target.hasAttribute('data-option')) { + this._highlightOption(e.target); + } + } + } /** * Paste event * @param {Object} e Event * @return + * @private */ - onPaste(e) { + _onPaste(e) { if(e.target !== this.input) return; // Disable pasting into the input if option has been set if(!this.options.allowPaste) { @@ -503,26 +916,14 @@ export class Choices { } } - /** - * Mouse over (hover) event - * @param {Object} e Event - * @return - */ - onMouseOver(e) { - // If the dropdown is either the target or one of its children is the target - if((e.target === this.dropdown || findAncestor(e.target, this.options.classNames.listDropdown))) { - if(e.target.hasAttribute('data-option')) { - this.highlightOption(e.target); - } - } - } /** * Focus event * @param {Object} e Event * @return + * @private */ - onFocus(e) { + _onFocus(e) { const hasActiveDropdown = this.dropdown.classList.contains(this.options.classNames.activeState); if(e.target === this.input && !hasActiveDropdown) { this.containerOuter.classList.add(this.options.classNames.focusState); @@ -536,8 +937,9 @@ export class Choices { * Blur event * @param {Object} e Event * @return + * @private */ - onBlur(e) { + _onBlur(e) { const hasActiveDropdown = this.dropdown.classList.contains(this.options.classNames.activeState); if(e.target === this.input && !hasActiveDropdown) { this.containerOuter.classList.remove(this.options.classNames.focusState); @@ -546,25 +948,16 @@ export class Choices { } } - /** - * Set value of input to blank - * @return - */ - clearInput() { - if (this.input.value) this.input.value = ''; - if(this.passedElement.type !== 'select-one') { - this.input.style.width = getWidthOfInput(this.input); - } - } /** * Tests value against a regular expression * @param {string} value Value to test * @return {Boolean} Whether test passed/failed + * @private */ - regexFilter(value) { + _regexFilter(value) { if(!value) return; - const expression = new RegExp(this.options.regexFilter, 'i'); + const expression = new RegExp(this.options._regexFilter, 'i'); return expression.test(value); } @@ -573,8 +966,9 @@ export class Choices { * @param {HTMLElement} option Option to scroll to * @param {Number} direction Whether option is above or below * @return + * @private */ - scrollToOption(option, direction) { + _scrollToOption(option, direction) { if(!option) return; const dropdownHeight = this.optionList.offsetHeight; @@ -628,8 +1022,9 @@ export class Choices { * Highlight option element * @param {HTMLElement} el Element to highlight * @return + * @private */ - highlightOption(el) { + _highlightOption(el) { // Highlight first element in dropdown const options = Array.from(this.dropdown.querySelectorAll('[data-option-selectable]')); @@ -661,161 +1056,6 @@ export class Choices { el.classList.add(this.options.classNames.highlightedState); } } - - } - - /** - * Select item (a selected item can be deleted) - * @param {Element} item Element to select - * @return - */ - selectItem(item) { - if(!item) return; - const id = item.id; - this.store.dispatch(selectItem(id, true)); - } - - /** - * Deselect item - * @param {Element} item Element to de-select - * @return - */ - deselectItem(item) { - if(!item) return; - const id = item.id; - this.store.dispatch(selectItem(id, false)); - } - - /** - * Select items within store - * @return - */ - selectAll() { - const items = this.store.getItems(); - items.forEach((item) => { - this.selectItem(item); - }); - } - - /** - * Deselect items within store - * @return - */ - deselectAll() { - const items = this.store.getItems(); - items.forEach((item) => { - this.deselectItem(item); - }); - } - - /** - * Add item to store with correct value - * @param {String} value Value to add to store - */ - addItem(value, label, optionId = -1, callback = this.options.callbackOnAddItem) { - const items = this.store.getItems(); - let passedValue = value.trim(); - let passedLabel = label || passedValue; - let passedOptionId = optionId || -1; - - // If a prepended value has been passed, prepend it - if(this.options.prependValue) { - passedValue = this.options.prependValue + passedValue.toString(); - } - - // If an appended value has been passed, append it - if(this.options.appendValue) { - passedValue = passedValue + this.options.appendValue.toString(); - } - - // Generate unique id - const id = items ? items.length + 1 : 1; - - this.store.dispatch(addItem(passedValue, passedLabel, id, passedOptionId)); - - if(this.passedElement.type === 'select-one') { - this.removeActiveItems(id); - } - - // Run callback if it is a function - if(callback){ - if(isType('Function', callback)) { - callback(id, passedValue, this.passedElement); - } else { - console.error('callbackOnAddItem: Callback is not a function'); - } - } - } - - /** - * Remove item from store - * @param - */ - removeItem(item, callback = this.options.callbackOnRemoveItem) { - if(!item || !isType('Object', item)) { - console.error('removeItem: No item object was passed to be removed'); - return; - } - - const id = item.id; - const value = item.value; - const optionId = item.optionId; - - this.store.dispatch(removeItem(id, optionId)); - - // Run callback - if(callback){ - if(!isType('Function', callback)) console.error('callbackOnRemoveItem: Callback is not a function'); return; - callback(id, value, this.passedElement); - } - } - - /** - * Remove an item from the store by its value - * @param {String} value Value to search for - * @return - */ - removeItemsByValue(value) { - if(!value || !isType('String', value)) console.error('removeItemsByValue: No value was passed to be removed'); return; - - const items = this.store.getItemsFilteredByActive(); - - items.forEach((item) => { - if(item.value === value) { - this.removeItem(item); - } - }); - } - - /** - * Remove all items from store array - * Note: removed items are soft deleted - * @param {Boolean} selectedOnly Optionally remove only selected items - * @return - */ - removeActiveItems(excludedId) { - const items = this.store.getItemsFilteredByActive(); - - items.forEach((item) => { - if(item.active && excludedId !== item.id) { - this.removeItem(item); - } - }); - } - - /** - * Remove all selected items from store - * Note: removed items are soft deleted - * @return - */ - removeSelectedItems() { - const items = this.store.getItemsFilteredByActive(); - - items.forEach((item) => { - if(item.selected && item.active) { - this.removeItem(item); - } - }); } /** @@ -823,8 +1063,9 @@ export class Choices { * @param {Object} option Option to add * @param {Number} groupId ID of the options group * @return + * @private */ - addOption(option, value, label, groupId = -1) { + _addOption(isSelected, isDisabled, value, label, groupId = -1) { if(!value) return if(!label) { label = value; } @@ -832,11 +1073,10 @@ export class Choices { // Generate unique id const options = this.store.getOptions(); const id = options.length + 1; - const isDisabled = option && (option.disabled || option.parentNode.disabled); this.store.dispatch(addOption(value, label, id, groupId, isDisabled)); - if(option && option.selected && !isDisabled) { + if(isSelected && !isDisabled) { this.addItem(value, label, id); } } @@ -845,142 +1085,32 @@ export class Choices { * Add group to dropdown * @param {Object} group Group to add * @param {Number} index Whether this is the first group to add + * @return + * @private */ - addGroup(group, id, isFirst) { + _addGroup(group, id, isFirst) { const groupOptions = Array.from(group.getElementsByTagName('OPTION')); const groupId = id; if(groupOptions) { this.store.dispatch(addGroup(group.label, groupId, true, group.disabled)); - groupOptions.forEach((option, optionIndex) => { - // We want to pre-highlight the first option - const highlighted = isFirst && optionIndex === 0 ? true : false; - this.addOption(option, option.value, option.innerHTML, groupId); + const isDisabled = option.disabled || option.parentNode.disabled; + this._addOption(option.selected, isDisabled, option.value, option.innerHTML, groupId); }); } else { this.store.dispatch(addGroup(group.label, group.id, false, group.disabled)); } } - /** - * Show dropdown to user by adding active state class - * @return - */ - showDropdown() { - this.containerOuter.classList.add(this.options.classNames.openState); - this.dropdown.classList.add(this.options.classNames.activeState); - - const dimensions = this.dropdown.getBoundingClientRect(); - const shouldFlip = dimensions.top + dimensions.height >= document.body.offsetHeight; - - // Whether or not the dropdown should appear above or below input - if(shouldFlip) { - this.containerOuter.classList.add(this.options.classNames.flippedState); - } else { - this.containerOuter.classList.remove(this.options.classNames.flippedState); - } - } - - /** - * Hide dropdown from user - * @return {[type]} [description] - */ - hideDropdown() { - // A dropdown flips if it does not have space below the input - const isFlipped = this.containerOuter.classList.contains(this.options.classNames.flippedState); - - this.containerOuter.classList.remove(this.options.classNames.openState); - this.dropdown.classList.remove(this.options.classNames.activeState); - - if(isFlipped) { - this.containerOuter.classList.remove(this.options.classNames.flippedState); - } - } - - /** - * Determine whether to hide or show dropdown based on its current state - * @return - */ - toggleDropdown() { - const isActive = this.dropdown.classList.contains(this.options.classNames.activeState); - - isActive ? this.hideDropdown() : this.showDropdown(); - } - - /** - * Set value of input - * @return - */ - setValue(args) { - const values = [...args]; - - values.forEach((item, index) => { - if(isType('Object', item)) { - if(!item.value) return; - this.addItem(item.value, item.label, item.id); - } else if(isType('String', item)) { - this.addItem(item); - } - }); - } - - /** - * Clear value of inputs - * @return - */ - clearValue() { - - } - - /** - * Disable - * @return {[type]} [description] - */ - disable() { - this.passedElement.disabled = true; - if(this.initialised) { - this.input.disabled = true; - this.containerOuter.classList.add(this.options.classNames.disabledState); - } - } - - /** - * Populate options via ajax callback - * @param {Function} fn Passed - * @return {[type]} [description] - */ - ajax(fn) { - this.containerOuter.classList.add('is-loading'); - // this.input.placeholder = this.options.loadingText; - - const placeholderItem = this.getTemplate('item', { id: -1, value: 'Loading', label: this.options.loadingText, active: true}); - this.itemList.appendChild(placeholderItem); - - const callback = (results, value, label) => { - if(results && results.length) { - this.containerOuter.classList.remove('is-loading'); - this.input.placeholder = ""; - results.forEach((result, index) => { - // Add each result to option dropdown - if(index === 0) { - this.addItem(result[value], result[label], index); - } - this.addOption(null, result[value], result[label]); - }); - } - }; - - fn(callback); - } - /** * Get template from name * @param {String} template Name of template to get * @param {...} args Data to pass to template * @return {HTMLElement} Template + * @private */ - getTemplate(template, ...args) { + _getTemplate(template, ...args) { if(!template) return; const templates = this.options.templates; return templates[template](...args); @@ -989,8 +1119,9 @@ export class Choices { /** * Create HTML element based on type and arguments * @return + * @private */ - createTemplates() { + _createTemplates() { const classNames = this.options.classNames; const templates = { containerOuter: () => { @@ -1055,14 +1186,15 @@ export class Choices { /** * Create DOM structure around passed select element * @return + * @private */ - generateInput() { - const containerOuter = this.getTemplate('containerOuter'); - const containerInner = this.getTemplate('containerInner'); - const itemList = this.getTemplate('itemList'); - const optionList = this.getTemplate('optionList'); - const input = this.getTemplate('input'); - const dropdown = this.getTemplate('dropdown'); + _createInput() { + const containerOuter = this._getTemplate('containerOuter'); + const containerInner = this._getTemplate('containerInner'); + const itemList = this._getTemplate('itemList'); + const optionList = this._getTemplate('optionList'); + const input = this._getTemplate('input'); + const dropdown = this._getTemplate('dropdown'); this.containerOuter = containerOuter; this.containerInner = containerInner; @@ -1116,12 +1248,13 @@ export class Choices { if(passedGroups && passedGroups.length) { passedGroups.forEach((group, index) => { const isFirst = index === 0 ? true : false; - this.addGroup(group, index, isFirst); + this._addGroup(group, index, isFirst); }); } else { const passedOptions = Array.from(this.passedElement.options); passedOptions.forEach((option) => { - this.addOption(option, option.value, option.innerHTML); + const isDisabled = option.disabled || option.parentNode.disabled; + this._addOption(option.selected, isDisabled, option.value, option.innerHTML); }); } @@ -1138,7 +1271,15 @@ export class Choices { } } - renderGroups(groups, options, fragment) { + /** + * Render group options into a DOM fragment and append to options list + * @param {Array} groups Groups to add to list + * @param {Array} options Options to add to groups + * @param {DocumentFragment} fragment Fragment to add groups and options to (optional) + * @return {DocumentFragment} Populated options fragment + * @private + */ + _renderGroups(groups, options, fragment) { const groupFragment = fragment || document.createDocumentFragment(); groups.forEach((group, i) => { @@ -1152,23 +1293,30 @@ export class Choices { }); if(groupOptions.length >= 1) { - const dropdownGroup = this.getTemplate('optgroup', group); + const dropdownGroup = this._getTemplate('optgroup', group); groupFragment.appendChild(dropdownGroup); - this.renderOptions(groupOptions, groupFragment); + this._renderOptions(groupOptions, groupFragment); } }); return groupFragment; } - renderOptions(options, fragment) { + /** + * Render options into a DOM fragment and append to options list + * @param {Array} options Options to add to list + * @param {DocumentFragment} fragment Fragment to add options to (optional) + * @return {DocumentFragment} Populated options fragment + * @private + */ + _renderOptions(options, fragment) { // Create a fragment to store our list items (so we don't have to update the DOM for each item) const optsFragment = fragment || document.createDocumentFragment(); options.forEach((option, i) => { - const dropdownItem = this.getTemplate('option', option); + const dropdownItem = this._getTemplate('option', option); if(this.passedElement.type === 'select-one') { optsFragment.appendChild(dropdownItem); @@ -1180,7 +1328,14 @@ export class Choices { return optsFragment; } - renderItems(items, fragment) { + /** + * Render items into a DOM fragment and append to items list + * @param {Array} items Items to add to list + * @param {DocumentFragment} fragment Fragrment to add items to (optional) + * @return + * @private + */ + _renderItems(items, fragment) { // Create fragment to add elements to const itemListFragment = fragment || document.createDocumentFragment(); // Simplify store data to just values @@ -1195,7 +1350,7 @@ export class Choices { // Add each list item to list items.forEach((item) => { // Create a standard select option - const option = this.getTemplate('selectOption', item); + const option = this._getTemplate('selectOption', item); // Append it to fragment selectedOptionsFragment.appendChild(option); @@ -1209,26 +1364,24 @@ export class Choices { // Add each list item to list items.forEach((item) => { // Create new list element - const listItem = this.getTemplate('item', item); + const listItem = this._getTemplate('item', item); // Append it to list itemListFragment.appendChild(listItem); }); - // Clear list - this.itemList.innerHTML = ''; - - // Update list - this.itemList.appendChild(itemListFragment); + return itemListFragment; } /** * Render DOM with values * @return + * @private */ - render() { + _render() { this.currentState = this.store.getState(); + // Only _render if our state has actually changed if(this.currentState !== this.prevState) { // Options @@ -1237,28 +1390,27 @@ export class Choices { // Get active groups/options const activeGroups = this.store.getGroupsFilteredByActive(); const activeOptions = this.store.getOptionsFilteredByActive(); - - const optListFragment = document.createDocumentFragment(); + + let optListFragment = document.createDocumentFragment(); // Clear options this.optionList.innerHTML = ''; // If we have grouped options if(activeGroups.length >= 1 && this.isSearching !== true) { - this.renderGroups(activeGroups, activeOptions, optListFragment); + optListFragment = this._renderGroups(activeGroups, activeOptions, optListFragment); } else if(activeOptions.length >= 1) { - this.renderOptions(activeOptions, optListFragment); + optListFragment = this._renderOptions(activeOptions, optListFragment); } if(optListFragment.children.length) { // If we actually have anything to add to our dropdown // append it and highlight the first option this.optionList.appendChild(optListFragment); - this.highlightOption(); + this._highlightOption(); } else { // Otherwise show a notice - const dropdownItem = this.isSearching ? this.getTemplate('notice', 'No results found') : this.getTemplate('notice', 'No options to select'); - + const dropdownItem = this.isSearching ? this._getTemplate('notice', 'No results found') : this._getTemplate('notice', 'No options to select'); this.optionList.appendChild(dropdownItem); } } @@ -1269,7 +1421,16 @@ export class Choices { const activeItems = this.store.getItemsFilteredByActive(); if(activeItems) { // Create a fragment to store our list items (so we don't have to update the DOM for each item) - this.renderItems(activeItems); + const itemListFragment = this._renderItems(activeItems); + + // Clear list + this.itemList.innerHTML = ''; + + // If we have items to add + if(itemListFragment.children.length) { + // Update list + this.itemList.appendChild(itemListFragment); + } } } @@ -1280,87 +1441,35 @@ export class Choices { /** * Trigger event listeners * @return + * @private */ - addEventListeners() { - document.addEventListener('keyup', this.onKeyUp); - document.addEventListener('keydown', this.onKeyDown); - document.addEventListener('mousedown', this.onMouseDown); - document.addEventListener('mouseover', this.onMouseOver); + _addEventListeners() { + document.addEventListener('keyup', this._onKeyUp); + document.addEventListener('keydown', this._onKeyDown); + document.addEventListener('mousedown', this._onMouseDown); + document.addEventListener('mouseover', this._onMouseOver); - this.input.addEventListener('input', this.onInput); - this.input.addEventListener('paste', this.onPaste); - this.input.addEventListener('focus', this.onFocus); - this.input.addEventListener('blur', this.onBlur); + this.input.addEventListener('input', this._onInput); + this.input.addEventListener('paste', this._onPaste); + this.input.addEventListener('focus', this._onFocus); + this.input.addEventListener('blur', this._onBlur); } /** * Destroy event listeners * @return + * @private */ - removeEventListeners() { - document.removeEventListener('keyup', this.onKeyUp); - document.removeEventListener('keydown', this.onKeyDown); - document.removeEventListener('mousedown', this.onMouseDown); - document.removeEventListener('mouseover', this.onMouseOver); + _removeEventListeners() { + document.removeEventListener('keyup', this._onKeyUp); + document.removeEventListener('keydown', this._onKeyDown); + document.removeEventListener('mousedown', this._onMouseDown); + document.removeEventListener('mouseover', this._onMouseOver); - this.input.removeEventListener('input', this.onInput); - this.input.removeEventListener('paste', this.onPaste); - this.input.removeEventListener('focus', this.onFocus); - this.input.removeEventListener('blur', this.onBlur); - } - - /** - * Initialise Choices - * @return - */ - init(callback) { - if(this.initialised !== true) { - - this.initialised = true; - - // Create required elements - this.createTemplates(); - - // Generate input markup - this.generateInput(); - - this.store.subscribe(this.render); - - // Render any items - this.render(); - - // Trigger event listeners - this.addEventListeners(); - - // Run callback if it is a function - if(callback = this.options.callbackOnInit){ - if(isType('Function', callback)) { - callback(); - } else { - console.error('callbackOnInit: Callback is not a function'); - } - } - } - } - - /** - * Destroy Choices and nullify values - * @return - */ - destroy() { - this.passedElement.classList.remove(this.options.classNames.input, this.options.classNames.hiddenState); - this.passedElement.tabIndex = ''; - this.passedElement.removeAttribute('style', 'display:none;'); - this.passedElement.removeAttribute('aria-hidden'); - - this.containerOuter.outerHTML = this.passedElement.outerHTML; - - this.passedElement = null; - this.userOptions = null; - this.options = null; - this.store = null; - - this.removeEventListeners(); + this.input.removeEventListener('input', this._onInput); + this.input.removeEventListener('paste', this._onPaste); + this.input.removeEventListener('focus', this._onFocus); + this.input.removeEventListener('blur', this._onBlur); } }; diff --git a/assets/scripts/src/reducers/index.js b/assets/scripts/src/reducers/index.js index 8e43bb5..364fb17 100644 --- a/assets/scripts/src/reducers/index.js +++ b/assets/scripts/src/reducers/index.js @@ -3,10 +3,23 @@ import items from './items'; import groups from './groups'; import options from './options'; -const rootReducer = combineReducers({ +const appReducer = combineReducers({ items, groups, options -}) +}); + +const rootReducer = (state, action) => { + // If we are clearing all items, groups and options we reassign + // state and then pass that state to our proper reducer. This isn't + // mutating our actual state. + // + // See: http://stackoverflow.com/a/35641992 + if (action.type === 'CLEAR_ALL') { + state = undefined; + } + + return appReducer(state, action); +}; export default rootReducer; \ No newline at end of file diff --git a/build/config.gypi b/build/config.gypi deleted file mode 100644 index 5b92012..0000000 --- a/build/config.gypi +++ /dev/null @@ -1,56 +0,0 @@ -# Do not edit. File was generated by node-gyp's "configure" step -{ - "target_defaults": { - "cflags": [], - "default_configuration": "Release", - "defines": [], - "include_dirs": [], - "libraries": [] - }, - "variables": { - "asan": 0, - "host_arch": "x64", - "icu_data_file": "icudt57l.dat", - "icu_data_in": "../../deps/icu-small/source/data/in/icudt57l.dat", - "icu_endianness": "l", - "icu_gyp_path": "tools/icu/icu-generic.gyp", - "icu_locales": "en,root", - "icu_path": "deps/icu-small", - "icu_small": "true", - "icu_ver_major": "57", - "llvm_version": 0, - "node_byteorder": "little", - "node_enable_v8_vtunejit": "false", - "node_install_npm": "true", - "node_no_browser_globals": "false", - "node_prefix": "/", - "node_release_urlbase": "https://nodejs.org/download/release/", - "node_shared_cares": "false", - "node_shared_http_parser": "false", - "node_shared_libuv": "false", - "node_shared_openssl": "false", - "node_shared_zlib": "false", - "node_tag": "", - "node_use_dtrace": "true", - "node_use_etw": "false", - "node_use_lttng": "false", - "node_use_openssl": "true", - "node_use_perfctr": "false", - "openssl_fips": "", - "openssl_no_asm": 0, - "target_arch": "x64", - "uv_parent_path": "/deps/uv/", - "uv_use_dtrace": "true", - "v8_enable_gdbjit": 0, - "v8_enable_i18n_support": 1, - "v8_no_strict_aliasing": 1, - "v8_optimized_debug": 0, - "v8_random_seed": 0, - "v8_use_snapshot": "true", - "want_separate_host_toolset": 0, - "xcode_version": "7.0", - "nodedir": "/Users/joshjohnson/.node-gyp/6.2.0", - "copy_dev_lib": "true", - "standalone_static_library": 1 - } -} diff --git a/index.html b/index.html index 622ee3a..8e0bf00 100644 --- a/index.html +++ b/index.html @@ -167,7 +167,7 @@ }); const choices7 = new Choices('#choices-7', { allowSearch: false }).setValue(['Set value 1', 'Set value 2']); - + const choicesAjax = new Choices('#choices-12').ajax((callback) => { fetch('https://api.discogs.com/artists/391170/releases?token=QBRmstCkwXEvCjTclCpumbtNwvVkEzGAdELXyRyW') .then((response) => { @@ -178,7 +178,7 @@ .catch((error) => { callback(); }); - }); + }) const choicesMultiple = new Choices('[data-choice]', { placeholderValue: 'This is a placeholder set in the config',