Div tabs with Javascript - javascript

I organized my tabs this way:
<ul id="tabs">
<li class="selected">DIV1</li>
<li class>DIV2</li>
<li class>DIV3</li>
</ul>
<div id="tabs_content">
<div id="div1" style="display: block;"><textarea name="div1" rows="7" cols="108"></textarea></div>
<div id="div2" style="display: none;"><textarea name="div2" rows="7" cols="108"></textarea></div>
<div id="div3" style="display: none;"><textarea name="div3" rows="7" cols="108"></textarea></div>
</div>
I would like that when I press one of the link inside the <li> element,
the corrispondend Div become visible with display: block and the others are changed to display: none
Also I would like to do the same with the "selected" class on the clicked <li> element.
Is this possible?
I tried with:
function selectTab(src)
{
document.getElementById('div1').style.display = 'none';
document.getElementById('div2').style.display = 'none';
document.getElementById('div3').style.display = 'none';
document.getElementById(src).style.display = 'block';
}
It works if I pass the ID by reference with onclick="" but I would like to avoid this.
Solution:
function selectTab(source, parent)
{
document.getElementById('div1').style.display = 'none';
document.getElementById('div2').style.display = 'none';
document.getElementById('div3').style.display = 'none';
document.getElementById(source).style.display = 'block';
var elements = [].slice.apply(document.getElementsByClassName('selected'));
for (var i = 0; i < elements.length; i++) {
elements[i].className = '';
}
parent.className = 'selected';
}

Possibly this is what you want, cross-browser (IE5.5+)
CSS
.selected {
background-color: green;
}
.hide {
display: none;
}
HTML
<ul id="tabs">
<li class="selected">DIV1
</li>
<li class>DIV2
</li>
<li class>DIV3
</li>
</ul>
<div id="tabs_content">
<div id="div1">
<textarea name="div1" rows="7" cols="108"></textarea>
</div>
<div id="div2" class="hide">
<textarea name="div2" rows="7" cols="108"></textarea>
</div>
<div id="div3" class="hide">
<textarea name="div3" rows="7" cols="108"></textarea>
</div>
</div>
javascript
var tabs = document.getElementById("tabs"),
tabs_content = document.getElementById("tabs_content"),
divs = tabs_content.getElementsByTagName("div"),
divsLength = divs.length,
lis = tabs.getElementsByTagName("li"),
lisLength = lis.length;
tabs.onclick = function (evt) {
var e = evt || window.event,
target = e.target || e.srcElement,
href,
id,
index,
div;
if (target.tagName.toUpperCase() === "A") {
for (index = 0; index < lisLength; index += 1) {
lis[index].className = "";
}
target.parentNode.className = "selected";
href = target.attributes.href.nodeValue;
if (href && href.charAt(0) === "#") {
id = href.slice(1);
for (index = 0; index < divsLength; index += 1) {
div = divs[index];
if (id === div.id) {
div.className = "";
} else {
div.className = "hide";
}
}
}
}
};
jsfiddle

Your selectTab function needs to be necessarily bound to the click event on those list elements. There's no other way you can do it. Your code is good enough. You can simplify things using JQuery as well, as some other answer here points out.
Okay, do this:
In your HTML, add "tab" class to each of the tags.
<li class="selected"><a class="tab" href="#div1">DIV1</a></li>
<li class><a class="tab" href="#div2">DIV2</a></li>
<li class><a class="tab" href="#div3">DIV3</a></li>
In your jquery,
$('.tab').click(function(){
var displaydiv = $(this).attr('href');
$('#div1').hide();
$('#div2').hide();
$('#div3').hide();
$(this).show();
$('"'+displaydiv+'"').show();
$(this).parent().attr('class','selected');
})

<ul id="tabs">
<li class="selected"><a onclick="showTab(this);" href="#div1">DIV1</a></li>
<li><a onclick="showTab(this);" href="#div2">DIV2</a></li>
<li><a onclick="showTab(this);" href="#div3">DIV3</a></li>
</ul>
<div id="tabs_content">
<div id="div1" style="display: block;"><textarea name="div1" rows="7" cols="108"></textarea></div>
<div id="div2" style="display: none;"><textarea name="div2" rows="7" cols="108"></textarea></div>
<div id="div3" style="display: none;"><textarea name="div3" rows="7" cols="108"></textarea></div>
</div>
Use the following javascript:
function showTab(a)
{
var id = a.href.replace('#','');
var tabs = document.getElementById('tabs_content').getElementsByTagName('div');
var index = -1;
for(var i=0,n=tabs.length;i<n;i+=1)
{
var t = tabs[i];
if(t.id === id)
{
t.style.display = 'block';
index = i;
}
else
{
t.style.display = 'none';
}
}
var links = document.getElementById('tabs').getElementsByTagName('li');
for(var i=0,n=links.length;i<n;i+=1)
{
links[i].setAttribute('class', index === i ? 'selected' : '');
}
}
Of course you could also first cache your menu and tabs, that way you can keep a variable. This is the proper way:
function Menu()
{
var self = this;
self.links = document.getElementById('tabs').getElementsByTagName('a');
self.tabs = document.getElementById('tabs_content').getElementsByTagName('div');
self.selectedIndex = 0;
self.n = self.links.length;
for(var i=0;i<self.n;i+=1)
{
// Set onclick for every link in the tabs-menu
self.links[i].onclick = function(ind){return function(){self.update(ind);};}(i);
}
self.update = function(ind)
{
// Hide previous tab
self.links[self.selectedIndex].parentNode.setAttribute('class', '');
self.tabs[self.selectedIndex].style.display = 'none';
// Select and show clicked tab
self.selectedIndex = ind;
self.links[self.selectedIndex].parentNode.setAttribute('class', 'selected');
self.tabs[self.selectedIndex].style.display = 'block';
};
}
setTimeout(function(){new Menu();},1);
Check out the jsfiddle for the Menu class in action: http://jsfiddle.net/3vf4A/1/. Note that even if Javascript is disabled, the a-tag will still get you to the correct area by scrolling to it automatically.

Related

I'm trying to get the parent of the parent (div) of the li-element which I click

