EDIT: na potrzeby tego pytania stworzyłem fiddle: https://jsfiddle.net/8p45tf3k/
Paradoksalnie, przy hardkodowaniu niegenerycznych i nierenderowanych na serwerze wartości, wszystko działa OK. Natomiast u mnie wciąż ten sam bug, nawet z wartościami "na sztywno".
PYTANIE:
Hej, na początku samym zaznaczam, że nie mam za wiele do czynienia z JS, stąd moje pytanie do bardziej doświadczonych. W swoim projekcie nie chciałem korzystać z rozwiązań dużych bibliotek typu jQuery bądź Bootstrap, jednak zaszła potrzeba poradzenia sobie jakoś w miarę elegancko z elementami oznaczonymi tagiem select
.
Nie udało mi się znaleźć jakiegoś dobrego gotowca, więc posiedziałem kilka godzin i udało mi się stworzyć coś od podstaw, w miarę generycznego, może nie do końca eleganckiego, choć moje wymagania spełnia i wykorzystuje jedynie vanilla JS i CSS .
Jednak pojawił się problem, ponieważ jak dwóch różnych elementach select
na liście opcji pojawi się obiekt o tej samej wartości oraz z tym samym id (co ma prawo się zdarzyć), wtedy zaznaczany jest ten z pierwszego renderowanego bodajże elementu:
<input type="checkbox" id="@item" onchange="addSelection(this)" />@item
I zastanawiam się **jak jeszcze mogę dodać wyjątkowości takiemu elementowi **checkbox
, jaki opcji
. Zabrakło mi pomysłów. Poniżej kod dla przycisku oraz JS. CSS pomijam, wydaje mi się że nie ma tu wiele do czynienia.
<!--multiple select-->
<div class="multiselect inputSelect barItem" id="dupa">
<div class="selectBox">
<div id="arrowSel"></div>
<span class="oryginalText">Select flags</span>
<div>Select flags</div>
<select asp-for="Dupa" class="inputSelect" id="selectdupa" multiple>
@foreach (string item in ViewBag.Dupa)
{
<option>@item</option>
}
</select>
</div>
<div class="checkboxes" id="checkboxesdupa">
@foreach (string item in ViewBag.Dupa)
{
<label for="@item">
<input type="checkbox" id="@item" onchange="addSelection(this)" />@item
</label>
}
</div>
</div>
<script>
//on checkbox change
function addSelection(checkbox) {
const checkboxes = checkbox.parentNode.parentNode.id;
console.log(checkboxes);
const selectionId = checkboxes.replace('checkboxes', 'select');
if (checkbox.checked) {
select(true, checkbox, selectionId);
}
else {
select(false, checkbox, selectionId);
}
}
//on checkbox check or uncheck, called by: addSelection
function select(selection, checkbox, selectionId) {
var sel = document.getElementById(selectionId);
var opts = sel.options;
for (var opt, j = 0; opt = opts[j]; j++) {
if (opt.value === checkbox.id) {
opt.selected = selection;
console.log(selection + ' ' + checkbox.id + ' ' + selectionId + ' ' + opt.selected + ' ' + opt.value);
break;
}
}
updatePlaceholder(opts, sel);
}
//on checkbox change
function updatePlaceholder(opts, sel) {
var counter = 0;
for (var opt, j = 0; opt = opts[j]; j++) {
if (opt.selected === true) {
counter++;
}
}
if (counter === 0) {
sel.previousElementSibling.style.color = '#bbbbbb';
sel.previousElementSibling.innerHTML = sel.previousElementSibling.previousElementSibling.innerHTML;
}
else {
sel.previousElementSibling.style.color = 'black';
sel.previousElementSibling.innerHTML = 'Selected: ' + counter;
}
}
//populate checkboxes on selections
function verifyCheckboxes(selectionId, checkboxes) {
var sel = document.getElementById(selectionId);
var opts = sel.options;
for (var opt, j = 0; opt = opts[j]; j++) {
if (opt.selected === true) {
var checkboxesList = checkboxes.getElementsByTagName("input");
for (var i = 0; i < checkboxesList.length; i++) {
if (checkboxesList[i].id == opt.value) {
checkboxesList[i].checked = true;
}
}
updatePlaceholder(opts, sel);
}
}
}
//get all select tag objects
const multiSelections = document.getElementsByClassName('multiselect');
//on click of select tag object
for (var multiSelect, j = 0; multiSelect = multiSelections[j]; j++) {
const checkboxes = document.getElementById("checkboxes" + multiSelect.id);
const selectionId = checkboxes.id.replace('checkboxes', 'select');
const multi = multiSelect;
verifyCheckboxes(selectionId, checkboxes);
window.addEventListener('click', function (e) {
if (multi.contains(e.target)) {
if (checkboxes.style.display === 'block') {
checkboxes.style.display = "none";
} else {
checkboxes.style.display = "block";
};
}
if (!checkboxes.contains(e.target) && !multi.contains(e.target)) {
checkboxes.style.display = "none";
}
if (checkboxes.contains(e.target)) {
checkboxes.style.display = "block";
}
});
}
</script>
I wygląd po kliknięciu głównego przycisku: