From d8620f433fab5b8593db185617f76e82c559b771 Mon Sep 17 00:00:00 2001 From: Josh Johnson Date: Mon, 4 Apr 2016 14:43:22 +0100 Subject: [PATCH] Render items from store --- assets/scripts/dist/bundle.js | 2 +- assets/scripts/src/actions/index.js | 9 ++- assets/scripts/src/choices.js | 113 ++++++++++++++------------- assets/scripts/src/reducers/index.js | 9 ++- index.html | 51 +++--------- 5 files changed, 88 insertions(+), 96 deletions(-) diff --git a/assets/scripts/dist/bundle.js b/assets/scripts/dist/bundle.js index c2ede6e..ecca338 100644 --- a/assets/scripts/dist/bundle.js +++ b/assets/scripts/dist/bundle.js @@ -1 +1 @@ -!function(e){function t(i){if(n[i])return n[i].exports;var r=n[i]={exports:{},id:i,loaded:!1};return e[i].call(r.exports,r,r.exports,t),r.loaded=!0,r.exports}var n={};return t.m=e,t.c=n,t.p="/assets/scripts/dist/",t(0)}([function(e,t,n){e.exports=n(1)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{"default":e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(t,"__esModule",{value:!0}),t.Choices=void 0;var o=function(){function e(e,t){for(var n=0;ni;i++){var r=arguments[i];(0,l.isType)("Object",r)?n(r):console.error("Custom options must be an object")}return e}},{key:"isOpen",value:function(){}},{key:"isDisabled",value:function(){}},{key:"isEmpty",value:function(){return 0===this.valueCount.length}},{key:"clearInput",value:function(){this.input.value&&(this.input.value="")}},{key:"onKeyUp",value:function(e){}},{key:"onKeyDown",value:function(e){var t=this,n=e.ctrlKey||e.metaKey,i=8,r=13,o=65;if(e.target===this.input){if(n&&e.keyCode===o&&this.list&&this.list.children){var a=function(){t.options.removeItems&&!t.input.value&&t.options.selectAll&&t.selectAll(t.list.children)};a()}e.keyCode===r&&e.target.value&&!function(){var e=t.input.value,n=function(){var n=!0;if(t.options.maxItems&&t.options.maxItems<=t.list.children.length&&(n=!1),t.options.allowDuplicates===!1&&t.element.value&&t.valueArray.indexOf(e)>-1&&(n=!1),n&&"text"===t.element.type){var i=!0;t.options.regexFilter&&(i=t.regexFilter(e)),i&&(t.addItem(t.list,e),t.updateInputValue(e),t.clearInput(t.element))}};n()}()}if(e.keyCode===i&&!e.target.value){var s=function(){if(t.options.removeItems){var e=t.list.querySelectorAll(".choices__item"),n=t.list.querySelectorAll(".is-selected"),i=e[e.length-1];i&&!t.options.editItems&&t.selectItem(i),t.options.editItems&&i&&1===n.length?(t.input.value=i.innerHTML,t.removeItem(i)):t.removeAll(e)}};s(),e.preventDefault()}}},{key:"onClick",value:function(e){var t=this;if("LI"===e.target.tagName){var n=e.target,i=function(e){for(var n=e.getAttribute("data-choice-id"),i=t.list.children,r=0;r'),n=(0,l.strToEl)('
');this.element.classList.add("choices__input","choices__input--hidden"),this.element.tabIndex="-1",this.element.setAttribute("style","display:none;"),this.element.setAttribute("aria-hidden","true"),(0,l.wrap)(this.element,n),(0,l.wrap)(n,t);var i=(0,l.strToEl)('
    '),r=(0,l.strToEl)('');r.placeholder&&(r.placeholder=this.element.placeholder),this.options.addItems||(r.disabled=!0),n.appendChild(i),n.appendChild(r),t.appendChild(n),this.containerOuter=t,this.containerInner=n,this.input=r,this.list=i,""!==this.element.value&&this.valueArray.forEach(function(t){e.addItem(e.list,t)}),document.addEventListener("keydown",this.onKeyDown),this.list.addEventListener("click",this.onClick)}},{key:"render",value:function(){switch(this.options.debug&&console.debug("Render"),this.element.type){case"text":this.renderTextInput();break;case"select-one":break;case"select-multiple":break;default:this.renderTextInput()}}},{key:"destroy",value:function(){this.options=null,this.element=null,this.initialised=null,this.removeEventListeners(this.input)}}]),e}();!function(){var e=document.getElementById(1);document.getElementById(2),document.getElementById(3),document.getElementById(4),document.getElementById(5),new d({element:e})}()},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{"default":e}}t.__esModule=!0,t.compose=t.applyMiddleware=t.bindActionCreators=t.combineReducers=t.createStore=void 0;var r=n(3),o=i(r),a=n(8),s=i(a),u=n(10),c=i(u),l=n(11),d=i(l),f=n(12),p=i(f),h=n(9);i(h);t.createStore=o.default,t.combineReducers=s.default,t.bindActionCreators=c.default,t.applyMiddleware=d.default,t.compose=p.default},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{"default":e}}function r(e,t,n){function i(){h===p&&(h=p.slice())}function o(){return f}function u(e){if("function"!=typeof e)throw new Error("Expected listener to be a function.");var t=!0;return i(),h.push(e),function(){if(t){t=!1,i();var n=h.indexOf(e);h.splice(n,1)}}}function c(e){if(!(0,a.default)(e))throw new Error("Actions must be plain objects. Use custom middleware for async actions.");if("undefined"==typeof e.type)throw new Error('Actions may not have an undefined "type" property. Have you misspelled a constant?');if(v)throw new Error("Reducers may not dispatch actions.");try{v=!0,f=d(f,e)}finally{v=!1}for(var t=p=h,n=0;nn;n++)t[n]=arguments[n];return function(e){return function(n,i,r){var a=e(n,i,r),u=a.dispatch,c=[],l={getState:a.getState,dispatch:function(e){return u(e)}};return c=t.map(function(e){return e(l)}),u=s.default.apply(void 0,c)(a.dispatch),o({},a,{dispatch:u})}}}var o=Object.assign||function(e){for(var t=1;tn;n++)t[n]=arguments[n];return function(){if(0===t.length)return arguments.length<=0?void 0:arguments[0];var e=t[t.length-1],n=t.slice(0,-1);return n.reduceRight(function(e,t){return t(e)},e.apply(void 0,arguments))}}t.__esModule=!0,t.default=n},function(e,t){"use strict";function n(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t=0?t:0},t.getElementOffset=function(e,t){var n=t;return n>1&&(n=1),n>0&&(n=0),Math.max(e.offsetHeight*n)},t.getScrollPosition=function(e){return"bottom"===e?Math.max((window.scrollY||window.pageYOffset)+(window.innerHeight||document.documentElement.clientHeight)):window.scrollY||window.pageYOffset},t.isInView=function(e,t,n){return this.getScrollPosition(t)>this.getElemDistance(e)+this.getElementOffset(e,n)},t.stripHTML=function(e){var t=document.createElement("DIV");return t.innerHTML=e,t.textContent||t.innerText||""},t.addAnimation=function(e,t){var i=n(),r=function o(){e.classList.remove(t),e.removeEventListener(i,o,!1)};e.classList.add(t),e.addEventListener(i,r,!1)},t.getRandomNumber=function(e,t){return Math.floor(Math.random()*(t-e)+e)},t.strToEl=function(){var e=document.createElement("div");return function(t){var n;for(e.innerHTML=t,n=e.children[0];e.firstChild;)e.removeChild(e.firstChild);return n}}()}]); \ No newline at end of file +!function(e){function t(i){if(n[i])return n[i].exports;var r=n[i]={exports:{},id:i,loaded:!1};return e[i].call(r.exports,r,r.exports,t),r.loaded=!0,r.exports}var n={};return t.m=e,t.c=n,t.p="/assets/scripts/dist/",t(0)}([function(e,t,n){e.exports=n(1)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{"default":e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(t,"__esModule",{value:!0}),t.Choices=void 0;var o=function(){function e(e,t){for(var n=0;ni;i++){var r=arguments[i];(0,l.isType)("Object",r)?n(r):console.error("Custom options must be an object")}return e}},{key:"isOpen",value:function(){}},{key:"isDisabled",value:function(){}},{key:"isEmpty",value:function(){return 0===this.valueCount.length}},{key:"clearInput",value:function(){this.input.value&&(this.input.value="")}},{key:"onKeyUp",value:function(e){}},{key:"onKeyDown",value:function(e){var t=this,n=e.ctrlKey||e.metaKey,i=8,r=13,o=65;if(e.target===this.input){if(n&&e.keyCode===o&&this.list&&this.list.children){var a=function(){t.options.removeItems&&!t.input.value&&t.options.selectAll&&t.selectAll(t.list.children)};a()}e.keyCode===r&&e.target.value&&!function(){var e=t.input.value,n=function(){var n=!0;if(t.options.maxItems&&t.options.maxItems<=t.list.children.length&&(n=!1),t.options.allowDuplicates===!1&&t.element.value&&t.valueArray.indexOf(e)>-1&&(n=!1),n&&"text"===t.element.type){var i=!0;t.options.regexFilter&&(i=t.regexFilter(e)),i&&(t.addItem(e),t.updateInputValue(e),t.clearInput(t.element))}};n()}()}if(e.keyCode===i&&!e.target.value){var s=function(){if(t.options.removeItems){var e=t.list.querySelectorAll(".choices__item"),n=t.list.querySelectorAll(".is-selected"),i=e[e.length-1];i&&!t.options.editItems&&t.selectItem(i),t.options.editItems&&i&&0===n.length?(t.input.value=i.innerHTML,t.removeItem(i)):t.removeAll(e)}};s(),e.preventDefault()}}},{key:"onClick",value:function(e){var t=this;if("LI"===e.target.tagName){var n=e.target,i=function(e){for(var n=e.getAttribute("data-choice-id"),i=t.list.children,r=0;r'),n=(0,l.strToEl)('
    ');this.element.classList.add("choices__input","choices__input--hidden"),this.element.tabIndex="-1",this.element.setAttribute("style","display:none;"),this.element.setAttribute("aria-hidden","true"),(0,l.wrap)(this.element,n),(0,l.wrap)(n,t);var i=(0,l.strToEl)('
      '),r=(0,l.strToEl)('');r.placeholder&&(r.placeholder=this.element.placeholder),this.options.addItems||(r.disabled=!0),n.appendChild(i),n.appendChild(r),t.appendChild(n),this.containerOuter=t,this.containerInner=n,this.input=r,this.list=i,""!==this.element.value&&this.valueArray.forEach(function(t){e.addItem(t)}),document.addEventListener("keydown",this.onKeyDown),this.list.addEventListener("click",this.onClick)}},{key:"renderItems",value:function(){var e=this,t=this.store.getState();this.list.innerHTML="",t.forEach(function(t){if(t.active){var n=(0,l.strToEl)('
    • '+t.value+"
    • ");e.list.appendChild(n)}}),console.log(t)}},{key:"renderInput",value:function(){switch(this.options.debug&&console.debug("Render"),this.element.type){case"text":this.renderTextInput(),this.store.subscribe(this.renderItems),this.renderItems();break;case"select-one":break;case"select-multiple":break;default:this.renderTextInput()}}},{key:"destroy",value:function(){this.options=null,this.element=null,this.initialised=null,this.removeEventListeners(this.input)}}]),e}();!function(){var e=document.getElementById(1),t=document.getElementById(2),n=document.getElementById(3),i=document.getElementById(4),r=document.getElementById(5);new d({element:e,editItems:!0,maxItems:5,callbackOnRemoveItem:function(e){console.log(e)},callbackOnAddItem:function(e,t){console.log(e,t)}}),new d({element:t,allowDuplicates:!1,editItems:!0}),new d({element:n,allowDuplicates:!1,editItems:!0,regexFilter:/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/}),new d({element:i,addItems:!1}),new d({element:r,prependValue:"item-",appendValue:"-"+Date.now()})}()},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{"default":e}}t.__esModule=!0,t.compose=t.applyMiddleware=t.bindActionCreators=t.combineReducers=t.createStore=void 0;var r=n(3),o=i(r),a=n(7),s=i(a),u=n(9),c=i(u),l=n(10),d=i(l),f=n(11),p=i(f),h=n(8);i(h);t.createStore=o.default,t.combineReducers=s.default,t.bindActionCreators=c.default,t.applyMiddleware=d.default,t.compose=p.default},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{"default":e}}function r(e,t,n){function i(){h===p&&(h=p.slice())}function o(){return f}function u(e){if("function"!=typeof e)throw new Error("Expected listener to be a function.");var t=!0;return i(),h.push(e),function(){if(t){t=!1,i();var n=h.indexOf(e);h.splice(n,1)}}}function c(e){if(!(0,a.default)(e))throw new Error("Actions must be plain objects. Use custom middleware for async actions.");if("undefined"==typeof e.type)throw new Error('Actions may not have an undefined "type" property. Have you misspelled a constant?');if(m)throw new Error("Reducers may not dispatch actions.");try{m=!0,f=d(f,e)}finally{m=!1}for(var t=p=h,n=0;nn;n++)t[n]=arguments[n];return function(e){return function(n,i,r){var a=e(n,i,r),u=a.dispatch,c=[],l={getState:a.getState,dispatch:function(e){return u(e)}};return c=t.map(function(e){return e(l)}),u=s.default.apply(void 0,c)(a.dispatch),o({},a,{dispatch:u})}}}var o=Object.assign||function(e){for(var t=1;tn;n++)t[n]=arguments[n];return function(){if(0===t.length)return arguments.length<=0?void 0:arguments[0];var e=t[t.length-1],n=t.slice(0,-1);return n.reduceRight(function(e,t){return t(e)},e.apply(void 0,arguments))}}t.__esModule=!0,t.default=n},function(e,t){"use strict";function n(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t=0?t:0},t.getElementOffset=function(e,t){var n=t;return n>1&&(n=1),n>0&&(n=0),Math.max(e.offsetHeight*n)},t.getScrollPosition=function(e){return"bottom"===e?Math.max((window.scrollY||window.pageYOffset)+(window.innerHeight||document.documentElement.clientHeight)):window.scrollY||window.pageYOffset},t.isInView=function(e,t,n){return this.getScrollPosition(t)>this.getElemDistance(e)+this.getElementOffset(e,n)},t.stripHTML=function(e){var t=document.createElement("DIV");return t.innerHTML=e,t.textContent||t.innerText||""},t.addAnimation=function(e,t){var i=n(),r=function o(){e.classList.remove(t),e.removeEventListener(i,o,!1)};e.classList.add(t),e.addEventListener(i,r,!1)},t.getRandomNumber=function(e,t){return Math.floor(Math.random()*(t-e)+e)},t.strToEl=function(){var e=document.createElement("div");return function(t){var n;for(e.innerHTML=t,n=e.children[0];e.firstChild;)e.removeChild(e.firstChild);return n}}()}]); \ No newline at end of file diff --git a/assets/scripts/src/actions/index.js b/assets/scripts/src/actions/index.js index f1f3f06..f0b31d3 100644 --- a/assets/scripts/src/actions/index.js +++ b/assets/scripts/src/actions/index.js @@ -1,12 +1,17 @@ -export const addItemToStore = (value, element, id) => { +export const addItemToStore = (value, id) => { return { type: 'ADD_ITEM', value: value, - element: element, id: id } }; +export const unselectAllFromStore = () => { + return { + type: 'UNSELECT_ALL' + } +} + export const removeItemFromStore = (id) => { return { type: 'REMOVE_ITEM', diff --git a/assets/scripts/src/choices.js b/assets/scripts/src/choices.js index 6b6630f..b98d805 100644 --- a/assets/scripts/src/choices.js +++ b/assets/scripts/src/choices.js @@ -2,7 +2,7 @@ import { createStore } from 'redux'; import choices from './reducers/index.js'; -import { addItemToStore, removeItemFromStore, selectItemFromStore } from './actions/index'; +import { addItemToStore, removeItemFromStore, selectItemFromStore, unselectAllFromStore } from './actions/index'; import { hasClass, wrap, getSiblings, isType, strToEl } from './lib/utils.js'; @@ -20,7 +20,6 @@ export class Choices { constructor(options) { const fakeEl = document.createElement("fakeel"); const userOptions = options || {}; - const store = createStore(choices); const defaultOptions = { element: document.querySelector('[data-choice]'), disabled: false, @@ -44,7 +43,7 @@ export class Choices { // Merge options with user options this.options = this.extend(defaultOptions, userOptions || {}); - this.store = store; + this.store = createStore(choices); this.initialised = false; this.supports = 'querySelector' in document && 'addEventListener' in document && 'classList' in fakeEl; @@ -62,6 +61,7 @@ export class Choices { // Bind methods this.onKeyDown = this.onKeyDown.bind(this); this.onClick = this.onClick.bind(this); + this.renderItems = this.renderItems.bind(this); this.init(); } @@ -183,12 +183,11 @@ export class Choices { // All is good, add if(canAddItem) { - this.addItem(this.list, value); + this.addItem(value); this.updateInputValue(value); this.clearInput(this.element); } } - } }; @@ -212,7 +211,7 @@ export class Choices { // If editing the last item is allowed and there is a last item and // there are not other selected items (minus the last item), we can edit // the item value. Otherwise if we can remove items, remove all items - if(this.options.editItems && lastItem && selectedItems.length === 1) { + if(this.options.editItems && lastItem && selectedItems.length === 0) { this.input.value = lastItem.innerHTML; this.removeItem(lastItem); } else { @@ -269,16 +268,12 @@ export class Choices { selectItem(item) { let id = item.getAttribute('data-choice-id'); - item.classList.add('is-selected'); this.store.dispatch(selectItemFromStore(id, true)); - console.log(this.store.getState()); } unselectItem(item) { let id = item.getAttribute('data-choice-id'); - item.classList.remove('is-selected'); this.store.dispatch(selectItemFromStore(id, false)); - console.log(this.store.getState()); } selectAll(items) { @@ -307,7 +302,7 @@ export class Choices { this.element.value = this.valueArray.join(this.options.delimiter); } - addItem(parent, value) { + addItem(value) { if (this.options.debug) console.debug('Add item'); let passedValue = value; @@ -322,25 +317,20 @@ export class Choices { passedValue = passedValue + this.options.appendValue.toString(); } + // Generate unique id let id = this.store.getState().length + 1; - // Create new list element - let item = strToEl(`
    • ${passedValue}
    • `); - - // Append it to list - parent.appendChild(item); - // Run callback if it is a function if(this.options.callbackOnAddItem){ if(isType('Function', this.options.callbackOnAddItem)) { - this.options.callbackOnAddItem(item, value); + this.options.callbackOnAddItem(id, value); } else { console.error('callbackOnAddItem: Callback is not a function'); } } - this.store.dispatch(addItemToStore(passedValue, item, id)); - console.log(this.store.getState()); + this.store.dispatch(addItemToStore(passedValue, id)); + this.store.dispatch(unselectAllFromStore(passedValue, id)); } removeItem(item) { @@ -351,7 +341,6 @@ export class Choices { let id = item.getAttribute('data-choice-id'); let value = item.innerHTML; - item.parentNode.removeChild(item); // Run callback if(this.options.callbackOnRemoveItem){ @@ -363,7 +352,6 @@ export class Choices { } this.store.dispatch(removeItemFromStore(id)); - console.log(this.store.getState()); } removeAll(items) { @@ -380,7 +368,7 @@ export class Choices { init() { if (!this.supports) console.error('init: Your browser doesn\'nt support shit'); this.initialised = true; - this.render(this.element); + this.renderInput(this.element); } renderTextInput() { @@ -434,7 +422,7 @@ export class Choices { if (this.element.value !== '') { // Add any preset values this.valueArray.forEach((value) => { - this.addItem(this.list, value); + this.addItem(value); }); } @@ -443,13 +431,32 @@ export class Choices { this.list.addEventListener('click', this.onClick); } + renderItems(){ + let items = this.store.getState(); - render() { + this.list.innerHTML = ''; + + items.forEach((item) => { + if(item.active) { + // Create new list element + let listItem = strToEl(`
    • ${item.value}
    • `); + + // Append it to list + this.list.appendChild(listItem); + } + }); + + console.log(items); + } + + renderInput() { if (this.options.debug) console.debug('Render'); switch (this.element.type) { case "text": this.renderTextInput(); + this.store.subscribe(this.renderItems); + this.renderItems(); break; case "select-one": // this.renderSelectInput(); @@ -461,7 +468,6 @@ export class Choices { this.renderTextInput(); break; } - } destroy() { @@ -482,36 +488,37 @@ export class Choices { let choices1 = new Choices({ element : input1, // delimiter: ' ', - // maxItems: 5, - // callbackOnRemoveItem: function(value) { - // console.log(value); - // }, - // callbackOnAddItem: function(item, value) { - // console.log(item, value); - // } + editItems: true, + maxItems: 5, + callbackOnRemoveItem: function(value) { + console.log(value); + }, + callbackOnAddItem: function(item, value) { + console.log(item, value); + } }); - // let choices2 = new Choices({ - // element : input2, - // allowDuplicates: false, - // editItems: true, - // }); + let choices2 = new Choices({ + element : input2, + allowDuplicates: false, + editItems: true, + }); - // let choices3 = new Choices({ - // element : input3, - // allowDuplicates: false, - // editItems: true, - // regexFilter: /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ - // }); + let choices3 = new Choices({ + element : input3, + allowDuplicates: false, + editItems: true, + regexFilter: /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ + }); - // let choices4 = new Choices({ - // element : input4, - // addItems: false - // }); + let choices4 = new Choices({ + element : input4, + addItems: false + }); - // let choices5 = new Choices({ - // element: input5, - // prependValue: 'item-', - // appendValue: `-${Date.now()}` - // }); + let choices5 = new Choices({ + element: input5, + prependValue: 'item-', + appendValue: `-${Date.now()}` + }); })(); \ No newline at end of file diff --git a/assets/scripts/src/reducers/index.js b/assets/scripts/src/reducers/index.js index f6f615c..ad38128 100644 --- a/assets/scripts/src/reducers/index.js +++ b/assets/scripts/src/reducers/index.js @@ -5,11 +5,18 @@ const choices = (state = [], action) => { return [...state, { id: parseInt(action.id), value: action.value, - element: action.element, active: true, selected: false }]; + case 'UNSELECT_ALL': + return state.map((item) => { + if(item.selected) { + item.selected = false; + } + return item; + }); + case 'REMOVE_ITEM': // Set item to inactive return state.map((item) => { diff --git a/index.html b/index.html index d9c95ba..4f6077e 100644 --- a/index.html +++ b/index.html @@ -6,50 +6,23 @@ - - - + + - - - + \ No newline at end of file