From f8b07948dd09d655a488b3ffa9530820f7802146 Mon Sep 17 00:00:00 2001 From: Donatas Date: Sun, 27 Dec 2020 20:11:46 +0200 Subject: [PATCH 1/3] Code reformation, Fixed need for multiple click to select an item, Added data-id attribute to every selection, jQuery update --- js/multiselect.js | 233 +++++++++++++++++++++------------------------- 1 file changed, 107 insertions(+), 126 deletions(-) diff --git a/js/multiselect.js b/js/multiselect.js index 29b256d..e6bf65f 100644 --- a/js/multiselect.js +++ b/js/multiselect.js @@ -1,152 +1,133 @@ const updateContainer = (container, inner, selected, opt) => { - if (selected.length > 0) { - container.value = selected.join(','); - inner.innerText = selected.join(', '); - } else { - container.value = ''; - inner.innerText = opt[0].innerText; - } - container.dispatchEvent(new window.Event('change', { bubbles: true })); + if (selected.length > 0) { + container.value = selected.join(','); + inner.innerText = selected.join(', '); + } else { + container.value = ''; + inner.innerText = opt[0].innerText; + } + container.dispatchEvent(new window.Event('change', {bubbles: true})); }; const buttonToggle = (display, dropdown) => { - display.classList.toggle('multi__dropdown--toggle'); - dropdown.classList.toggle('multi--hidden'); + display.classList.toggle('multi__dropdown--toggle'); + dropdown.classList.toggle('multi--hidden'); }; const map = {}; let multi_idx = 0; const multiSelect = () => { - Array.from(document.querySelectorAll('.multi')) - .filter((multi) => { - return multi.getAttribute('data-multiselect-initialized') === null; - }) - .forEach((el) => { - // stores values of dropdown - map[multi_idx] = []; - // array of options - const { options: opt } = el; - // create container - const container = document.createElement('div'); - // carry over classes - el.classList.forEach((className) => { - container.classList.add(className); - }); + Array.from(document.querySelectorAll('.multi')) + .filter((multi) => { + return multi.getAttribute('data-multiselect-initialized') === null; + }) + .forEach((el) => { + // stores values of dropdown + map[multi_idx] = []; + // array of options + const {options: opt} = el; + // create container + const container = document.createElement('div'); + // carry over classes + el.classList.forEach((className) => { + container.classList.add(className); + }); - // Add data-multiselect-initialized attribute - container.setAttribute('data-multiselect-initialized', true); - container.setAttribute('key', multi_idx); - const key = multi_idx; - // carry over ids if exist - // container.id = el.id; - el.id ? (container.id = el.id) : ''; - // carry over names - el.getAttribute('name') - ? container.setAttribute('name', el.getAttribute('name')) - : ''; - el.getAttribute('onchange') - ? container.setAttribute('onchange', el.getAttribute('onchange')) - : ''; - // container.setAttribute('name', el.getAttribute('name') || ''); - // container.classList.add('multi') + // Add data-multiselect-initialized attribute + container.setAttribute('data-multiselect-initialized', true); + container.setAttribute('key', multi_idx); + const key = multi_idx; + // carry over ids if exist + // container.id = el.id; + el.id ? (container.id = el.id) : ''; + // carry over names + el.getAttribute('name') + ? container.setAttribute('name', el.getAttribute('name')) + : ''; + el.getAttribute('onchange') + ? container.setAttribute('onchange', el.getAttribute('onchange')) + : ''; - // create display - const display = document.createElement('button'); - display.classList.add('multi__display'); + // create display + const display = document.createElement('button'); + display.classList.add('multi__display'); + display.type = 'button'; - // create inner (displays the values) - const inner = document.createElement('div'); - inner.classList.add('multi__inner'); + // create inner (displays the values) + const inner = document.createElement('div'); + inner.classList.add('multi__inner'); - // set innerText to default value - // display.innerText = opt[0].innerText - inner.innerText = opt[0].innerText; - display.value = ''; - // append display to container - container.appendChild(display); - display.appendChild(inner); + // set innerText to default value + inner.innerText = opt[0].innerText; + display.value = ''; + // append display to container + container.appendChild(display); + display.appendChild(inner); - // replace new select element with new container - el.parentNode.replaceChild(container, el); + // replace new select element with new container + el.parentNode.replaceChild(container, el); - // create dropdown - const dropdown = document.createElement('div'); - dropdown.classList.add('multi__dropdown'); - // create ul - const list = document.createElement('ul'); - dropdown.classList.add('multi--hidden'); - // iterate over options, skip first (placeholder) - for (let i = 1; i < opt.length; i++) { - const li = document.createElement('li'); - li.classList.add('multi__li-item'); - // ACCESSIBILITY - // const a = document.createElement('a'); - // a.classList.add('item-anchor'); - // a.setAttribute('role','option'); - // a.setAttribute('tabindex','0'); - // a.innerText=opt[i].innerText - li.innerText = opt[i].innerText; - li.addEventListener('click', (e) => { - e.stopPropagation(); - if (map[key].includes(e.target.innerText)) { - map[key].splice(map[key].indexOf(e.target.innerText), 1); - e.target.classList.remove('multi__li-item--selected'); - } else { - map[key].push(e.target.innerText); - e.target.classList.add('multi__li-item--selected'); - } - // e.target.parentElement.removeChild(e.target); - updateContainer(container, inner, map[key], opt); + // create dropdown + const dropdown = document.createElement('div'); + dropdown.classList.add('multi__dropdown'); + // create ul + const list = document.createElement('ul'); + dropdown.classList.add('multi--hidden'); + // iterate over options, skip first (placeholder) + for (let i = 1; i < opt.length; i++) { + const li = document.createElement('li'); + li.classList.add('multi__li-item'); + // ACCESSIBILITY + li.innerText = opt[i].innerText; + // Edit by DonatasP + li.setAttribute('data-id', opt[i].value); + if (opt[i].selected) { + $(li).addClass('multi__li-item--selected'); + } + $(li).on('click', function (e) { + e.stopPropagation(); + if ($(this).hasClass('multi__li-item--selected')) { + map[key].splice(map[key].indexOf(e.target.innerText), 1); + $(this).removeClass('multi__li-item--selected'); + } else { + map[key].push(e.target.innerText); + $(this).addClass('multi__li-item--selected'); + } + updateContainer(container, inner, map[key], opt); + }); + // li.appendChild(a); + list.appendChild(li); + } + // add event listener to container to show / hide dropdown + container.addEventListener('click', (e) => { + e.stopPropagation(); + buttonToggle(display, dropdown); + }); + // append dropdown to container + container.appendChild(dropdown); + // append ul to dropdown + dropdown.appendChild(list); }); - // li.appendChild(a); - list.appendChild(li); - } - // add event listener to container to show / hide dropdown - container.addEventListener('click', (e) => { - e.stopPropagation(); - buttonToggle(display, dropdown); - // display.classList.toggle('multi__dropdown--toggle'); - // dropdown.classList.toggle('multi--hidden'); - }); - // append dropdown to container - container.appendChild(dropdown); - // append ul to dropdown - dropdown.appendChild(list); - }); - // } - multi_idx++; + // } + multi_idx++; }; // add event listener to window document.addEventListener('click', (e) => { - document.querySelectorAll('.multi__display').forEach((display) => { - display.classList.remove('multi__dropdown--toggle'); - }); + document.querySelectorAll('.multi__display').forEach((display) => { + display.classList.remove('multi__dropdown--toggle'); + }); - document.querySelectorAll('.multi__dropdown').forEach((dropdown) => { - dropdown.classList.add('multi--hidden'); - }); + document.querySelectorAll('.multi__dropdown').forEach((dropdown) => { + dropdown.classList.add('multi--hidden'); + }); }); // // https://stackoverflow.com/questions/799981/document-ready-equivalent-without-jquery document.addEventListener('DOMContentLoaded', function (event) { - //do work - multiSelect(); + //do work + multiSelect(); }); // Refresh Method window.multiSelect = { - refresh() { - multiSelect(); - }, - // addMulti() { - // const root = document.querySelector('#root'); - // const select = document.createElement('select'); - // select.classList.add('multi'); - // const option = document.createElement('option'); - // option.selected = true; - // option.disabled = true; - // option.innerHTML="Default" - // select.appendChild(option); - // const option_two = document.createElement('option'); - // option_two.innerHTML="Banana"; - // select.appendChild(option_two); - // root.appendChild(select); - // } + refresh() { + multiSelect(); + }, }; From e8e89ec942ba3b7692790cbb41c5b26e26e1d89d Mon Sep 17 00:00:00 2001 From: Donatas Date: Mon, 28 Dec 2020 17:08:46 +0200 Subject: [PATCH 2/3] Removed useless width --- css/style.css | 1 - 1 file changed, 1 deletion(-) diff --git a/css/style.css b/css/style.css index 5f2bb5a..7f0a196 100644 --- a/css/style.css +++ b/css/style.css @@ -52,7 +52,6 @@ border-left: .3em solid transparent; } .multi__inner { - width: 180px; overflow: hidden; } .multi__dropdown { From 2583f9fab3a0a5743750177f4e9391022b16b261 Mon Sep 17 00:00:00 2001 From: Donatas Date: Mon, 28 Dec 2020 20:45:47 +0200 Subject: [PATCH 3/3] Added inputs after every dropdown to get data in forms --- js/multiselect.js | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/js/multiselect.js b/js/multiselect.js index e6bf65f..418e079 100644 --- a/js/multiselect.js +++ b/js/multiselect.js @@ -1,3 +1,5 @@ +let multi = []; +let input = []; const updateContainer = (container, inner, selected, opt) => { if (selected.length > 0) { container.value = selected.join(','); @@ -13,6 +15,7 @@ const buttonToggle = (display, dropdown) => { dropdown.classList.toggle('multi--hidden'); }; const map = {}; +const value = {}; let multi_idx = 0; const multiSelect = () => { Array.from(document.querySelectorAll('.multi')) @@ -20,8 +23,14 @@ const multiSelect = () => { return multi.getAttribute('data-multiselect-initialized') === null; }) .forEach((el) => { + if ($(el).attr('multiple') != undefined) { + multi[multi_idx] = true; + } else { + multi[multi_idx] = false; + } // stores values of dropdown map[multi_idx] = []; + value[multi_idx] = []; // array of options const {options: opt} = el; // create container @@ -64,7 +73,10 @@ const multiSelect = () => { // replace new select element with new container el.parentNode.replaceChild(container, el); - + // Update 1.0.1 input field + input[key] = document.createElement('input'); + input[key].type = "hidden"; + input[key].name = $(el).attr('name'); // create dropdown const dropdown = document.createElement('div'); dropdown.classList.add('multi__dropdown'); @@ -82,19 +94,34 @@ const multiSelect = () => { if (opt[i].selected) { $(li).addClass('multi__li-item--selected'); } - $(li).on('click', function (e) { + $(li).on('click', function(e) { e.stopPropagation(); + $(li).trigger('selected-'+key); + // Edited here + let id = $(this).attr('data-id'); if ($(this).hasClass('multi__li-item--selected')) { map[key].splice(map[key].indexOf(e.target.innerText), 1); + value[key].splice(value[key].indexOf(id), 1); $(this).removeClass('multi__li-item--selected'); } else { + if (multi[key] == false) { + map[key] = []; + value[key] = []; + $('.multi__li-item--selected').removeClass('multi__li-item--selected'); + } map[key].push(e.target.innerText); + value[key].push(id); $(this).addClass('multi__li-item--selected'); + if (multi[key] == false) { + container.click(); + } } + input[key].value = value[key]; updateContainer(container, inner, map[key], opt); }); // li.appendChild(a); list.appendChild(li); + container.appendChild(input[key]); } // add event listener to container to show / hide dropdown container.addEventListener('click', (e) => { @@ -105,9 +132,8 @@ const multiSelect = () => { container.appendChild(dropdown); // append ul to dropdown dropdown.appendChild(list); + multi_idx++; }); - // } - multi_idx++; }; // add event listener to window document.addEventListener('click', (e) => {