I'm trying to get the parent of the parent (div) of the li-element which I click and change/remove it's class but I don't know how to tell JS that it should get the specific li class that I click. Sorry for this simple question I'm fairly new to JS.
<!DOCTYPE html>
<html>
<body>
<p>List:</p>
<div class="div">
<ul>
<li class="lis">Coffee</li>
<li class="lis">Tea</li>
<li class="lis">Water</li>
</ul>
</div>
<script>
let li = document.getElementsByClassName("lis")
li.click() = function() {
var x = li.parentElement.parentElement.classList.value
if(x.classList.contains("div")) {
x.remove.classList("div")
}
}
</script>
</body>
</html>
<script>
var elements = document.getElementsByClassName("lis");
var myFunction = function(e) {
x = e.target.innerHTML;
e.target.parentElement.parentElement.innerHTML=x
};
for (var i = 0; i < elements.length; i++) {
elements[i].addEventListener('click', myFunction, false);
}
</script>
You can use .closest() to select the closest div and after that, you can remove the class from that element.
Try below working code -
var elements = document.getElementsByClassName("lis");
var myFunction = function() {
var x = this.closest('.div')
if (x) {
this.closest('.div').classList.remove("div")
console.log('Div Element Class Removed!');
}
};
for (var i = 0; i < elements.length; i++) {
elements[i].addEventListener('click', myFunction, false);
}
<!DOCTYPE html>
<html>
<body>
<p>List:</p>
<div class="div">
<ul>
<li class="lis">Coffee</li>
<li class="lis">Tea</li>
<li class="lis">Water</li>
</ul>
</div>
</body>
</html>
I recommend to delegate to the nearest static container
Also you had remove.classList - that should be classList.remove
Here I give an ID to the UL and test if the LI clicked has the lis class
document.getElementById("ul").addEventListener("click",function(e) {
const tgt = e.target.closest("li")
if (tgt.classList.contains("lis")) {
tgt.closest("div").classList.remove("div")
}
})
.div { background-color:red }
<p>List:</p>
<div class="div">
<ul id="ul">
<li class="lis">Coffee</li>
<li class="lis">Tea</li>
<li class="lis">Water</li>
</ul>
</div>
I came up with another good solution that let's me add and remove the div class, the parent of specified li elements. I added an extra div to make sure it always gets the certain parent that I've specified with .closest(body > div) and used a for loop to make the array that it creates select one certain li element, the one I currently click on.
<!DOCTYPE html>
<html>
<body>
<p>List:</p>
<div class="div">
<ul>
<li class="lis">Coffee</li>
<li class="lis">Tea</li>
<li class="lis">Water</li>
</ul>
</div>
<div>
<ul>
<li class="l">Coffee</li>
<li class="l">Tea</li>
<li class="l">Water</li>
</ul>
</div>
<script>
let lists = document.getElementsByClassName("lis");
let divs = document.getElementsByTagName("div");
for (let list of lists) {
list.addEventListener("click", () => {
list.closest("body > div")
for (let div of divs) {
div.addEventListener("click", () => {
if (div.classList.contains("div")) {
div.classList.remove("div")
} else {
div.classList.add("div")
}
})
}
})
}
</script>
<style>
.div {
color: brown;
font-size: larger;
}
</style>
</body>
</html>
var li = document.getElementsByClassName("lis");
for (var i=0; i<li.length; i++) {
li[i].onclick = function() {
var el = this.parentElement.parentElement;
if (el.className == "div") {
el.className = "";
}
}
}

html-JavaScript- when switching to next div only displays for a split second then disappears

Here is my function. I want to switch from one div to another. I am getting this to happen but only for a quick second then it returns back to the first div.
function NextDiv()
{
var div = document.querySelectorAll("#div0>div");
for (var i = 0; i < div.length; i++)
{
if (div[i].style.display != "none")
{
div[i].style.display = "none";
if (i == div.length - 1)
{
div[0].style.display = "block";
}
else
{
div[i + 1].style.display = "block";
}
return false;
}
}
}
here is a testable fiddle: https://jsfiddle.net/pnumtc35/5/
at the line where you do div[i+1] the new div gets shown. but on the next iteration of your for-loop it get immediately hidden again. Thats why i added a break to stop the loop.
function NextDiv()
{
console.log('click');
var div = document.querySelectorAll("#div0>div");
for (var i = 0; i < div.length; i++)
{
if (div[i].style.display != "none")
{
div[i].style.display = "none";
if (i == div.length - 1)
{
div[0].style.display = "block";
}
else
{
div[i + 1].style.display = "block";
break; // ADDED
}
}
}
}
<div id="div0">
<div class="column" id="div1" >
<h2>Customer Information </h2>
<button runat="server" id="nextbutton" onclick="NextDiv()" >Next </button>
</div>
<div class="column" id="div2" style="display: none;">
<h2>Payment Information</h2>
<button runat="server" id="Button1" onclick="NextDiv()">Next </button>
</div>
<div class="column" id="div3" style="display: none;">
<h2>Shipment Information</h2>
<Button ID="btn1" runat="server" Text="Save" onclick="SaveInfo"/>
</div>
</div>

Show/Hide Javascript one at a time

