jQuery tabs - Enable and disable - javascript

I'm having a problem on how to disable tab 3 when the first button is clicked. When I click Activate 2nd tab, the 2nd tab will be enabled, but the 3rd tab will be enabled, too; it should be enabled when I click Activate 3rd tab.
What should I do?
<div class="tab-wrapper" id="tab-wrapper">
<div class="tab-header">
<ul class="tabs">
<li>Step 1</li>
<li>Step 2</li>
<li>Step 3</li>
</ul>
</div>
<div class="tab_container">
<div id="tab1" class="tab_content">
this is tab 1
<button id="button2">Activate 2nd tab</button>
</div>
<div id="tab2" class="tab_content">
this is tab 2
<button id="button3">Activate 3rd tab</button>
</div>
<div id="tab3" class="tab_content">
This is tab3
</div>
</div>
</div>
</body>
<script type="text/javascript">
$(function() {
var activate = false,
tabLinks = $('.tabs a'),
tabContent = $('.tab_container').children();
tabLinks.eq(0).addClass('active'); // Add active class, could possibly go in markup
$('#tab2').hide();
$('#tab3').hide(); // Hide second tab
tabLinks.bind('click', function(e) {
e.preventDefault();
if(activate === true) { // Only do something if button has been clicked
var target = this.hash,
el = $(this);
tabLinks.filter('.active').removeClass('active');
el.addClass('active');
tabContent.hide(); // Hide all
$(target).show(); // Show selected
}
});
$('#button2').bind('click', function() {
activate = true; // Activate tab functionality
tabLinks.eq(1).trigger('click'); // Trigger a click on the second tab link
});
$('#button3').bind('click', function() {
activate = true; // Activate tab functionality
tabLinks.eq(2).trigger('click'); // Trigger a click on the third tab link
});
});
</script>
</html>

You can do something like this (using an array to know if the tab is already activated instead of only one boolean):
$(function() {
var activate = [true, false, false],
tabLinks = $('.tabs a'),
tabContent = $('.tab_container').children();
tabLinks.eq(0).addClass('active'); // Add active class, could possibly go in markup
$('#tab2').hide(); // Hide second tab
$('#tab3').hide(); // Hide second tab
tabLinks.on('click', function(e) {
e.preventDefault();
var idx = $(this).data('index');
if (activate[idx] === true) { // Only do something if button has been clicked
var target = this.hash,
el = $(this);
tabLinks.filter('.active').removeClass('active');
el.addClass('active');
tabContent.hide(); // Hide all
$(target).show(); // Show selected
}
});
$('button').on('click', function() {
var index = $(this).data('index');
activate[index] = true; // Activate tab functionality
tabLinks.eq(index).trigger('click'); // Trigger a click on the second tab link
});
});
* {
padding: 0;
margin: 0;
}
body {
margin: 30px;
}
.tab-wrapper {
width: 500px;
}
.tabs {
overflow: hidden;
list-style: none;
}
.tabs li {
float: left;
margin-right: 10px;
border: 1px solid #ccc;
border-bottom: 0;
}
.tabs a {
display: block;
padding: 5px;
width: 100px;
}
.tabs a.active {
background: #efefef;
}
.tab_container > div {
padding: 10px;
border: 1px solid #ccc;
}
button {
padding: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<div class="tab-wrapper" id="tab-wrapper">
<div class="tab-header">
<ul class="tabs">
<li>step1</li>
<li>step2</li>
<li>step3</li>
</ul>
</div>
<div class="tab_container">
<div id="tab1" class="tab_content">
here is the list of the overview
<button data-index="1">Activate 2nd tab</button>
</div>
<div id="tab2" class="tab_content">
here is the list of the overview
<button data-index="2">Activate 3nd tab</button>
</div>
<div id="tab3" class="tab_content">
End
</div>
</div>
</div>
</body>
You can find the code on jsfiddle too :
https://jsfiddle.net/psLshz3u/

Related

How do I check whether an element is already bound to an event?

Goal
Avoid unnecessary event bindings.
Sample code
Comment box with a reply button for each individual comment
const btns = document.getElementsByClassName('reply-btn');
for (let i = 0; i < btns.length; i++) {
btns[i].addEventListener('click', showCommentContentAsPreview);
}
function showCommentContentAsPreview(e) {
console.log('showCommentContentAsPreview()');
// CHECK IF THIS BUTTON ALREADY BINDED !!!
const previewDiv = document.getElementById('preview');
const commentId = e.target.getAttribute('data-comment-id')
const commentDiv = document.getElementById('comment-' + commentId);
const commentText = commentDiv.querySelector('p').innerText
const closeReplyBtn = previewDiv.querySelector('button');
const previewContent = previewDiv.querySelector('.preview-content');
// set to preview
previewContent.innerText = commentText;
// show reply close button
closeReplyBtn.classList.remove('hidden');
// bind EventListener to "reply close button"
closeReplyBtn.addEventListener('click', closeReply)
function closeReply() {
console.log('bind to btn');
previewContent.innerText = '';
this.removeEventListener('click', closeReply);
closeReplyBtn.classList.add('hidden');
}
}
.hidden {
display: none;
}
.comment {
border-bottom: 1px solid #000;
padding: 5px;
}
.preview {
background-color: #ccc;
padding: 20px;
margin-top: 20px;
}
<div>
<!-- comment list -->
<div id="comment-1" class="comment">
<p>Comment Content 1</p>
<button class="reply-btn" data-comment-id="1">reply</button>
</div>
<div id="comment-2" class="comment">
<p>Comment Content 2</p>
<button class="reply-btn" data-comment-id="2">reply</button>
</div>
</div>
<!-- output -->
<div>
<div id="preview" class="preview">
<div class="preview-content"></div>
<button class="hidden">Close Preview</button>
</div>
</div>
Simulate problem
When you try the example, the following two scenarios occur:
Click reply once and then click "close preview"
Click on reply several times and then on "close preview".
Question
How can I avoid multiple bindings to the same button? I am already thinking about singleton.
Instead of binding a listener to every element in the series, you can bind a single listener once on a common parent of them all, and then use element.matches() to determine if the click target is the one that you want before doing more work. See the following example:
function logTextContent (elm) {
console.log(elm.textContent);
}
function handleClick (ev) {
if (ev.target.matches('.item')) {
logTextContent(ev.target);
}
}
document.querySelector('ul.list').addEventListener('click', handleClick);
<ul class="list">
<li class="item">Item 1</li>
<li class="item">Item 2</li>
<li class="item">Item 3</li>
<li class="item">Item 4</li>
<li class="item">Item 5</li>
</ul>
With the helpful hints from #Zephyr and #jsejcksn I have rewritten the code of the above question. Thus I have achieved my goal of avoiding multiple identical bindings to one element.
const container = document.getElementById('comment-container');
const previewDiv = document.getElementById('preview');
const closeReplyBtn = previewDiv.querySelector('button');
const previewContent = previewDiv.querySelector('.preview-content');
container.addEventListener('click', handleClick);
function handleClick(ev) {
if (ev.target.matches('.reply-btn')) {
if (ev.target.getAttribute('listener') !== 'true') {
removeOtherListenerFlags();
ev.target.setAttribute('listener', 'true');
showCommentContentAsPreview(ev);
}
}
if (ev.target.matches('#preview button')) {
previewContent.innerText = '';
closeReplyBtn.classList.add('hidden');
removeOtherListenerFlags();
}
}
function showCommentContentAsPreview(e) {
console.log('showCommentContentAsPreview()');
const commentId = e.target.getAttribute('data-comment-id')
const commentDiv = document.getElementById('comment-' + commentId);
const commentText = commentDiv.querySelector('p').innerText
// set to preview
previewContent.innerText = commentText;
// show reply close button
closeReplyBtn.classList.remove('hidden');
}
function removeOtherListenerFlags() {
const replyBtns = container.querySelectorAll('.reply-btn')
Object.keys(replyBtns).forEach((el) => {
replyBtns[el].removeAttribute('listener');
})
}
.hidden {
display: none;
}
.comment {
border-bottom: 1px solid #000;
padding: 5px;
}
.preview {
background-color: #ccc;
padding: 20px;
margin-top: 20px;
}
<div id="comment-container">
<div id="comment-listing">
<!-- comment list -->
<div id="comment-1" class="comment">
<p>Comment Content 1</p>
<button class="reply-btn" data-comment-id="1">reply 1</button>
</div>
<div id="comment-2" class="comment">
<p>Comment Content 2</p>
<button class="reply-btn" data-comment-id="2">reply 2</button>
</div>
</div>
<!-- output -->
<div>
<div id="preview" class="preview">
<div class="preview-content"></div>
<button class="hidden">Close Preview</button>
</div>
</div>
</div>
Cool and Thanks!

Adding Multiple Vanilla JavaScript Tabs to the Same Page

Using a variation of the following code, I was able to successfully add one set of Vanilla JavaScript tabs.
Yet how to do I add multiple sets of JavaScript tabs to one page using the same classes in the HTML.
I'm having difficultly creating unique dynamic IDs for the tab selectors and tab content areas using JavaScript. As you can see in https://www.w3.org/TR/wai-aria-practices/examples/tabs/tabs-1/tabs.html, these unique IDs are needed for accessible tags.
var accessibleTabsContainers = document.querySelectorAll('.accessible-tabs-container');
var tabSelector = document.querySelectorAll('.tab-selectors > li');
var tabContent = document.querySelectorAll('.tab-contents > div');
var largeRandNumber = Math.floor((Math.random() * 1000) + 1000);
accessibleTabsContainers.forEach(function(elem, indexAccessibleTabContainer) {
elem.setAttribute('data-id', indexAccessibleTabContainer);
tabSelector.forEach(function(singleTabSelector, i) {
var ariaControlTabContent = 'tab-content-' + largeRandNumber + '-' + i + '_' + indexAccessibleTabContainer;
var tabSelectorId = 'tab-selector-' + largeRandNumber + '-' + i + '_' + indexAccessibleTabContainer;
singleTabSelector.setAttribute('data-id', i);
singleTabSelector.setAttribute('id', tabSelectorId);
singleTabSelector.setAttribute('aria-controls', ariaControlTabContent);
tabContent[i].setAttribute('data-id', i);
tabContent[i].setAttribute('tabindex', 0);
tabContent[i].setAttribute('role', 'tabpanel');
tabContent[i].setAttribute('id', ariaControlTabContent);
tabContent[i].setAttribute('aria-labeledby', tabSelectorId);
if(i === 0) {
tabSelector[i].setAttribute('aria-pressed', 'true');
} else {
tabSelector[i].setAttribute('aria-pressed', 'false');
tabSelector[i].setAttribute('tabindex', -1);
}
});
});
function onTabSelectorClick(e) {
accessibleTabsContainers.forEach(function(accessibleTabsContainer, indexAccessibleTabContainer) {
var tabSelectorSelected = e.target;
var accessibleTabsContainerSelected = tabSelectorSelected.parentElement.parentElement;
if(!tabSelectorSelected.classList.contains('active-tab-selector')) {
var tabSelectorSelectedFromContainer = accessibleTabsContainerSelected.querySelectorAll('.tab-contents > div');
console.log(tabSelectorSelectedFromContainer);
tabSelector.forEach(function(singleTabSelected, i) {
if(tabSelectorSelected.getAttribute('data-id') === tabContent[i].getAttribute('data-id')) {
tabContent[i].classList.add('tab-content-active');
} else {
tabSelector[i].classList.remove('active-tab-selector');
tabSelector[i].setAttribute('aria-pressed', 'false');
tabSelector[i].setAttribute('aria-selected', 'false');
tabSelector[i].setAttribute('tabindex', -1);
tabContent[i].classList.remove('tab-content-active');
}
});
tabSelectorSelected.classList.add('active-tab-selector');
tabSelectorSelected.setAttribute('aria-pressed', 'true');
tabSelectorSelected.setAttribute('aria-selected', 'true');
tabSelectorSelected.removeAttribute('tabindex');
}
});
}
tabSelector.forEach(function(tabSelector) {
tabSelector.addEventListener('click', onTabSelectorClick);
});
.wrapper {
max-width: 960px;
margin: 0 auto;
}
.tab-selectors {
display: inline-block;
}
.tab-selectors > li {
padding: 10px;
}
.tab-selectors > .active-tab-selector {
border: 1px solid #f00;
}
.tab-content {
display: inline-block;
}
.tab-contents > div {
padding: 10px;
border: 2px solid #000;
height: 150px;
width: 150px;
display: none;
}
.tab-contents > .tab-content-active {
display: block;
}
<div class="wrapper">
<h1>Accessible Tabs using Vanilla JavaScript</h1>
<div class="accessible-tabs-container">
<ul role="tablist" aria-lable="Tabs Example" class="tab-selectors">
<li class="active-tab-selector">Tab Selector 1</li>
<li>Tab Selector 2</li>
<li>Tab Selector 3</li>
</ul>
<div class="tab-contents">
<div class="tab-content-active">
Tab Content 1
</div>
<div>
Tab Content 2
</div>
<div>
Tab Content 3
</div>
</div>
</div>
<div class="accessible-tabs-container">
<ul role="tablist" aria-lable="Tabs Example" class="tab-selectors">
<li class="active-tab-selector">Tab Selector 1</li>
<li>Tab Selector 2</li>
<li>Tab Selector 3</li>
</ul>
<div class="tab-contents">
<div class="tab-content-active">
Tab Content 1
</div>
<div>
Tab Content 2
</div>
<div>
Tab Content 3
</div>
</div>
</div>
</div>
I'm trying to generate these unique IDs in line 6 of the Vanilla JavaScript (accessibleTabsContainers.forEach) but it's not working.
Any assistance would be appreciated.
I solved my own issue. In the forEach loop that iterates inside the onTabSelectorClick function, I refactored the code to add the lines below:
var tabSelectorSelected = e.target;
var accessibleTabsContainerSelected = tabSelectorSelected.closest('.accessible-tabs-container');
var tabSelectorsSelectedFromTabs = accessibleTabsContainerSelected.querySelectorAll('ul > li');
Then in a forEach loop instead of iterating through tabSelector (which references var tabSelector = document.querySelectorAll('.tab-selectors > li');) and loops through all tabs li tags, not just the ones referenced by the element clicked, I used tabSelectorsSelectedFromTabs, which references the tab elements inside their parent div tag (var accessibleTabsContainerSelected = tabSelectorSelected.closest('.accessible-tabs-container');), from the tab element (li tag) clicked (var tabSelectorSelected = e.target;).
See https://codepen.io/hollyw00d/pen/JjYJWjG. Also, I added the correct code in this answer. Below is a more useful before and after description of the code:
Incorrect forEach Loop Snippet inside onTabSelectorClick function that is passed in Click Event Handler
var tabSelector = document.querySelectorAll('.tab-selectors > li');
function onTabSelectorClick(e) {
tabSelector.forEach(function() {
// Code here
});
}
Correct forEach Loop Snippet inside onTabSelectorClick function that is passed in Click Event Handler
var tabSelectorSelected = e.target;
var accessibleTabsContainerSelected = tabSelectorSelected.closest('.accessible-tabs-container');
var tabSelectorsSelectedFromTabs = accessibleTabsContainerSelected.querySelectorAll('ul > li');
function onTabSelectorClick(e) {
tabSelectorsSelectedFromTabs.forEach(function() {
// Code here
});
}
var accessibleTabsContainers = document.querySelectorAll('.accessible-tabs-container');
var tabSelector = document.querySelectorAll('.tab-selectors > li');
var tabContent = document.querySelectorAll('.tab-contents > div');
var largeRandNumber = Math.floor((Math.random() * 1000) + 1000);
accessibleTabsContainers.forEach(function(elem, indexAccessibleTabContainer) {
elem.setAttribute('data-id', indexAccessibleTabContainer);
tabSelector.forEach(function(singleTabSelector, i) {
var tabSelectorId = 'tab-selector-' + largeRandNumber + '_' + i + '_' + indexAccessibleTabContainer;
var ariaControlTabContent = 'tab-content-' + largeRandNumber + '_' + i + '_' + indexAccessibleTabContainer;
singleTabSelector.setAttribute('data-id', i);
singleTabSelector.setAttribute('id', tabSelectorId);
singleTabSelector.setAttribute('aria-controls', ariaControlTabContent);
tabContent[i].setAttribute('data-id', i);
tabContent[i].setAttribute('tabindex', 0);
tabContent[i].setAttribute('role', 'tabpanel');
tabContent[i].setAttribute('id', ariaControlTabContent);
tabContent[i].setAttribute('aria-labeledby', tabSelectorId);
if(i === 0) {
singleTabSelector.setAttribute('aria-pressed', 'true');
} else {
singleTabSelector.setAttribute('aria-pressed', 'false');
singleTabSelector.setAttribute('tabindex', -1);
}
});
});
function onTabSelectorClick(e) {
var tabSelectorSelected = e.target;
var accessibleTabsContainerSelected = tabSelectorSelected.closest('.accessible-tabs-container');
var tabSelectorsSelectedFromTabs = accessibleTabsContainerSelected.querySelectorAll('ul > li');
var tabContentsSelectedFromContainer = accessibleTabsContainerSelected.querySelectorAll('.tab-contents > div');
if(!tabSelectorSelected.classList.contains('active-tab-selector')) {
tabSelectorsSelectedFromTabs.forEach(function(singleTabSelected, i) {
if(tabSelectorSelected.getAttribute('data-id') === tabContentsSelectedFromContainer[i].getAttribute('data-id')) {
singleTabSelected.classList.add('active-tab-selector');
singleTabSelected.setAttribute('tabindex', 0);
singleTabSelected.setAttribute('aria-pressed', 'true');
tabContentsSelectedFromContainer[i].classList.add('tab-content-active');
} else {
singleTabSelected.classList.remove('active-tab-selector');
singleTabSelected.setAttribute('tabindex', -1);
singleTabSelected.setAttribute('aria-pressed', 'false');
tabContentsSelectedFromContainer[i].classList.remove('tab-content-active');
}
});
}
}
tabSelector.forEach(function(tabSelector) {
tabSelector.addEventListener('click', onTabSelectorClick);
});
.wrapper {
max-width: 960px;
margin: 0 auto;
}
.tab-selectors {
display: inline-block;
}
.tab-selectors > li {
padding: 10px;
}
.tab-selectors > .active-tab-selector {
border: 1px solid #f00;
}
.tab-content {
display: inline-block;
}
.tab-contents > div {
padding: 10px;
border: 2px solid #000;
height: 150px;
width: 150px;
display: none;
}
.tab-contents > .tab-content-active {
display: block;
}
<div class="wrapper">
<h1>Accessible Tabs using Vanilla JavaScript</h1>
<div class="accessible-tabs-container">
<ul role="tablist" aria-lable="Tabs Example" class="tab-selectors">
<li class="active-tab-selector">Tab Selector 1</li>
<li>Tab Selector 2</li>
<li>Tab Selector 3</li>
</ul>
<div class="tab-contents">
<div class="tab-content-active">
Tab Content 1
</div>
<div>
Tab Content 2
</div>
<div>
Tab Content 3
</div>
</div>
</div>
<div class="accessible-tabs-container">
<ul role="tablist" aria-lable="Tabs Example" class="tab-selectors">
<li class="active-tab-selector">Tab Selector 1</li>
<li>Tab Selector 2</li>
<li>Tab Selector 3</li>
</ul>
<div class="tab-contents">
<div class="tab-content-active">
Tab Content 1
</div>
<div>
Tab Content 2
</div>
<div>
Tab Content 3
</div>
</div>
</div>
</div>

click button to switch div positions

Brief Explanation: I have div1 and div2 onside a <div>. On right click i open context menu which has a button switch.
On clicking this button i want div1 and div2 to switch positions,
attached pic for your reference:
here is my code:
$(document).on("contextmenu", "div", function(event) {
// alert("right clicked");
event.stopPropagation();
this.clickedElement = $(this);
event.preventDefault();
$(this.clickedElement).addClass('selecteddiv');
$(".custom-menu4").show();
$(".custom-menu4 li").unbind().click(function() {
switch ($(this).attr("data-action")) {
case "second":
$(".custom-menu4").hide();
$(".selecteddiv").removeClass('selecteddiv');
break;
case "first":
alert("clicked switch");
break;
}
})
// alert("add");
});
.selecteddiv {
border: 1px solid rgb(180, 13, 172);
}
.custom-menu4 {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="click" style="padding: 20px">
<div class="switch">Hello</div>
<div class="switch">World</div>
</div>
<ul class='custom-menu4'>
<li data-action="first">Switch</li>
<li data-action="second">Cancel</li>
</ul>
link to jsfiddle
On clicking the switch button, the div1 should switch position with div2, i mean in whatever positions they are, they should switch.
Please help.
You can do it by selecting the second element and prepending it to the div with class "click" so it becames the first.
$("li:contains('Switch')").click(function() {
$('div.switch:last').prependTo('.click');
})
.selecteddiv {
border: 1px solid rgb(180, 13, 172);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="click" style="padding: 20px">
<div class="switch">Hello</div>
<div class="switch">World</div>
</div>
<ul class='custom-menu4'>
<li data-action="first">Switch</li>
<li data-action="second">Cancel</li>
</ul>
You just need to select the first switchable element, and move it after the other one. Demo:
$(document).on("contextmenu", "div", function(event) {
event.stopPropagation();
event.preventDefault();
$('.selecteddiv').removeClass("selecteddiv");
$(this).addClass('selecteddiv');
$(".custom-menu4").show();
$(".custom-menu4 li").off().click(function() {
switch ($(this).attr("data-action")) {
case "second":
$(".custom-menu4").hide();
$(".selecteddiv").removeClass('selecteddiv');
break;
case "first":
/***** This is the important bit, to do the switching ****/
var $div = $('.switch').first();
$div.next('.switch').after($div);
break;
}
})
});
.selecteddiv {
border: 1px solid rgb(180, 13, 172);
}
.custom-menu4 {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="click" style="padding: 20px">
<div class="switch">Hello</div>
<div class="switch">World</div>
</div>
<ul class='custom-menu4'>
<li data-action="first">Switch</li>
<li data-action="second">Cancel</li>
</ul>
I simplified this a lot
$(document).on("contextmenu","div", function(event) {
event.stopPropagation();
event.preventDefault();
$(".custom-menu4").show();
})
$('#btn-cancel').click(function (evt) {
$(".custom-menu4").hide();
});
$('#btn-switch').click(function (evt) {
var $div = $('#top-divs div').first();
$('#top-divs').append($div);
});
.selecteddiv {
border: 1px solid rgb(180, 13, 172);
}
.custom-menu4 {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="top-divs" style="padding: 20px">
<div class="switch">Hello</div>
<div class="switch">World</div>
</div>
<ul class='custom-menu4'>
<li id="btn-switch" data-action="first">Switch</li>
<li id="btn-cancel" data-action="second">Cancel</li>
</ul>
$('.click').find('.switch').eq(0).appendTo($('.click'));
http://jsfiddle.net/ohw25Ltf/
You can use flex with order and keep the DOM elements in their original location.
With this technique, you could manipulate the ordering of multiple elements quite easily only by changing their order.
$(".switch-btn").click(function() {
$('.switch').toggleClass('high-order');
})
.click {
display: flex;
flex-flow: column wrap;
padding: 20px;
}
.click > div {
order: 1
}
.click > div.high-order {
order: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="click">
<div>Hello</div>
<div class="switch">World</div>
</div>
<button class="switch-btn">Switch</button>
Do this in JavaScript:
$(".custom-menu4 li").unbind().click(function() {
switch ($(this).attr("data-action")) {
case "second":
$(".custom-menu4").hide();
$(".selecteddiv").removeClass('selecteddiv');
break;
case "first":
alert("clicked switch");
var selected = $("div.selecteddiv").html();
var unselected = $("div").not(".selecteddiv").html();
$("div.selecteddiv").html(unselected);
$("div").not(".selecteddiv").html(selected);
$(".selecteddiv").removeClass("selecteddiv");
break;
}
})

Re-select li not working

I have a list of lis. If an li gets selected, it will get a background color of orange, and the previous 'selected' li's background color will get removed.
The problem is, if select the same li 3 times, nothing happens. The first time, it gets a background color of orange. Second time, the background color will get removed. Third time, the background color should get orange, but it doesn't. Nothing happens.
How can I get the orange color to reappear the third time it gets selected, and have 'normal' behavior every time after?
JSFiddle
"use strict"
var parentElem = document.getElementById('wrapper'),
cells = parentElem.firstElementChild.children,
previousColorNameSelection = parentElem.children[0];
parentElem.firstElementChild.addEventListener('click', function(e) {
var currentTarget;
if (e.target.tagName === 'LI') {
currentTarget = e.target.firstElementChild.firstElementChild;
} else if (hasClass(e.target, 'namesInnerWrapper')) {
currentTarget = e.target.firstElementChild;
} else if (hasClass(e.target, 'namesName')) {
currentTarget = e.target;
}
console.log(currentTarget.innerHTML, currentTarget);
currentTarget.parentElement.parentElement.style.backgroundColor = 'orange';
previousColorNameSelection.parentElement.parentElement.style.backgroundColor = '';
previousColorNameSelection = currentTarget;
});
function hasClass(ele, cls) {
return ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'));
}
#wrapper {
width: 300px;
}
li:nth-child(odd) {
background: rgba(100, 200, 255, 0.1);
}
li {
list-style-type: none;
}
ul {
position: relative;
height: 350px;
}
<div id="wrapper">
<ul>
<li style="width:100%">
<div class="namesInnerWrapper"><span class="namesName">balancing</span>
</div>
</li>
<li style="width:100%">
<div class="namesInnerWrapper"><span class="namesName">preknow</span>
</div>
</li>
<li style="width:100%">
<div class="namesInnerWrapper"><span class="namesName">barents</span>
</div>
</li>
<li style="width:100%">
<div class="namesInnerWrapper"><span class="namesName">underwash</span>
</div>
</li>
<li style="width:100%">
<div class="namesInnerWrapper"><span class="namesName">immaterializing</span>
</div>
</li>
<li style="width:100%">
<div class="namesInnerWrapper"><span class="namesName">noncreditor</span>
</div>
</li>
<li style="width:100%">
<div class="namesInnerWrapper"><span class="namesName">unrevised</span>
</div>
</li>
</ul>
</div>
I'm going to give you an answer in jQuery because it's so much more simple that way. (JSFiddle)
Let's first just use a class for specifying the background color. Easier to work with.
li.active{
background-color: orange;
}
And then let's use jQuery like this:
$(function(){
$('li').on('click', function(){
// Save whether or not the li being clicked is already selected
var alreadySelected = $(this).hasClass('active') ? true : false;
// Remove the active class from all list items
$('li').removeClass('active');
// If it wasn't already selected, then select it now
if(!alreadySelected) $(this).addClass('active');
});
});

add class to li onclick

how will i go on to added a class to li class='active' on click and also on page load have the first li ( overview ) active by default ?
<ul>
<li>Overview</li>
<li>Reviews</li>
<li>News</li>
<li>Gallery</li>
</lu>
<div id='overview' style='display: none;'>
<!-- overview content -->
</div>
<div id='articles' style='display: none;'>
<!-- arcticles content -->
</div>
<div id='news' style='display: none;'>
<!-- news content -->
</div>
<div id='gallery' style='display: none;'>
<!-- gallery content -->
</div>
<script type="text/javascript">
function showdiv(id){
document.getElementById(id).style.display = "block";
}
</script>
Here is a Quick JSFiddle Demo that demonstrates swapping classNames and display of divs in pure JavaScript.
var toggleDiv = function(self, id) {
var li = self.parentNode,
contents = document.getElementsByClassName('content'),
menu = document.getElementById('menu'),
children = menu.children,
child = undefined,
i = 0;
// Loop over all content divs and show the active and hide all others.
for (i = 0; i < contents.length; i++)
contents[i].style.display = contents[i].id == id ? 'block' : 'none';
// Loop over all menu items and add active class to the selected
// and remove from others if applicable.
for (i = 0; i < children.length; i++) {
child = children[i];
if (child === li) {
child.className = (child.className + ' active').trim();
} else {
if (child.className.indexOf('active') > -1) {
child.className = child.className.replace('active', '').trim();
}
}
}
}
<ul id="menu">
<li>Overview</li>
<li>Reviews</li>
<li>News</li>
<li>Gallery</li>
</ul>
<div id="overview" class="content">Overview...</div>
<div id="reviews" class="content">Reviews...</div>
<div id="news" class="content">News...</div>
<div id="gallery" class="content">Gallery...</div>
ul {
margin: 0;
padding: 0;
list-style-type: none;
}
li {
position: relative;
display: inline-block;
width: 80px;
background: #4679BD;
color: #FFFFFF;
text-align: center;
}
li>a {
color: #FFFFFF;
text-decoration: none;
font-weight: bold;
}
.content {
display: none;
}
.active {
background: #064CA8;
}
You should consider using jQuery if you have not already. It really makes these a bit easier.
Strictly speaking, here is one way: (untested)
<ul>
<li>Overview</li>
<li>Reviews</li>
<li>News</li>
<li>Gallery</li>
</ul>
<div id='overview' style='display: none;'>
<!-- overview content -->
</div>
<div id='articles' style='display: none;'>
<!-- arcticles content -->
</div>
<div id='news' style='display: none;'>
<!-- news content -->
</div>
<div id='gallery' style='display: none;'>
<!-- gallery content -->
</div>
<script type="text/javascript">
function showdiv(id, a){
if (window.activeA != undefined) {
window.activeA.className = ''; // delcare window.activeA, if not already exists
}
document.getElementById(id).style.display = "block";
a.className = 'active';
window.activeA = a;
}
</script>

Categories

Resources