I have this:
var editor = document.getElementById('editor');
var words = document.querySelector('.words');
function wordsCount() {
var arr = editor.innerText.trim().replace(/\s+/g, ' ').split(' ');
words.textContent = !arr[0] ? 0 : arr.length;
}
wordsCount();
section {
display: none;
}
:target {
display: block;
}
.words:before {
content: "words: "
}
.words {
margin-top: 10px;
background-color: silver;
}
<aside>
<ol>
<li>Show 1</li>
<li>Show 2</li>
<li>Show 3</li>
</ol>
</aside>
<div id="editor">
<section id="1">Section 1 text</section>
<section id="2">Section 2 text</section>
<section id="3">Section 3 text</section>
</div>
<div class="words"></div>
Note: Right now, for the word count to work I need to delete:
section {
display: none;
}
My question is: How do I make the word count script target (count) only sections that are displayed, and only those. Any ideas?
You can attach click event to a element, pass this.hash from index 1 to wordsCount(), use RegExp /[^\s]+/g and String.prototype.match()
var editor = document.getElementById('editor');
var words = document.querySelector('.words');
function wordsCount(el) {
var arr = el.textContent.trim().match(/[^\s]+/g);
words.textContent = !arr[0] ? 0 : arr.length;
}
document.querySelectorAll("a")
.forEach(function(el) {
el.onclick = function() {
wordsCount(document.getElementById(this.hash.slice(1)))
}
})
section {
display: none;
}
:target {
display: block;
}
.words:before {
content: "words: "
}
.words {
margin-top: 10px;
background-color: silver;
}
<aside>
<ol>
<li>Show 1</li>
<li>Show 2</li>
<li>Show 3</li>
</ol>
</aside>
<div id="editor">
<section id="1">Section 1 text a</section>
<section id="2">Section 2 text b c</section>
<section id="3">Section 3 text d e f</section>
</div>
<div class="words"></div>
You have to find the length of words on click event of the anchor tag.
Stack Snippet
var words = document.querySelector('.words');
var anchor = document.querySelectorAll("a");
var section = document.querySelectorAll("section");
for (let i = 0; i < anchor.length; i++) {
anchor[i].addEventListener("click", function() {
var arr = document.getElementById(i + 1).innerText.trim().replace(/\s+/g, ' ').split(' ');
words.textContent = !arr[0] ? 0 : arr.length;
})
}
section {
display: none;
}
:target {
display: block;
}
.words:before {
content: "words: "
}
.words {
margin-top: 10px;
background-color: silver;
}
<aside>
<ol>
<li>Show 1</li>
<li>Show 2</li>
<li>Show 3</li>
</ol>
</aside>
<div id="editor">
<section id="1">Section 1 text 2</section>
<section id="2">Section 2 text</section>
<section id="3">Section 3 text 3 4</section>
</div>
<div class="words"></div>
Related
<button>Click!</button>
<ul>
<li class="green">Home</li>
<li class="green">faq</li>
<li class="green">dropdown</li>
<li class="green">about</li>
<li class="green">contact</li>
</ul>
let li = document.querySelectorAll('li');
let btn = document.querySelector('button');
for(let i=0; i<li.length; i++) {
let number = 0;
btn.addEventListener('click', ()=>{
li[number++].classList.add('red')
if(number === li.length) {
number = 0
}
})
}
I wanted a single item to turn red with each click and the previous one to turn green again
You can do it like this if this helps you. As soon as you press the button. Remove the red class from every element first and then add it like you were doing
let li = document.querySelectorAll('li');
let btn = document.querySelector('button');
for(let i=0; i<li.length; i++) {
let number = 0;
btn.addEventListener('click', ()=>{
for(let i=0; i<li.length; i++) {
li[i].classList.remove('red')
}
li[number++].classList.add('red')
if(number === li.length) {
number = 0
}
})
}
.green {
color:green;
}
.red {
color:red;
}
<button>Click!</button>
<ul>
<li class="green">Home</li>
<li class="green">faq</li>
<li class="green">dropdown</li>
<li class="green">about</li>
<li class="green">contact</li>
</ul>
Doing this with JavaScript and one event listener
document.querySelector(".menu").addEventListener("click", function (e) {
// find the li that was clicked
const clickedLi = e.target.closest("li");
if (!clickedLi) return;
// see if we had something clicked already
const selected = e.currentTarget.querySelector(".red");
if (selected) selected.classList.remove('red');
// update the class on what was clicked
clickedLi.classList.add('red');
});
.green {
background-color: green;
}
li.red {
background-color: red;
}
<ul class="menu">
<li class="green">Home</li>
<li class="green">faq</li>
<li class="green">dropdown</li>
<li class="green">about</li>
<li class="green">contact</li>
</ul>
Using just html and css to make the selections
.menu input[type="radio"] {
display: none;
}
.menu input[type="radio"]+label {
display: inline-block;
width: 100%;
background-color: green;
}
.menu input[type="radio"]:checked + label {
background-color: red;
}
<ul class="menu">
<li><input type="radio" name="list" id="li1"><label for="li1">Foo</label></li>
<li><input type="radio" name="list" id="li2"><label for="li2">Bar</label></li>
<li><input type="radio" name="list" id="li3"><label for="li3">Baz</label></li>
<li><input type="radio" name="list" id="li4"><label for="li4">Cheese</label></li>
</ul>
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!
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>
Using jQuery, how can I dynamically add href and id attributes to link the menu items to the sections in the code below in order?
<body>
<nav>
<ul>
<li><a>nav1</a></li>
<li><a>nav2</a></li>
<li><a>nav3</a></li>
</ul>
</nav>
<section class="main-section"></section>
<section class="main-section"></section>
<section class="main-section"></section>
</body>
It should look like this after.
<body>
<nav>
<ul>
<li>nav1</li>
<li>nav2</li>
<li>nav3</li>
</ul>
</nav>
<section id="id1" class="main-section"></section>
<section id="id2" class="main-section"></section>
<section id="id3" class="main-section"></section>
</body>
You can try this.....
Fiddle
Html :
<ul>
</ul>
</nav>
<div id='addMore'>
</div>
<button id='btn'>add section and link</button>
Jquery :
var count = 0;
$('#btn').click(function(){
$('#addMore').append('<section id="id'+ count+'" class="main-section"></section>');
$('nav ul').append('<li>nav'+count+'</li>');
count++;
});
let me know if it according to you requirements...
Happy coding...
How about this: First build your strings
var sections ="";
var list = "<ul>";
for(var i=0; i < 3; i++)
{
list += '<li>nav'+i+'</li>';
sections += '<section id="id'+i+'" class="main-section"></section>';
}
list += "</ul>"
Then add them somewhere like:
$('nav').html(list );
$('#container').html(sections);
Here is the JSFIDDLE
var totalLists = 4;
var listitems='';
var sectionitems='';
$(document).ready(function(){
for(var i = 1; i<= totalLists; i++){
listitems = listitems+'<li>nav'+i+'</li>';
sectionitems=sectionitems+'<section id="id'+i+'" class="main-section"></section>'
}
$("#navlists").append(listitems);
$("#section").append(sectionitems);
});
You can try this solution :
adding id dynamically to section within body according to nav element
Seems like the nav element exist already then the solution is find the a element length(for creating section), then insert newly created element after existing section or nav. Hope this helped.
Html
<nav>
<ul>
<li><a>nav1</a>
</li>
<li><a>nav2</a>
</li>
<li><a>nav3</a>
</li>
</ul>
</nav>
jQuery
$('nav li a').each(function(i,e){
var section;
$(this).attr('href','#id'+(i+1));
section = $('<section/>',{
class : 'main-section',
id : 'id'+(i+1)
});
if ( $('nav').next().is('section') ) {
$(section).insertAfter($('nav').nextAll().last());
} else {
$(section).insertAfter('nav');
}
});
DEMO
You can loop through the links, then assign common href and id values based on the index of the link.
This checks if the section exists before setting the attributes.
var sections = $('section.main-section');
$('nav a').each(function(index){
if(sections.eq(index).length) {
$(this).attr('href','#section' + index);
sections.eq(index).attr('id','section' + index);
}
})
/* This CSS is for demo purposes only */ html, body { margin: 0; height: 100%; } .main-section { height: 100%; } ul,li { padding: 0; margin: 0; } ul { position: fixed; } li { display: inline-block; } #section0 { background: rgb(150,200,250); } #section1 { background: rgb(250,200,150); } #section2 { background: rgb(150,250,200); }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav>
<ul>
<li><a>nav1</a></li>
<li><a>nav2</a></li>
<li><a>nav3</a></li>
<li><a>nav4</a></li> <!-- This will not change because
there is no fourth section -->
</ul>
</nav>
<section class="main-section"></section>
<section class="main-section"></section>
<section class="main-section"></section>
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>