mirror of
https://github.com/Choices-js/Choices.git
synced 2024-06-08 00:42:15 +02:00
Handle on one element per instance + remove list items on back space
This commit is contained in:
parent
8ea38d8d6b
commit
ecee8cff47
2
assets/scripts/dist/bundle.js
vendored
2
assets/scripts/dist/bundle.js
vendored
File diff suppressed because one or more lines are too long
|
@ -1,24 +1,13 @@
|
|||
'use strict';
|
||||
|
||||
import { wrap, getSiblings, isType } from './lib/utils.js';
|
||||
|
||||
(function (root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define(function() {
|
||||
return factory(root);
|
||||
});
|
||||
} else if (typeof exports === 'object') {
|
||||
module.exports = factory;
|
||||
} else {
|
||||
root.Choices = factory(root);
|
||||
}
|
||||
})(this, function (root) {
|
||||
|
||||
'use strict';
|
||||
|
||||
class Choices {
|
||||
constructor() {
|
||||
class Choices {
|
||||
constructor(options) {
|
||||
const fakeEl = document.createElement("fakeelement");
|
||||
const USER_OPTIONS = options || {};
|
||||
const DEFAULT_OPTIONS = {
|
||||
element: '[data-choice]',
|
||||
element: document.querySelector('[data-choice]'),
|
||||
disabled: false,
|
||||
maxItems: 5,
|
||||
debug: true,
|
||||
|
@ -31,13 +20,17 @@ import { wrap, getSiblings, isType } from './lib/utils.js';
|
|||
callbackOnRemove: function(){}
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Merge options with user options
|
||||
this.options = DEFAULT_OPTIONS;
|
||||
this.options = this.extend(DEFAULT_OPTIONS, USER_OPTIONS || {});
|
||||
this.initialised = false;
|
||||
this.supports = 'querySelector' in document && 'addEventListener' in document && 'classList' in fakeEl;
|
||||
|
||||
// Retrieve elements
|
||||
this.elements = document.querySelectorAll(this.options.element);
|
||||
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) : [];
|
||||
|
||||
// Bind methods
|
||||
this.onClick = this.onClick.bind(this);
|
||||
|
@ -47,6 +40,41 @@ import { wrap, getSiblings, isType } from './lib/utils.js';
|
|||
this.onBlur = this.onChange.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges unspecified amount of objects into new object
|
||||
* @private
|
||||
* @return {Object} Merged object of arguments
|
||||
*/
|
||||
extend() {
|
||||
let extended = {};
|
||||
let length = arguments.length;
|
||||
|
||||
/**
|
||||
* Merge one object into another
|
||||
* @param {Object} obj Object to merge into extended object
|
||||
*/
|
||||
let merge = function(obj) {
|
||||
for(let prop in obj) {
|
||||
extended[prop] = obj[prop];
|
||||
}
|
||||
};
|
||||
|
||||
// Loop through each passed argument
|
||||
for(let i = 0; i < length; i++) {
|
||||
// Store argument at position i
|
||||
let obj = arguments[i];
|
||||
|
||||
// If we are in fact dealing with an object, merge it. Otherwise throw error
|
||||
if(isType('Object', obj)) {
|
||||
merge(obj);
|
||||
} else {
|
||||
console.error('Custom options must be an object');
|
||||
}
|
||||
}
|
||||
|
||||
return extended;
|
||||
};
|
||||
|
||||
/* State */
|
||||
|
||||
isOpen() {
|
||||
|
@ -61,8 +89,8 @@ import { wrap, getSiblings, isType } from './lib/utils.js';
|
|||
|
||||
}
|
||||
|
||||
clearInput(el) {
|
||||
if(el.value) el.value = '';
|
||||
clearInput() {
|
||||
if(this.input.value) this.input.value = '';
|
||||
}
|
||||
|
||||
/* Event handling */
|
||||
|
@ -70,24 +98,34 @@ import { wrap, getSiblings, isType } from './lib/utils.js';
|
|||
onKeyDown(e) {
|
||||
// Handle enter key
|
||||
if(e.keyCode === 13 && e.target.value) {
|
||||
let el = e.target;
|
||||
let value = el.value;
|
||||
let list = e.target.parentNode.querySelector('.choice__list');
|
||||
let value = this.input.value;
|
||||
|
||||
let handleEnterKey = () => {
|
||||
this.addItem(el, value, list);
|
||||
this.updateInputValue(el, value);
|
||||
this.clearInput(el);
|
||||
this.addItem(value);
|
||||
this.updateInputValue(value);
|
||||
this.clearInput(this.element);
|
||||
};
|
||||
|
||||
if(this.options.maxItems) {
|
||||
if(this.options.maxItems > list.children.length) {
|
||||
if(this.options.maxItems > this.list.children.length) {
|
||||
handleEnterKey();
|
||||
}
|
||||
} else {
|
||||
handleEnterKey();
|
||||
}
|
||||
}
|
||||
|
||||
if(e.keyCode === 8 && !e.target.value) {
|
||||
|
||||
let handleBackspaceKey = () => {
|
||||
let lastItem = this.list.children[this.list.children.length - 1];
|
||||
lastItem.parentNode.removeChild(lastItem);
|
||||
};
|
||||
|
||||
handleBackspaceKey();
|
||||
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
onFocus(e) {
|
||||
|
@ -142,19 +180,16 @@ import { wrap, getSiblings, isType } from './lib/utils.js';
|
|||
|
||||
}
|
||||
|
||||
updateInputValue(el, value) {
|
||||
updateInputValue(value) {
|
||||
if(this.options.debug) console.debug('Update input value');
|
||||
// Find hidden element
|
||||
let hiddenInput = el.parentNode.querySelector('.choice__input--hidden');
|
||||
// If input already has values, parse the array, otherwise create a blank array
|
||||
let valueArray = hiddenInput.value !== '' && isType('Array', JSON.parse(hiddenInput.value)) ? JSON.parse(hiddenInput.value) : [];
|
||||
|
||||
// Push new value to array
|
||||
valueArray.push(value);
|
||||
this.valueArray.push(value);
|
||||
// Caste array to string and set it as the hidden inputs value
|
||||
hiddenInput.value = JSON.stringify(valueArray);
|
||||
this.element.value = JSON.stringify(this.valueArray);
|
||||
}
|
||||
|
||||
addItem(el, value, list) {
|
||||
addItem(value) {
|
||||
if(this.options.debug) console.debug('Add item');
|
||||
|
||||
// Create new list element
|
||||
|
@ -163,7 +198,7 @@ import { wrap, getSiblings, isType } from './lib/utils.js';
|
|||
item.textContent = value;
|
||||
|
||||
// Append it to list
|
||||
list.appendChild(item);
|
||||
this.list.appendChild(item);
|
||||
}
|
||||
|
||||
removeItem() {
|
||||
|
@ -182,61 +217,71 @@ import { wrap, getSiblings, isType } from './lib/utils.js';
|
|||
if(!this.supports) console.error('Your browser doesn\'nt support shit');
|
||||
this.initialised = true;
|
||||
|
||||
let els = this.elements;
|
||||
for (let i = els.length - 1; i >= 0; i--) {
|
||||
let el = els[i];
|
||||
this.render(el);
|
||||
}
|
||||
this.render(this.element);
|
||||
}
|
||||
|
||||
render(el) {
|
||||
render() {
|
||||
if(this.options.debug) console.debug('Render');
|
||||
|
||||
let wrapper = document.createElement('div');
|
||||
// Create DOM elements
|
||||
let container = document.createElement('div');
|
||||
let input = document.createElement('input');
|
||||
let list = document.createElement('ul');
|
||||
|
||||
wrapper.classList.add('choice', 'choice--active');
|
||||
container.className = 'choice choice--active';
|
||||
|
||||
el.classList.add('choice__input', 'choice__input--hidden');
|
||||
el.tabIndex = '-1';
|
||||
el.setAttribute('style', 'display:none;');
|
||||
el.setAttribute('aria-hidden', 'true');
|
||||
// Hide passed input
|
||||
this.element.classList.add('choice__input', 'choice__input--hidden');
|
||||
this.element.tabIndex = '-1';
|
||||
this.element.setAttribute('style', 'display:none;');
|
||||
this.element.setAttribute('aria-hidden', 'true');
|
||||
|
||||
wrap(el, wrapper);
|
||||
// Wrap input in container
|
||||
wrap(this.element, container);
|
||||
|
||||
list.classList.add('choice__list');
|
||||
list.className = 'choice__list';
|
||||
|
||||
if(el.value !== '') {
|
||||
let valueArray = JSON.parse(el.value);
|
||||
valueArray.map((v) => {
|
||||
this.addItem(el, v, list);
|
||||
input.type = 'text';
|
||||
input.placeholder = this.element.placeholder;
|
||||
input.className = 'choice__input choice__input--cloned';
|
||||
|
||||
container.appendChild(list);
|
||||
container.appendChild(input);
|
||||
|
||||
this.container = container;
|
||||
this.input = input;
|
||||
this.list = list;
|
||||
|
||||
if(this.element.value !== '') {
|
||||
let initialValues = JSON.parse(this.element.value);
|
||||
initialValues.forEach((value) => {
|
||||
this.addItem(value);
|
||||
});
|
||||
}
|
||||
|
||||
input.type = 'text';
|
||||
input.classList.add('choice__input', 'choice__input--cloned');
|
||||
|
||||
wrapper.appendChild(list);
|
||||
wrapper.appendChild(input);
|
||||
|
||||
this.addEventListeners(input);
|
||||
this.addEventListeners(this.input);
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.options = null;
|
||||
this.elements = null;
|
||||
this.element = null;
|
||||
|
||||
let els = this.elements;
|
||||
|
||||
for (let i = els.length - 1; i >= 0; i--) {
|
||||
let el = els[i];
|
||||
|
||||
this.removeEventListeners(el);
|
||||
this.removeEventListeners(this.input);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
window.addEventListener('load', function() {
|
||||
|
||||
let choiceInputs = document.querySelectorAll('[data-choice]');
|
||||
|
||||
for (let i = choiceInputs.length - 1; i >= 0; i--) {
|
||||
|
||||
let input = choiceInputs[i];
|
||||
|
||||
var choices = new Choices({
|
||||
element : input
|
||||
});
|
||||
|
||||
var choices = new Choices();
|
||||
choices.init();
|
||||
};
|
||||
});
|
|
@ -5,8 +5,8 @@
|
|||
<title>Choices</title>
|
||||
</head>
|
||||
<body>
|
||||
<input id="1" type="text" data-choice value='["preset-1", "preset-2"]'>
|
||||
<input id="2" type="text" data-choice>
|
||||
<input id="1" type="text" data-choice value='["preset-1", "preset-2"]' placeholder="This is a placeholder" class="custom class">
|
||||
<input id="2" type="text" data-choice >
|
||||
<script src="assets/scripts/dist/bundle.js"></script>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in a new issue