On my web page there are 2 selectors - one is a tab, and another is a dropdown. Based on user clicks on the tab and the dropdown, I get the click value and push it unto an array. There are at most 2 elements in the array - both elements need to be the unique value mapped to tab and dropdown selection respectively:
Tag1 -> value from Tab selection
Tag2 -> value from drop down
To add/update the array to a specific location, I used Array.prototype.splice()
I managed to push the selection values from the tab and the dropdown in the array. However, I run into some problem scenarios as described below.
Kindly see test code below:
// Get all tabs
var tabs = document.querySelectorAll('.tab')
// Get select element
var select = document.querySelector('select')
// Create tag array
var tags = []
var tagText = document.querySelector('#tags')
// Register click event listeners for tabs
if (tabs.length > 0) {
tabs.forEach(function (tab) {
tab.addEventListener('click', handleTabClick, true)
})
}
// Register click event listener for select element
if (select) {
select.addEventListener('change', handleSelectChange, true)
}
// Handle tab click
function handleTabClick(e) {
var currentElement = e.target
// Remove all active modifiers
tabs.forEach(function (tab) {
tab.classList.remove('active')
})
// Apply the active modifer to the current element
currentElement.classList.add('active')
// Update the UI showing the correct pane by ID
var id = currentElement.dataset.targetPane
if (id != 'tab-all') {
// Add selected id to array
tags.splice(0, 1, id)
} else {
tags.splice(0, 1, '')
}
tagText.innerHTML = tags
}
// Handle select change
function handleSelectChange(e) {
var id = e.target.value
if (id != 'all') {
// Add selected id to array
tags.splice(1, 1, id)
} else {
tags.splice(1, 1, '')
}
tagText.innerHTML = tags
}
.tabs {
padding-left: 0;
list-style-type: none;
display: flex;
}
.tab {
flex: 1;
text-align: center;
padding: 10px;
cursor: pointer;
color: #000000;
border: 1px solid #d1d1d1;
}
.active {
border-bottom: 3px solid red;
}
Tab options (1st in tags array): Tag 1
<ul class="tabs">
<li class="tab active" data-target-pane="tab-all">All
</li>
<li class="tab" data-target-pane="finance">
Finance
</li>
<li class="tab" data-target-pane="energy">
Energy
</li>
</ul>
Dropdown options (2nd in tags array): Tag 2
<label class="select">
<select>
<option value="all" selected="">All</option>
<option value="whitepaper">Whitepaper</option>
<option value="articles">Articles</option>
<option value="video">Video</option>
</select>
</label>
<p>Return tags array: <b><span id="tags"></span></b></p>
<p>Tag 1 -> value from Tab<br>
Tag 2 -> value from dropdown<br><br>Expect the tags array output to always be [Tag 1 , Tag 2].<br>Max 2 item in array. If user selected "All", empty the previous selection within the same Tag (1 or 2) array location.</p>
Problem scenario (undesirable result)
1) If the user first selects a dropdown option (Tag2) and than selects another dropdown option (Tag2): the Tags array then has [Tag2, Tag2]. Expected: [Tag2]
2) If the user first selects a dropdown option (Tag2) and than selects a tab (Tag1): the Tags array first has [Tag2] and it gets replaced with [Tag1]. Expected: [Tag2 , Tag1]
3) If the user first selects a dropdown option (Tag2) and than selects another dropdown option (Tag2), and lastly selects the dropdown value "All" (Tag2): the Tags array first has [Tag2, Tag2] and with "All" selected it becomes [Tag2,]. Expected: first [Tag2] and with "All" selected, []
Ideal scenario
1) If the user first selected a tab (Tag1) before selecting a dropdown option (Tag2): Tags array should get [Tag1, Tag2].
2) If the user selected "All", empty the previous selection within the same Tag(1 or 2) array location. For example, user first selected a tab (Tag1) and than selects tab "All". Tags array gets []. If the user first selected a tab (Tag1) and selected a dropdown option (Tag2), and than selects the dropdown "All" value. Tag array should become [Tag1]
I expect the tags array to be one of the following:
1) Max 2 items in array -> [Tag1 , Tag2] or [Tag2 , Tag1]
2) Single array element [Tag1] or [Tag2]
But it should never have [Tag1, Tag1] or [Tag2, Tag2]
In short, the array should have unique values corresponding to the tab selection and dropdown selection.
As you sometimes want a result with [Tag 1, Tag 2] and other times [Tag 2, Tag 1], it would be good to remember in which slot you last stored the Tag 1 selection, so that you know which of the two to replace.
I will assume that the last made selection will always be the last value in the array as well.
So I have introduced the variable tabIndex
which is either 0 or 1. Also, I have adapted the code so that it first removes the current value from the array (from the index that can be derived from tabIndex
) and then pushes the selected value to the end of the array, updating tabIndex
at the same time.
// Get all tabs
var tabs = document.querySelectorAll('.tab')
// Get select element
var select = document.querySelector('select')
// Create tag array
var tags = []
var tagText = document.querySelector('#tags')
var tabIndex = 0;
// Register click event listeners for tabs
tabs.forEach(function (tab) {
tab.addEventListener('click', handleTabClick, true)
})
// Register click event listener for select element
if (select) {
select.addEventListener('change', handleSelectChange, true)
}
// Handle tab click
function handleTabClick(e) {
var currentElement = e.target
// Remove all active modifiers
tabs.forEach(function (tab) {
tab.classList.remove('active')
})
// Apply the active modifer to the current element
currentElement.classList.add('active')
// Update the UI showing the correct pane by ID
var id = currentElement.dataset.targetPane
tags.splice(tabIndex, 1)
if (id != 'tab-all') {
// Add selected id to array
tabIndex = tags.length
tags.push(id)
}
tagText.textContent = JSON.stringify(tags)
}
// Handle select change
function handleSelectChange(e) {
var id = e.target.value
tags.splice(1-tabIndex, 1)
if (id != 'all') {
// Add selected id to array
tabIndex = 1 - tags.length;
tags.push(id)
}
tagText.textContent = JSON.stringify(tags)
}
.tabs {
padding-left: 0;
list-style-type: none;
display: flex;
}
.tab {
flex: 1;
text-align: center;
padding: 10px;
cursor: pointer;
color: #000000;
border: 1px solid #d1d1d1;
}
.active {
border-bottom: 3px solid red;
}
Tab options (1st in tags array): Tag 1
<ul class="tabs">
<li class="tab active" data-target-pane="tab-all">All</li>
<li class="tab" data-target-pane="finance">Finance</li>
<li class="tab" data-target-pane="energy">Energy</li>
</ul>
Dropdown options (2nd in tags array): Tag 2
<label class="select">
<select>
<option value="all" selected="">All</option>
<option value="whitepaper">Whitepaper</option>
<option value="articles">Articles</option>
<option value="video">Video</option>
</select>
</label>
<p>Return tags array: <b><span id="tags"></span></b></p>
<p>Tag 1 -> value from Tab<br>
Tag 2 -> value from dropdown<br><br>Expect the tags array output to always be [Tag 1 , Tag 2].<br>Max 2 item in array. If user selected "All", empty the previous selection within the same Tag (1 or 2) array location.</p>