mirror of
https://github.com/Choices-js/Choices.git
synced 2024-05-02 22:03:11 +02:00
Handle click events on list items + set active status in store + set select status in store
This commit is contained in:
parent
c4598aeccb
commit
174aa399c2
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
|
@ -5,18 +5,19 @@ export const addItemToStore = (value, element, id) => {
|
|||
element: element,
|
||||
id: id
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const removeItemFromStore = (id) => {
|
||||
return {
|
||||
type: 'REMOVE_ITEM',
|
||||
id: id,
|
||||
id: id
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const updateItemInStore = (value) => {
|
||||
export const selectItemFromStore = (id, value) => {
|
||||
return {
|
||||
type: 'UPDATE_ITEM',
|
||||
type: 'SELECT_ITEM',
|
||||
id: id,
|
||||
value: value
|
||||
}
|
||||
}
|
||||
};
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
import { createStore } from 'redux';
|
||||
import choices from './reducers/index.js';
|
||||
import { addItemToStore, removeItemFromStore } from './actions/index';
|
||||
import { hasClass, wrap, getSiblings, isType } from './lib/utils.js';
|
||||
import { addItemToStore, removeItemFromStore, selectItemFromStore } from './actions/index';
|
||||
import { hasClass, wrap, getSiblings, isType, strToEl } from './lib/utils.js';
|
||||
|
||||
|
||||
/**
|
||||
|
@ -18,10 +18,10 @@ import { hasClass, wrap, getSiblings, isType } from './lib/utils.js';
|
|||
|
||||
export class Choices {
|
||||
constructor(options) {
|
||||
const FAKE_EL = document.createElement("fakeel");
|
||||
const USER_OPTIONS = options || {};
|
||||
const STORE = createStore(choices);
|
||||
const DEFAULT_OPTIONS = {
|
||||
const fakeEl = document.createElement("fakeel");
|
||||
const userOptions = options || {};
|
||||
const store = createStore(choices);
|
||||
const defaultOptions = {
|
||||
element: document.querySelector('[data-choice]'),
|
||||
disabled: false,
|
||||
addItems: true,
|
||||
|
@ -35,6 +35,7 @@ export class Choices {
|
|||
placeholder: false,
|
||||
prependValue: false,
|
||||
appendValue: false,
|
||||
selectAll: true,
|
||||
callbackOnInit: function() {},
|
||||
callbackOnRender: function() {},
|
||||
callbackOnRemoveItem: function() {},
|
||||
|
@ -42,27 +43,25 @@ export class Choices {
|
|||
};
|
||||
|
||||
// Merge options with user options
|
||||
this.options = this.extend(DEFAULT_OPTIONS, USER_OPTIONS || {});
|
||||
this.store = STORE;
|
||||
this.options = this.extend(defaultOptions, userOptions || {});
|
||||
this.store = store;
|
||||
|
||||
this.initialised = false;
|
||||
this.supports = 'querySelector' in document && 'addEventListener' in document && 'classList' in FAKE_EL;
|
||||
this.supports = 'querySelector' in document && 'addEventListener' in document && 'classList' in fakeEl;
|
||||
|
||||
// Retrieve elements
|
||||
// Retrieve triggering element (i.e. element with 'data-choice' trigger)
|
||||
this.element = this.options.element;
|
||||
|
||||
// If input already has values, parse the array, otherwise create a blank array
|
||||
// Hmm, this should really map this.store
|
||||
this.valueArray = this.element.value !== '' ? this.cleanInputValue(this.element.value) : [];
|
||||
|
||||
// How many values in array
|
||||
this.valueCount = this.valueArray.length;
|
||||
|
||||
// Bind methods
|
||||
this.onClick = this.onClick.bind(this);
|
||||
this.onKeyDown = this.onKeyDown.bind(this);
|
||||
this.onChange = this.onChange.bind(this);
|
||||
this.onFocus = this.onFocus.bind(this);
|
||||
this.onBlur = this.onChange.bind(this);
|
||||
this.onClick = this.onClick.bind(this);
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
@ -93,7 +92,7 @@ export class Choices {
|
|||
|
||||
// Loop through each passed argument
|
||||
for (let i = 0; i < length; i++) {
|
||||
// Store argument at position i
|
||||
// store argument at position i
|
||||
let obj = arguments[i];
|
||||
|
||||
// If we are in fact dealing with an object, merge it. Otherwise throw error
|
||||
|
@ -131,74 +130,74 @@ export class Choices {
|
|||
}
|
||||
|
||||
onKeyDown(e) {
|
||||
const CTRLDOWN_KEY = e.ctrlKey || e.metaKey;
|
||||
const DELETE_KEY = 8 || 46;
|
||||
const ENTER_KEY = 13;
|
||||
const A_KEY = 65;
|
||||
const ctrlDownKey = e.ctrlKey || e.metaKey;
|
||||
const deleteKey = 8 || 46;
|
||||
const enterKey = 13;
|
||||
const aKey = 65;
|
||||
|
||||
// If CTRL + A or CMD + A have been pressed and there are items to select
|
||||
if (CTRLDOWN_KEY && e.keyCode === A_KEY && this.list && this.list.children) {
|
||||
let handleSelectAll = () => {
|
||||
if(this.options.removeItems && !this.input.value) {
|
||||
this.selectAll(this.list.children);
|
||||
}
|
||||
};
|
||||
// If we are typing in the input
|
||||
if(e.target === this.input) {
|
||||
// If CTRL + A or CMD + A have been pressed and there are items to select
|
||||
if (ctrlDownKey && e.keyCode === aKey && this.list && this.list.children) {
|
||||
let handleSelectAll = () => {
|
||||
if(this.options.removeItems && !this.input.value && this.options.selectAll) {
|
||||
this.selectAll(this.list.children);
|
||||
}
|
||||
};
|
||||
|
||||
handleSelectAll();
|
||||
}
|
||||
handleSelectAll();
|
||||
}
|
||||
|
||||
// If enter key is pressed and the input has a value
|
||||
if (e.keyCode === ENTER_KEY && e.target.value) {
|
||||
let value = this.input.value;
|
||||
// If enter key is pressed and the input has a value
|
||||
if (e.keyCode === enterKey && e.target.value) {
|
||||
let value = this.input.value;
|
||||
|
||||
let handleEnter = () => {
|
||||
let canUpdate = true;
|
||||
let handleEnter = () => {
|
||||
let canUpdate = true;
|
||||
|
||||
// If there is a max entry limit and we have reached that limit
|
||||
// don't update
|
||||
if (this.options.maxItems && this.options.maxItems <= this.list.children.length) {
|
||||
canUpdate = false;
|
||||
}
|
||||
|
||||
// If no duplicates are allowed, and the value already exists
|
||||
// in the array, don't update
|
||||
if (this.options.allowDuplicates === false && this.element.value) {
|
||||
if (this.valueArray.indexOf(value) > -1) {
|
||||
// If there is a max entry limit and we have reached that limit
|
||||
// don't update
|
||||
if (this.options.maxItems && this.options.maxItems <= this.list.children.length) {
|
||||
canUpdate = false;
|
||||
}
|
||||
}
|
||||
|
||||
// All is good, update
|
||||
if (canUpdate) {
|
||||
if(this.element.type === 'text') {
|
||||
let canAddItem = true;
|
||||
// If no duplicates are allowed, and the value already exists
|
||||
// in the array, don't update
|
||||
if (this.options.allowDuplicates === false && this.element.value) {
|
||||
if (this.valueArray.indexOf(value) > -1) {
|
||||
canUpdate = false;
|
||||
}
|
||||
}
|
||||
|
||||
// If a user has supplied a regular expression filter
|
||||
if(this.options.regexFilter) {
|
||||
// Determine whether we can update based on whether
|
||||
// our regular expression passes
|
||||
canAddItem = this.regexFilter(value);
|
||||
// All is good, update
|
||||
if (canUpdate) {
|
||||
if(this.element.type === 'text') {
|
||||
let canAddItem = true;
|
||||
|
||||
// If a user has supplied a regular expression filter
|
||||
if(this.options.regexFilter) {
|
||||
// Determine whether we can update based on whether
|
||||
// our regular expression passes
|
||||
canAddItem = this.regexFilter(value);
|
||||
}
|
||||
|
||||
// All is good, add
|
||||
if(canAddItem) {
|
||||
this.addItem(this.list, value);
|
||||
this.updateInputValue(value);
|
||||
this.clearInput(this.element);
|
||||
}
|
||||
}
|
||||
|
||||
// All is good, add
|
||||
if(canAddItem) {
|
||||
this.addItem(this.list, value);
|
||||
this.updateInputValue(value);
|
||||
this.clearInput(this.element);
|
||||
this.unselectAll(this.list.children);
|
||||
}
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
handleEnter();
|
||||
handleEnter();
|
||||
}
|
||||
}
|
||||
|
||||
// If backspace or delete key is pressed and the input has no value
|
||||
if (e.keyCode === DELETE_KEY && !e.target.value) {
|
||||
if (e.keyCode === deleteKey && !e.target.value) {
|
||||
|
||||
let handleBackspaceKey = () => {
|
||||
if(this.options.removeItems) {
|
||||
|
@ -206,14 +205,14 @@ export class Choices {
|
|||
let selectedItems = this.list.querySelectorAll('.is-selected');
|
||||
let lastItem = currentListItems[currentListItems.length - 1];
|
||||
|
||||
if(lastItem) {
|
||||
lastItem.classList.add('is-selected');
|
||||
if(lastItem && !this.options.editItems) {
|
||||
this.selectItem(lastItem);
|
||||
}
|
||||
|
||||
// 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 === 1) {
|
||||
this.input.value = lastItem.innerHTML;
|
||||
this.removeItem(lastItem);
|
||||
} else {
|
||||
|
@ -228,36 +227,30 @@ export class Choices {
|
|||
}
|
||||
}
|
||||
|
||||
onFocus(e) {
|
||||
|
||||
}
|
||||
|
||||
onClick(e) {
|
||||
if(e.target.tagName === 'LI') {
|
||||
let item = e.target;
|
||||
|
||||
}
|
||||
let handleClick = (item) => {
|
||||
let passedId = item.getAttribute('data-choice-id');
|
||||
let items = this.list.children;
|
||||
|
||||
onChange(e) {
|
||||
// We only want to select one item with a click
|
||||
// so we unselect any items that aren't the target
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
let singleItem = items[i];
|
||||
let id = singleItem.getAttribute('data-choice-id');;
|
||||
|
||||
}
|
||||
|
||||
/* Event listeners */
|
||||
|
||||
addEventListeners(el) {
|
||||
el.addEventListener('click', this.onClick);
|
||||
el.addEventListener('keyup', this.onKeyUp);
|
||||
el.addEventListener('keydown', this.onKeyDown);
|
||||
el.addEventListener('change', this.onChange);
|
||||
el.addEventListener('focus', this.onFocus);
|
||||
el.addEventListener('blur', this.onBlur);
|
||||
}
|
||||
|
||||
removeEventListeners(el) {
|
||||
el.removeEventListener('click', this.onClick);
|
||||
el.removeEventListener('keyup', this.onKeyUp);
|
||||
el.removeEventListener('keydown', this.onKeyDown);
|
||||
el.removeEventListener('change', this.onChange);
|
||||
el.removeEventListener('focus', this.onFocus);
|
||||
el.removeEventListener('blur', this.onBlur);
|
||||
if(id === passedId && !singleItem.classList.contains('is-selected')) {
|
||||
this.selectItem(singleItem);
|
||||
} else {
|
||||
this.unselectItem(singleItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handleClick(item);
|
||||
}
|
||||
}
|
||||
|
||||
/* Methods */
|
||||
|
@ -274,26 +267,24 @@ export class Choices {
|
|||
return passesTest;
|
||||
}
|
||||
|
||||
getPlaceholder() {}
|
||||
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) {
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
let item = items[i];
|
||||
|
||||
if (!item.classList.contains('is-selected')) {
|
||||
item.classList.add('is-selected');
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
unselectAll(items) {
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
let item = items[i];
|
||||
|
||||
if (item.classList.contains('is-selected')) {
|
||||
item.classList.remove('is-selected');
|
||||
}
|
||||
this.selectItem(item);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -333,11 +324,8 @@ export class Choices {
|
|||
|
||||
let id = this.store.getState().length + 1;
|
||||
|
||||
// Create new list element
|
||||
let item = document.createElement('li');
|
||||
item.classList.add('choices__item');
|
||||
item.textContent = passedValue;
|
||||
item.id = id;
|
||||
// Create new list element
|
||||
let item = strToEl(`<li class="choices__item" data-choice-id=${id}>${passedValue}</li>`);
|
||||
|
||||
// Append it to list
|
||||
parent.appendChild(item);
|
||||
|
@ -361,7 +349,7 @@ export class Choices {
|
|||
return;
|
||||
}
|
||||
|
||||
let id = item.id;
|
||||
let id = item.getAttribute('data-choice-id');
|
||||
let value = item.innerHTML;
|
||||
item.parentNode.removeChild(item);
|
||||
|
||||
|
@ -396,21 +384,20 @@ export class Choices {
|
|||
}
|
||||
|
||||
renderTextInput() {
|
||||
// Template:
|
||||
//
|
||||
// <div class="choices choices--active">
|
||||
// <div class="choices__inner">
|
||||
// <input id="1" type="text" data-choice="" class="choices__input choices__input--hidden" tabindex="-1" style="display:none;" aria-hidden="true">
|
||||
// <ul class="choices__list choices__list--items"></ul>
|
||||
// <input type="text" class="choices__input choices__input--cloned">
|
||||
// </div>
|
||||
// </div>
|
||||
/*
|
||||
Template:
|
||||
|
||||
let containerOuter = document.createElement('div');
|
||||
containerOuter.className = 'choices choices--active';
|
||||
<div class="choices choices--active">
|
||||
<div class="choices__inner">
|
||||
<input id="1" type="text" data-choice="" class="choices__input choices__input--hidden" tabindex="-1" style="display:none;" aria-hidden="true">
|
||||
<ul class="choices__list choices__list--items"></ul>
|
||||
<input type="text" class="choices__input choices__input--cloned">
|
||||
</div>
|
||||
</div>
|
||||
*/
|
||||
|
||||
let containerInner = document.createElement('div');
|
||||
containerInner.className = 'choices__inner';
|
||||
let containerOuter = strToEl('<div class="choices choices--active"></div>');
|
||||
let containerInner = strToEl('<div class="choices__inner"></div>');
|
||||
|
||||
// Hide passed input
|
||||
this.element.classList.add('choices__input', 'choices__input--hidden');
|
||||
|
@ -424,12 +411,8 @@ export class Choices {
|
|||
// Wrapper inner container with outer container
|
||||
wrap(containerInner, containerOuter);
|
||||
|
||||
let list = document.createElement('ul');
|
||||
list.className = 'choices__list choices__list--items';
|
||||
|
||||
let input = document.createElement('input');
|
||||
input.type = 'text';
|
||||
input.className = 'choices__input choices__input--cloned';
|
||||
let list = strToEl('<ul class="choices__list choices__list--items"></ul>');
|
||||
let input = strToEl('<input type="text" class="choices__input choices__input--cloned">');
|
||||
|
||||
if (input.placeholder) {
|
||||
input.placeholder = this.element.placeholder;
|
||||
|
@ -456,70 +439,10 @@ export class Choices {
|
|||
}
|
||||
|
||||
// Trigger event listeners
|
||||
this.addEventListeners(this.input);
|
||||
document.addEventListener('keydown', this.onKeyDown);
|
||||
this.list.addEventListener('click', this.onClick);
|
||||
}
|
||||
|
||||
renderSelectInput() {
|
||||
let containerOuter = document.createElement('div');
|
||||
containerOuter.className = 'choices choices--active';
|
||||
|
||||
let containerInner = document.createElement('div');
|
||||
containerInner.className = 'choices__inner';
|
||||
|
||||
// Hide passed input
|
||||
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');
|
||||
|
||||
// Wrap input in container preserving DOM ordering
|
||||
wrap(this.element, containerInner);
|
||||
|
||||
// Wrapper inner container with outer container
|
||||
wrap(containerInner, containerOuter);
|
||||
|
||||
let options = document.createElement('ul');
|
||||
options.className = 'choices__list choices__list--options';
|
||||
|
||||
let input = document.createElement('input');
|
||||
input.type = 'text';
|
||||
input.className = 'choices__input choices__input--cloned';
|
||||
|
||||
containerInner.appendChild(input);
|
||||
containerInner.appendChild(options);
|
||||
containerOuter.appendChild(containerInner);
|
||||
|
||||
this.containerOuter = containerOuter;
|
||||
this.containerInner = containerInner;
|
||||
this.input = input;
|
||||
this.list = null;
|
||||
this.options = options;
|
||||
|
||||
let initialOptions = this.element.children;
|
||||
|
||||
if (initialOptions) {
|
||||
for (let i = 0; i < initialOptions.length; i++) {
|
||||
let parentOption = initialOptions[i];
|
||||
|
||||
if(parentOption.tagName === 'OPTGROUP') {
|
||||
this.addItem(this.options, parentOption.label);
|
||||
for (let j = 0; j < parentOption.children.length; j++) {
|
||||
let childOption = parentOption.children[j];
|
||||
this.addItem(this.options, childOption.innerHTML);
|
||||
}
|
||||
} else if(parentOption.tagName === 'OPTION') {
|
||||
this.addItem(this.options, parentOption.innerHTML);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Trigger event listeners
|
||||
this.addEventListeners(this.input);
|
||||
}
|
||||
|
||||
renderMultipleSelectInput() {
|
||||
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.options.debug) console.debug('Render');
|
||||
|
@ -529,13 +452,13 @@ export class Choices {
|
|||
this.renderTextInput();
|
||||
break;
|
||||
case "select-one":
|
||||
this.renderSelectInput();
|
||||
// this.renderSelectInput();
|
||||
break;
|
||||
case "select-multiple":
|
||||
this.renderMultipleSelectInput();
|
||||
// this.renderMultipleSelectInput();
|
||||
break;
|
||||
default:
|
||||
rthis.renderTextInput();
|
||||
this.renderTextInput();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -558,8 +481,8 @@ export class Choices {
|
|||
|
||||
let choices1 = new Choices({
|
||||
element : input1,
|
||||
delimiter: ' ',
|
||||
maxItems: 5,
|
||||
// delimiter: ' ',
|
||||
// maxItems: 5,
|
||||
// callbackOnRemoveItem: function(value) {
|
||||
// console.log(value);
|
||||
// },
|
||||
|
@ -568,27 +491,27 @@ export class Choices {
|
|||
// }
|
||||
});
|
||||
|
||||
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()}`
|
||||
// });
|
||||
})();
|
|
@ -1,4 +1,4 @@
|
|||
export let hasClass = (elem, className) => {
|
||||
export const hasClass = (elem, className) => {
|
||||
return new RegExp(' ' + className + ' ').test(' ' + elem.className + ' ');
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@ export let hasClass = (elem, className) => {
|
|||
* @param {String} str String to capitalise
|
||||
* @return {String} Capitalised string
|
||||
*/
|
||||
export let capitalise = function(str) {
|
||||
export const capitalise = function(str) {
|
||||
return str.replace(/\w\S*/g, function(txt){
|
||||
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
|
||||
});
|
||||
|
@ -19,7 +19,7 @@ export let capitalise = function(str) {
|
|||
* @param {Object} obj Object to be tested
|
||||
* @return {Boolean}
|
||||
*/
|
||||
export let isType = function(type, obj) {
|
||||
export const isType = function(type, obj) {
|
||||
var clas = Object.prototype.toString.call(obj).slice(8, -1);
|
||||
return obj !== undefined && obj !== null && clas === type;
|
||||
};
|
||||
|
@ -29,7 +29,7 @@ export let isType = function(type, obj) {
|
|||
* CSS transition end event listener
|
||||
* @return
|
||||
*/
|
||||
export let whichTransitionEvent = function(){
|
||||
export const whichTransitionEvent = function(){
|
||||
var t,
|
||||
el = document.createElement("fakeelement");
|
||||
|
||||
|
@ -51,7 +51,7 @@ export let whichTransitionEvent = function(){
|
|||
* CSS animation end event listener
|
||||
* @return
|
||||
*/
|
||||
export let whichAnimationEvent = function() {
|
||||
export const whichAnimationEvent = function() {
|
||||
var t,
|
||||
el = document.createElement('fakeelement');
|
||||
|
||||
|
@ -77,7 +77,7 @@ export let whichAnimationEvent = function() {
|
|||
* @param {String} selector Class to find
|
||||
* @return {Array} Array of parent elements
|
||||
*/
|
||||
export let getParentsUntil = function(elem, parent, selector) {
|
||||
export const getParentsUntil = function(elem, parent, selector) {
|
||||
var parents = [];
|
||||
// Get matches
|
||||
for (; elem && elem !== document; elem = elem.parentNode) {
|
||||
|
@ -156,7 +156,7 @@ export let getParentsUntil = function(elem, parent, selector) {
|
|||
}
|
||||
};
|
||||
|
||||
export let wrap = function (element, wrapper) {
|
||||
export const wrap = function (element, wrapper) {
|
||||
wrapper = wrapper || document.createElement('div');
|
||||
if (element.nextSibling) {
|
||||
element.parentNode.insertBefore(wrapper, element.nextSibling);
|
||||
|
@ -166,7 +166,7 @@ export let wrap = function (element, wrapper) {
|
|||
return wrapper.appendChild(element);
|
||||
};
|
||||
|
||||
export let getSiblings = function (elem) {
|
||||
export const getSiblings = function (elem) {
|
||||
var siblings = [];
|
||||
var sibling = elem.parentNode.firstChild;
|
||||
for ( ; sibling; sibling = sibling.nextSibling ) {
|
||||
|
@ -183,7 +183,7 @@ export let getSiblings = function (elem) {
|
|||
* @param {[type]} cls Class of parent
|
||||
* @return {NodeElement} Found parent element
|
||||
*/
|
||||
export let findAncestor = function(el, cls) {
|
||||
export const findAncestor = function(el, cls) {
|
||||
while ((el = el.parentElement) && !el.classList.contains(cls));
|
||||
return el;
|
||||
};
|
||||
|
@ -195,7 +195,7 @@ export let findAncestor = function(el, cls) {
|
|||
* @param {Boolean} immediate If passed, trigger the function on the leading edge, instead of the trailing.
|
||||
* @return {Function} A function will be called after it stops being called for a given delay
|
||||
*/
|
||||
export let debounce = function(func, wait, immediate) {
|
||||
export const debounce = function(func, wait, immediate) {
|
||||
var timeout;
|
||||
return function() {
|
||||
var context = this,
|
||||
|
@ -217,7 +217,7 @@ export let debounce = function(func, wait, immediate) {
|
|||
* @param {NodeElement} el Element to test for
|
||||
* @return {Number} Elements Distance from top of page
|
||||
*/
|
||||
export let getElemDistance = function(el) {
|
||||
export const getElemDistance = function(el) {
|
||||
var location = 0;
|
||||
if (el.offsetParent) {
|
||||
do {
|
||||
|
@ -234,7 +234,7 @@ export let getElemDistance = function(el) {
|
|||
* @param {Node} el Element to test for
|
||||
* @return {Number} Height of element
|
||||
*/
|
||||
export let getElementOffset = function(el, offset) {
|
||||
export const getElementOffset = function(el, offset) {
|
||||
var elOffset = offset;
|
||||
if(elOffset > 1) elOffset = 1;
|
||||
if(elOffset > 0) elOffset = 0;
|
||||
|
@ -247,7 +247,7 @@ export let getElementOffset = function(el, offset) {
|
|||
* @private
|
||||
* @return {String} Position of scroll
|
||||
*/
|
||||
export let getScrollPosition = function(position) {
|
||||
export const getScrollPosition = function(position) {
|
||||
if(position === 'bottom') {
|
||||
// Scroll position from the bottom of the viewport
|
||||
return Math.max((window.scrollY || window.pageYOffset) + (window.innerHeight || document.documentElement.clientHeight));
|
||||
|
@ -263,7 +263,7 @@ export let getScrollPosition = function(position) {
|
|||
* @return {String} Position of scroll
|
||||
* @return {Boolean}
|
||||
*/
|
||||
export let isInView = function(el, position, offset) {
|
||||
export const isInView = function(el, position, offset) {
|
||||
// If the user has scrolled further than the distance from the element to the top of its parent
|
||||
return this.getScrollPosition(position) > (this.getElemDistance(el) + this.getElementOffset(el, offset)) ? true : false;
|
||||
};
|
||||
|
@ -273,7 +273,7 @@ export let isInView = function(el, position, offset) {
|
|||
* @param {String} Initial string/html
|
||||
* @return {String} Sanitised string
|
||||
*/
|
||||
export let stripHTML = function(html) {
|
||||
export const stripHTML = function(html) {
|
||||
let el = document.createElement("DIV");
|
||||
el.innerHTML = html;
|
||||
return el.textContent || el.innerText || "";
|
||||
|
@ -285,7 +285,7 @@ export let stripHTML = function(html) {
|
|||
* @param {String} animation Animation class to add to element
|
||||
* @return
|
||||
*/
|
||||
export let addAnimation = (el, animation) => {
|
||||
export const addAnimation = (el, animation) => {
|
||||
let animationEvent = whichAnimationEvent();
|
||||
|
||||
let removeAnimation = () => {
|
||||
|
@ -304,6 +304,26 @@ export let addAnimation = (el, animation) => {
|
|||
* @param {Number} max Maximum range
|
||||
* @return {Number} Random number
|
||||
*/
|
||||
export let getRandomNumber = function(min, max) {
|
||||
export const getRandomNumber = function(min, max) {
|
||||
return Math.floor(Math.random() * (max - min) + min);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn a string into a node
|
||||
* @param {String} String to convert
|
||||
* @return {Node} Converted node element
|
||||
*/
|
||||
export const strToEl = (function() {
|
||||
var tmpEl = document.createElement('div');
|
||||
return function(str) {
|
||||
var r;
|
||||
tmpEl.innerHTML = str;
|
||||
r = tmpEl.children[0];
|
||||
|
||||
while (tmpEl.firstChild) {
|
||||
tmpEl.removeChild(tmpEl.firstChild);
|
||||
}
|
||||
|
||||
return r;
|
||||
};
|
||||
}());
|
|
@ -1,4 +1,3 @@
|
|||
// Array of choices
|
||||
const choices = (state = [], action) => {
|
||||
switch (action.type) {
|
||||
case 'ADD_ITEM':
|
||||
|
@ -7,17 +6,29 @@ const choices = (state = [], action) => {
|
|||
id: parseInt(action.id),
|
||||
value: action.value,
|
||||
element: action.element,
|
||||
active: true
|
||||
active: true,
|
||||
selected: false
|
||||
}];
|
||||
|
||||
case 'REMOVE_ITEM':
|
||||
// Remove item from items array
|
||||
return state.filter(function(item) {
|
||||
if(item.id !== parseInt(action.id)) {
|
||||
return item;
|
||||
// Set item to inactive
|
||||
return state.map((item) => {
|
||||
if(item.id === parseInt(action.id)) {
|
||||
item.active = false;
|
||||
}
|
||||
return item;
|
||||
});
|
||||
|
||||
case 'SELECT_ITEM':
|
||||
return state.map((item) => {
|
||||
if(item.id === parseInt(action.id)) {
|
||||
item.selected = action.value;
|
||||
}
|
||||
|
||||
return item;
|
||||
});
|
||||
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
</head>
|
||||
<body>
|
||||
<label for="1">Text input with no values and a limit of 5 items</label>
|
||||
<input id="1" type="text" data-choice>
|
||||
|
||||
<input id="1" type="text" data-choice value="preset-1, preset-2">
|
||||
<!--
|
||||
<label for="2">Text input with preset values, custom classes and a placeholder. No duplicate values allowed</label>
|
||||
<input id="2" type="text" data-choice value="preset-1, preset-2" placeholder="This is a placeholder" class="custom class">
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
|||
<input id="4" type="text" data-choice value="josh@joshuajohnson.co.uk, joe@bloggs.co.uk" placeholder="This is a placeholder">
|
||||
|
||||
<label for="5">Text input that prepends and appends a value to each item</label>
|
||||
<input id="5" type="text" data-choice value="preset-1, preset-2" placeholder="This is a placeholder">
|
||||
<input id="5" type="text" data-choice value="preset-1, preset-2" placeholder="This is a placeholder"> -->
|
||||
|
||||
<!-- <label for="3">Select input with two options</label>
|
||||
<select id="3" name="3" data-choice>
|
||||
|
|
Loading…
Reference in a new issue