This is probably very simple but I'm at a loss.
I have two anchors that toggle the display of their own div containers. Right now, you can have both div containers showing by clicking each button once. I would like only one div showing at a time.
So if you select button 1 to show div 1, then you select button 2, it will show div 2 but also hide div 1.
Here is my code:
<script type="text/javascript" language="JavaScript">
function ReverseDisplay(d)
{
if(document.getElementById(d).style.display == "none")
{ document.getElementById(d).style.display = "block"; }
else
{ document.getElementById(d).style.display = "none"; }
}
</script>
<a id="menus" href="javascript:ReverseDisplay('menuList')">Button 1</a>
<a id="reso" href="javascript:ReverseDisplay('resoList')">Button 2</a>
<p>Some content</p>
<div id="menuList" style="display:none;">Some content</div>
<div id="resoList" style="display:none;">Some content</div>
Give div's common class
<div id="menuList" class="content" style="display:none;">Some content 1</div>
<div id="resoList" class="content" style="display:none;">Some content 2</div>
And then hide all before showing specific:
function ReverseDisplay(d) {
[].slice.call(document.querySelectorAll('.content')).forEach(function(el) {
el.style.display = 'none';
});
var element = document.getElementById(d);
element.style.display = element.style.display == "none" ? "block" : "none";
}
Check the demo below.
function ReverseDisplay(d) {
[].slice.call(document.querySelectorAll('.content')).forEach(function(el) {
el.style.display = 'none';
});
var element = document.getElementById(d);
element.style.display = element.style.display == "none" ? "block" : "none";
}
.content {
padding: 10px;
background: #EEE;
}
<a id="menus" href="javascript:ReverseDisplay('menuList')">Button 1</a>
<a id="reso" href="javascript:ReverseDisplay('resoList')">Button 2</a>
<p>Some content</p>
<div id="menuList" class="content" style="display:none;">Some content 1</div>
<div id="resoList" class="content" style="display:none;">Some content 2</div>
A bit more digging and I found a solution:
<script type="text/javascript" language="JavaScript">
(function() {
var opened_element = null;
window.ReverseDisplay = function(d) {
var e = document.getElementById(d);
if (opened_element && opened_element !== e) {
opened_element.style.display = 'none';
}
if(e.style.display == 'block') {
e.style.display = 'none';
}
else {
e.style.display = 'block';
}
opened_element = e;
};
}());</script>
You could
function ReverseDisplay(d) {
var el = document.getElementById(d),
els = document.getElementsByClassName('list'),
c;
for (var i = 0; i < els.length; i++) {
c = els[i];
if (el == c) {
if (el.style.display == "block") {
el.style.display = "none";
} else {
el.style.display = "block";
}
} else {
c.style.display = "none";
}
}
}
.list {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<a id="menus" href="javascript:ReverseDisplay('menuList')">Button 1</a>
<a id="reso" href="javascript:ReverseDisplay('resoList')">Button 2</a>
<p>Some content</p>
<div id="menuList" class="list">Some content 1</div>
<div id="resoList" class="list">Some content 2</div>
Here is jQuery for those that could use this:
function hideTarget(elem){
$(elem).hide();
}
function showTarget(elem, target, hideThis){
$(elem).click(function(){
$(target).show();
hideTarget(hideThis);
});
}
showTarget('#reso','#resoList','#menuList');
showTarget('#menus','#menuList','#resoList');
Here is the fiddle.

javascript css change overiding css

Sorry for the unclear question title...couldn't think how to put the question in a shirt summary.
I have css to change the background-color of a link when hovered over (with css transistion to fade the color in).
Due the nature of the requirement, I use JS to change the background color of the link which is in use (I have tabs, the selected one's background is selected using JS - getElementById('foo').style.backgroundColor = 'red';).
Even after a tab has been selected, I want the others to change color when hovering.
It works initially but once I have clicked on a tab (JS then changes that tab's color), the hover css style does not work - the other links no longer change color when hovering.
Has anyone else had the same problem?
HTML:
<div class="software_section_selects_wrapper">
<a id="a1" onclick="displayArrow('1')">OVERVIEW</a>
<a id="a2" onclick="displayArrow('2')">SPECS</a>
<a id="a3" onclick="displayArrow('3')">COMMENTS</a>
<div style="clear: both;"></div>
</div>
<div class="section_selects_arrow_wrapper">
<img id="red1"alt="" src="images/red_arrow.png" width="40px" height="20px"/>
<img id="red2"alt="" src="images/red_arrow.png" width="40px" height="20px"/>
<img id="red3"alt="" src="images/red_arrow.png" width="40px" height="20px"/>
</div>
<div id="overview" class="software_overview">
</div>
<div id="specs" class="software_overview">
</div>
<div id="comments" class="software_overview">
</div>
JS:
function displayArrow(arrow) {
var which_arrow = arrow;
if (which_arrow == '1') {
document.getElementById('a1').style.backgroundColor = 'red';
document.getElementById('a2').style.backgroundColor = 'black';
document.getElementById('a3').style.backgroundColor = 'black';
document.getElementById('red1').style.display = 'block';
document.getElementById('red2').style.display = 'none';
document.getElementById('red3').style.display = 'none';
document.getElementById('overview').style.display = 'block';
document.getElementById('specs').style.display = 'none';
document.getElementById('comments').style.display = 'none';
} else if (which_arrow == '2') {
document.getElementById('a2').style.backgroundColor = 'red';
document.getElementById('a1').style.backgroundColor = 'black';
document.getElementById('a3').style.backgroundColor = 'black';
document.getElementById('red2').style.display = 'block';
document.getElementById('red1').style.display = 'none';
document.getElementById('red3').style.display = 'none';
document.getElementById('specs').style.display = 'block';
document.getElementById('overview').style.display = 'none';
document.getElementById('comments').style.display = 'none';
} else {
document.getElementById('a3').style.backgroundColor = 'red';
document.getElementById('a2').style.backgroundColor = 'black';
document.getElementById('a1').style.backgroundColor = 'black';
document.getElementById('red3').style.display = 'block';
document.getElementById('red1').style.display = 'none';
document.getElementById('red2').style.display = 'none';
document.getElementById('comments').style.display = 'block';
document.getElementById('overview').style.display = 'none';
document.getElementById('specs').style.display = 'none';
}
}
This line of code:
document.getElementById('a2').style.backgroundColor = 'black';
adds an inline style which is stronger than :hover styling coming from the stylesheet.
Instead of adding the inline style, reset it to nothing:
document.getElementById('a2').style.backgroundColor = '';
I think his is what you are looking for
<div class="software_section_selects_wrapper">
<a id="a1" onclick="displayArrow('1')" onmouseover="MouseHoverMethod(this)" onmouseout="MouseOutMethod(this)">OVERVIEW</a>
<a id="a2" onclick="displayArrow('2')" onmouseover="MouseHoverMethod(this)" onmouseout="MouseOutMethod(this)">SPECS</a>
<a id="a3" onclick="displayArrow('3')" onmouseover="MouseHoverMethod(this)" onmouseout="MouseOutMethod(this)">COMMENTS</a>
<div style="clear: both;"></div>
</div>
Add following javascript functions and change the color as you need.
function MouseHoverMethod(x) {
x.style.backgroundColor = 'green';
}
function MouseOutMethod(x) {
x.style.backgroundColor = 'black';
}
Your code is far to complicated. You are breaking rule #1 of programming: DRY - Don't repeat yourself.
Also there is no need to set the color with JavaScript, instead set a class to to selected item and use that to style it.
Example: (without the red arrow stuff, because without the style sheet it's difficult to see what you are doing there, and it probably could be replaced with some pure CSS, too):
<div class="software_section_selects_wrapper">
<a onclick="displayTab(this, 'overview')">OVERVIEW</a>
<a onclick="displayTab(this, 'specs')">SPECS</a>
<a onclick="displayTab(this, 'comments')">COMMENTS</a>
<div style="clear: both;"></div>
</div>
<div class="tabs">
<div id="overview" class="software_overview">
</div>
<div id="specs" class="software_overview">
</div>
<div id="comments" class="software_overview">
</div>
</div>
JS:
<script>
function clearClass(elements) {
for (var i = 0; i < elements.length; i++) {
elements[i].className = '';
}
}
function displayTab(link, tabId) {
var links = link.parentNode.getElementsByTagName('a');
clearClass(links);
link.className = 'active';
var tab = document.getElementById(tabId);
var tabs = tab.parentNode.getElementsByTagName('div');
clearClass(tabs);
tab.className = 'active';
}
</script>
CSS:
.tabs > div {
display: none;
}
.tabs > div.active {
display: block;
}
.software_section_selects_wrapper > a {
color: white;
background-color: black;
}
.software_section_selects_wrapper > a.active {
color: white;
background-color: red;
}
Live: http://jsfiddle.net/d9ffnw46/1/
BTW, you should look into using a framework library such as jQuery. As a beginner it makes code such as this much simpler.
EDIT: Here's an example with jQuery: http://jsfiddle.net/d9ffnw46/2/

How to get elements by style property value?

I need to get all div elements with "display: none" style and then remove all of these elements. Also i need to select just that divs which are contained in #somecontainer element. Have to do it in RAW javascript. Any idea?
example html:
<table id="listtabletemp">
<thead>
<tr id="theader">
<td id="theaderleft">loolz</td>
</tr>
</thead>
<tbody>
<tr class="" rel="13117025">
<td><div><style>
.ikthgjyhtr{display:none}
.tVOx{display:inline}
</style>
<div style="display:none">crap here</div>
<div></div>
<div></div>
<div style="display:none">crap here</div>
<div class="230">something good</div>
<div class="ikthgjyhtr">crap here</div>
<div style="display:none">crap here</div>
<div class="ikthgjyhtr">crap here</div>
<div style="display: inline">something good</div>something good
<div style="display: inline">something good</div>
<div class="21">something good</div>
<div style="display:none">crap here</div>
<div style="display:none">crap here</div>
<div style="display:none">crap here</div>
<div class="4">something good</div>
<div class="224">something good</div></div>
</td>
</tr>
</tbody>
</table>
Simple, the DOM is your friend:
function removeDivs() {
var container = document.getElementById("somecontainer");
var divs = container.getElementsByTagName("div");
var empty = [];
var getStyle = function(obj, css){
var style = null;
if(obj.currentStyle) {
style = obj.currentStyle[css];
} else if(window.getComputedStyle) {
style = window.getComputedStyle(obj, null).getPropertyValue(css);
}
return(style);
};
for(var i = 0, len = divs.length; i < len; i++) {
var div = divs[i];
if(div && ((div.style.display && div.style.display == "none") || getStyle(div, "display") == "none")) {
empty.push(div);
}
}
for(var i = 0, len = empty.length; i < len; i++) {
var div = empty[i];
div.parentNode.removeChild(div);
}
}
Quick and dirty, here's something to get you started:
http://jsfiddle.net/kttsJ/
var parent = document.getElementById('parent');
var items = parent.getElementsByTagName('DIV');
var hidden = [];
for (var i in items){
if ((items[i]).getAttribute !== undefined){
if ((items[i]).hasAttribute('style')){
if ((/display\:\s*none/gi).test(items[i].getAttribute('style'))){
hidden.push(items[i]);
}
}
}
}
for (var i in hidden){
hidden[i].parentNode.removeChild(hidden[i]);
}
This removes divs with the "display: none" style. I tested it on the OP's example. Note: I added a "some-container" id when testing.
function removeDivs() {
"use strict";
//Some container.
const someContainer = document.getElementById("some-container");
//Divs inside it.
const divsInside = someContainer.querySelectorAll("div");
//Loop, remove div if "display: none".
divsInside.forEach(function (divInside) {
const style = window.getComputedStyle(divInside);
if (style.display === "none") {
someContainer.removeChild(divInside);
}
});
}
removeDivs();

Categories