From 152b4283dcd4150c7e9cbabd764ade5dc1db912b Mon Sep 17 00:00:00 2001 From: Josh Johnson Date: Fri, 18 Mar 2016 11:05:50 +0000 Subject: [PATCH] Don't store input values as array for text inputs + handle different input types --- assets/scripts/dist/bundle.js | 2 +- assets/scripts/src/choices.js | 115 +++++++++++++++++++++--------- assets/styles/css/choices.css | 4 ++ assets/styles/css/choices.min.css | 2 +- assets/styles/scss/choices.scss | 4 ++ index.html | 22 +++++- 6 files changed, 110 insertions(+), 39 deletions(-) diff --git a/assets/scripts/dist/bundle.js b/assets/scripts/dist/bundle.js index 5d805a2..d0c3f82 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 o=n[i]={exports:{},id:i,loaded:!1};return e[i].call(o.exports,o,o.exports,t),o.loaded=!0,o.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,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var o=function(){function e(e,t){for(var n=0;ni;i++){var o=arguments[i];(0,s.isType)("Object",o)?n(o):console.error("Custom options must be an object")}return e}},{key:"isOpen",value:function(){}},{key:"isDisabled",value:function(){}},{key:"isEmpty",value:function(){}},{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;if(n&&65===e.keyCode)for(var i=0;i-1&&(n=!1)}n&&(t.addItem(e),t.updateInputValue(e),t.clearInput(t.element))};n()}(),(8===e.keyCode||46===e.keyCode)&&!e.target.value){var s=function(){var e=t.list.querySelectorAll(".choices__item"),n=e[e.length-1];n.classList.add("is-selected");for(var i=0;i=0;t--){var n=e[t],i=new a({element:n});i.init()}})},function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var n=(t.hasClass=function(e,t){return new RegExp(" "+t+" ").test(" "+e.className+" ")},t.capitalise=function(e){return e.replace(/\w\S*/g,function(e){return e.charAt(0).toUpperCase()+e.substr(1).toLowerCase()})},t.isType=function(e,t){var n=Object.prototype.toString.call(t).slice(8,-1);return void 0!==t&&null!==t&&n===e},t.whichTransitionEvent=function(){var e,t=document.createElement("fakeelement"),n={transition:"transitionend",OTransition:"oTransitionEnd",MozTransition:"transitionend",WebkitTransition:"webkitTransitionEnd"};for(e in n)if(void 0!==t.style[e])return n[e]},t.whichAnimationEvent=function(){var e,t=document.createElement("fakeelement"),n={animation:"animationend",OAnimation:"oAnimationEnd",MozAnimation:"animationend",WebkitAnimation:"webkitAnimationEnd"};for(e in n)if(void 0!==t.style[e])return n[e]});t.getParentsUntil=function(e,t,n){for(var i=[];e&&e!==document;e=e.parentNode){if(t){var o=t.charAt(0);if("."===o&&e.classList.contains(t.substr(1)))break;if("#"===o&&e.id===t.substr(1))break;if("["===o&&e.hasAttribute(t.substr(1,t.length-1)))break;if(e.tagName.toLowerCase()===t)break}if(n){var s=n.charAt(0);"."===s&&e.classList.contains(n.substr(1))&&i.push(e),"#"===s&&e.id===n.substr(1)&&i.push(e),"["===s&&e.hasAttribute(n.substr(1,n.length-1))&&i.push(e),e.tagName.toLowerCase()===n&&i.push(e)}else i.push(e)}return 0===i.length?null:i},t.wrap=function(e,t){return t=t||document.createElement("div"),e.nextSibling?e.parentNode.insertBefore(t,e.nextSibling):e.parentNode.appendChild(t),t.appendChild(e)},t.getSiblings=function(e){for(var t=[],n=e.parentNode.firstChild;n;n=n.nextSibling)1===n.nodeType&&n!==e&&t.push(n);return t},t.findAncestor=function(e,t){for(;(e=e.parentElement)&&!e.classList.contains(t););return e},t.debounce=function(e,t,n){var i;return function(){var o=this,s=arguments,a=function(){i=null,n||e.apply(o,s)},r=n&&!i;clearTimeout(i),i=setTimeout(a,t),r&&e.apply(o,s)}},t.getElemDistance=function(e){var t=0;if(e.offsetParent)do t+=e.offsetTop,e=e.offsetParent;while(e);return 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(),o=function s(){e.classList.remove(t),e.removeEventListener(i,s,!1)};e.classList.add(t),e.addEventListener(i,o,!1)},t.getRandomNumber=function(e,t){return Math.floor(Math.random()*(t-e)+e)}}]); \ No newline at end of file +!function(e){function t(i){if(n[i])return n[i].exports;var o=n[i]={exports:{},id:i,loaded:!1};return e[i].call(o.exports,o,o.exports,t),o.loaded=!0,o.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,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var o=function(){function e(e,t){for(var n=0;ni;i++){var o=arguments[i];(0,s.isType)("Object",o)?n(o):console.error("Custom options must be an object")}return e}},{key:"isOpen",value:function(){}},{key:"isDisabled",value:function(){}},{key:"isEmpty",value:function(){}},{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;if(n&&65===e.keyCode)for(var i=0;i-1&&(n=!1),n&&(t.addItem(e),t.updateInputValue(e),t.clearInput(t.element))};n()}(),(8===e.keyCode||46===e.keyCode)&&!e.target.value){var s=function(){var e=t.list.querySelectorAll(".choices__item"),n=e[e.length-1];n.classList.add("is-selected");for(var i=0;i=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(),o=function s(){e.classList.remove(t),e.removeEventListener(i,s,!1)};e.classList.add(t),e.addEventListener(i,o,!1)},t.getRandomNumber=function(e,t){return Math.floor(Math.random()*(t-e)+e)}}]); \ No newline at end of file diff --git a/assets/scripts/src/choices.js b/assets/scripts/src/choices.js index 2a3f248..895b8b4 100644 --- a/assets/scripts/src/choices.js +++ b/assets/scripts/src/choices.js @@ -2,6 +2,14 @@ import { hasClass, wrap, getSiblings, isType } from './lib/utils.js'; +/** + + TODO: + - Handle select input + - Handle multiple select input ? + + */ + class Choices { constructor(options) { const fakeEl = document.createElement("fakeelement"); @@ -10,8 +18,9 @@ class Choices { element: document.querySelector('[data-choice]'), disabled: false, create: true, - maxItems: 10, - allowDuplicates: false, + maxItems: false, + delimiter: ',', + allowDuplicates: true, debug: false, placeholder: false, callbackOnInit: function(){}, @@ -30,7 +39,9 @@ class Choices { // Retrieve elements this.element = this.options.element; // If input already has values, parse the array, otherwise create a blank array - this.valueArray = this.element.value !== '' && isType('Array', JSON.parse(this.element.value)) ? JSON.parse(this.element.value) : []; + this.valueArray = this.element.value !== '' ? this.element.value.replace(/\s/g, '').split(',') : []; + + console.log(this.valueArray); // Bind methods this.onClick = this.onClick.bind(this); @@ -127,9 +138,7 @@ class Choices { // If no duplicates are allowed, and the value already exists // in the array, don't update if(this.options.allowDuplicates === false && this.element.value) { - let currentValues = JSON.parse(this.element.value); - - if(currentValues.indexOf(value) > -1) { + if(this.valueArray.indexOf(value) > -1) { canUpdate = false; } } @@ -228,8 +237,9 @@ class Choices { // Push new value to array this.valueArray.push(value); + // Caste array to string and set it as the hidden inputs value - this.element.value = JSON.stringify(this.valueArray); + this.element.value = this.valueArray.toString(); } removeInputValue(value) { @@ -238,13 +248,13 @@ class Choices { let index = this.valueArray.indexOf(value); this.valueArray.splice(index, 1); - this.element.value = JSON.stringify(this.valueArray); + this.element.value = this.valueArray.toString(); } addItem(value) { if(this.options.debug) console.debug('Add item'); - // Create new list element + // // Create new list element let item = document.createElement('li'); item.classList.add('choices__item'); item.textContent = value; @@ -263,17 +273,12 @@ class Choices { this.render(this.element); } - render() { - if(this.options.debug) console.debug('Render'); - - // Create DOM elements + renderTextInput() { let containerOuter = document.createElement('div'); - let containerInner = document.createElement('div'); - let input = document.createElement('input'); - let list = document.createElement('ul'); + containerOuter.className = 'choices choices--active'; - containerOuter.className = 'choices choices--active'; - containerInner.className = 'choices__inner'; + let containerInner = document.createElement('div'); + containerInner.className = 'choices__inner'; // Hide passed input this.element.classList.add('choices__input', 'choices__input--hidden'); @@ -283,15 +288,21 @@ class Choices { // Wrap input in container preserving DOM ordering wrap(this.element, containerInner); - + + // Wrapper inner container with outer container wrap(containerInner, containerOuter); - list.className = 'choices__list'; + let list = document.createElement('ul'); + list.className = 'choices__list'; - input.type = 'text'; - input.placeholder = this.element.placeholder; - input.className = 'choices__input choices__input--cloned'; - + let input = document.createElement('input'); + input.type = 'text'; + input.className = 'choices__input choices__input--cloned'; + + if(input.placeholder) { + input.placeholder = this.element.placeholder; + } + containerInner.appendChild(list); containerInner.appendChild(input); containerOuter.appendChild(containerInner); @@ -302,15 +313,40 @@ class Choices { this.list = list; if(this.element.value !== '') { - let initialValues = JSON.parse(this.element.value); - initialValues.forEach((value) => { + // Add any preset values + this.valueArray.forEach((value) => { this.addItem(value); }); } + // Trigger event listeners this.addEventListeners(this.input); } + renderSelectInput() { + + } + + render() { + if(this.options.debug) console.debug('Render'); + + switch(this.element.type) { + case "text": + this.renderTextInput(); + break; + case "select-one": + this.renderSelectInput(); + break; + case "select-multiple": + console.warn('Choices does not support multiple select boxes'); + break; + default: + rthis.renderTextInput(); + break; + } + + } + destroy() { this.options = null; this.element = null; @@ -321,16 +357,27 @@ class Choices { window.addEventListener('load', function() { - let choiceInputs = document.querySelectorAll('[data-choice]'); + let input1 = document.getElementById(1); + let input2 = document.getElementById(2); + let input3 = document.getElementById(3); - for (let i = choiceInputs.length - 1; i >= 0; i--) { + let choices1 = new Choices({ + element : input1, + delimiter: ' ', + maxItems: 5, + }); - let input = choiceInputs[i]; + let choices2 = new Choices({ + element : input2, + allowDuplicates: false + }); - var choices = new Choices({ - element : input - }); + let choices3 = new Choices({ + element : input3 + }); + + choices1.init(); + choices2.init(); + choices3.init(); - choices.init(); - }; }); \ No newline at end of file diff --git a/assets/styles/css/choices.css b/assets/styles/css/choices.css index 9aaefee..017a321 100644 --- a/assets/styles/css/choices.css +++ b/assets/styles/css/choices.css @@ -16,6 +16,10 @@ body { color: #222222; padding: 2.4rem; } +label { + display: block; + margin-bottom: .8rem; } + .choices { margin-bottom: 2.4rem; position: relative; } diff --git a/assets/styles/css/choices.min.css b/assets/styles/css/choices.min.css index ed4a476..99c19fe 100644 --- a/assets/styles/css/choices.min.css +++ b/assets/styles/css/choices.min.css @@ -1 +1 @@ -*,:after,:before{box-sizing:border-box}body,html{margin:0;height:100%;widows:100%}html{font-size:62.5%}body{background-color:#fafafa;font-family:'Helvetica Neue','Helvetica','Arial',sans-serif;font-size:1.6rem;color:#222;padding:2.4rem}.choices{margin-bottom:2.4rem;position:relative}.choices__inner{background-color:#fff;padding:.75rem .75rem .375rem;border:1px solid #ddd;border-radius:.25rem;font-size:1.4rem}.choices__inner:focus{outline:1px solid #00bcd4;outline-offset:-1px}.choices__list{margin:0;padding-left:0;list-style-type:none;display:inline}.choices__input{font-size:1.4rem;padding:0;margin-bottom:.5rem;display:inline-block;vertical-align:baseline;border:0;border-radius:0;max-width:100%}.choices__input:focus{outline:0}.choices__item{display:inline-block;border-radius:.4rem;padding:.4rem .8rem;font-size:1.4rem;margin-right:.375rem;margin-bottom:.375rem;background-color:#00bcd4;text-shadow:0 1px 0 #008fa1;border:1px solid #00a5bb;color:#fff}.choices__item.is-selected{background-color:#00a5bb} \ No newline at end of file +*,:after,:before{box-sizing:border-box}body,html{margin:0;height:100%;widows:100%}html{font-size:62.5%}body{background-color:#fafafa;font-family:'Helvetica Neue','Helvetica','Arial',sans-serif;font-size:1.6rem;color:#222;padding:2.4rem}label{display:block;margin-bottom:.8rem}.choices{margin-bottom:2.4rem;position:relative}.choices__inner{background-color:#fff;padding:.75rem .75rem .375rem;border:1px solid #ddd;border-radius:.25rem;font-size:1.4rem}.choices__inner:focus{outline:1px solid #00bcd4;outline-offset:-1px}.choices__list{margin:0;padding-left:0;list-style-type:none;display:inline}.choices__input{font-size:1.4rem;padding:0;margin-bottom:.5rem;display:inline-block;vertical-align:baseline;border:0;border-radius:0;max-width:100%}.choices__input:focus{outline:0}.choices__item{display:inline-block;border-radius:.4rem;padding:.4rem .8rem;font-size:1.4rem;margin-right:.375rem;margin-bottom:.375rem;background-color:#00bcd4;text-shadow:0 1px 0 #008fa1;border:1px solid #00a5bb;color:#fff}.choices__item.is-selected{background-color:#00a5bb} \ No newline at end of file diff --git a/assets/styles/scss/choices.scss b/assets/styles/scss/choices.scss index 757fffd..cbed131 100644 --- a/assets/styles/scss/choices.scss +++ b/assets/styles/scss/choices.scss @@ -20,6 +20,10 @@ body { padding: 2.4rem; } +label { + display: block; + margin-bottom: .8rem; +} .choices { margin-bottom: 2.4rem; diff --git a/index.html b/index.html index 93ce193..e315947 100644 --- a/index.html +++ b/index.html @@ -6,8 +6,24 @@ - - - + + + + + + + + + + + \ No newline at end of file