I have 2 tabs at the top of a page. When one tab is clicked, I would like that tab to have an "active" class and the other tab to have an "inactive" class so that the user can see what tab is currently selected. How can I go about doing this with javascript/css?
<div class="tabActive">
Option 1
</div>
<div id="tabInactive">
Option 2
</div>
another non-jQuery solution could be the following that works with more than two div:
function changeClass(elClass) {
var divsLenght = document.getElementsByTagName("div").length;
for (var i = 0; i < divsLenght; i++) {
document.getElementsByTagName("div")[i].className = "tabInactive";
}
elClass.className = "tabActive";
}
Demo: http://jsbin.com/opetec/2
<div class="tabInactive" onclick="this.classname='tabActive'"></div>
if using jquery:
$("div.tabInactive").click(function() {
$("div.tabInactive").removeClass("tabActive");
$(this).addClass("tabActive");
});
here's a solution that doesn't use any jQuery! it does assume there is only 2 tabs thought.
http://jsfiddle.net/nYpV3/
<div id="tab1" onclick="setToActive(this, 'tab2');">
Option 1
</div>
<div id="tab2" onclick="setToActive(this, 'tab1');">
Option 2
</div>
function setToActive(me, otherId){
me.className='active';
document.getElementById(otherId).className='inactive';
}
Give your tabs a class of "tab"...
HTML:
<div class="tab">
...
</div>
<div class="tab">
...
</div>
JS:
function getByClass(_class, elem) {
var i, result = [], elems = document.getElementsByTagName("div"); //get the elements
for (i = 0; i < elems.length; i++) {
if (elems[i].className.indexOf(_class) !== -1) { //if the elements have the class passed in, add it to the result array
result.push(elems[i]);
}
}
return result;
}
var i, tabs = getByClass("tab", "div"); //get all divs with class tab
for (i = 0; i < tabs.length; i++) { //for each tab...
tabs[i].onclick = function() { //wire up it's click event...
//to clear the other tabs...
var j;
for(j=0; j < tabs.length; j++) {
tabs[j].className = tabs[j].className.replace(" active", "");
}
this.className += " active"; //where active is a class predefined in the CSS
};
}
http://jsfiddle.net/thomas4g/pqMq2/12/
Try this using jQuery
<div class="tab active">
Option 1
</div>
<div class="tab">
Option 2
</div>
<script>
$(function(){
$(".tab").live("click", function(){
$(".tab").removeClass("active");
$(this).addClass("active");
});
});
</script>
This is my guess:
$('.tabActive, #tabInactive').click(function() {
$(this).toggleClass('active');
}
Related
I want to show and hide a div on click of previous and next. I am using jQuery toggle to achieve this. Below is what I have tried so far.
HTML code
<div id="one">a</div>
<div id="two">b</div>
<div id="three">c</div>
<div id="prev">prev</div>
<div id="next">next</div>
jQuery Script
jQuery(function(){
jQuery("#two, #three").hide();
jQuery("#next").on("click", function(){
jQuery("#one, #two, #three").toggle();
});
});
Fiddle link
https://jsfiddle.net/mqns2hy4/
So as you can see from the above, when I click on "next", I want only b to come and then when I click again, I wish to have c only and so on. Similarly on click of "Prev", I want the above to move in reverse and so on.
You could create one variable that holds index of active element and change that variable on click. Then you can hide all elements except one with the current active index.
let active = 0;
let el = $("div");
let total = el.length - 1;
const toggle = (el, index) => {
el.hide()
el.eq(index).show()
}
toggle(el, active)
$('button').on('click', function() {
this.id === 'prev' ? active -= 1 : active += 1;
if(active > total) active = 0;
if(active < 0) active = total
toggle(el, active)
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="one">a</div>
<div id="two">b</div>
<div id="three">c</div>
<button id="prev">prev</button>
<button id="next">next</button>
You could keep the index of the currently shown div:
jQuery(function(){
let index = 0;
// you could also use a class to select them:
let divs = ["#one", "#two", "#three"].map(it => jQuery(it));
divs.forEach(it => it.hide());
jQuery("#next").on("click", function(){
divs[index].show();
if(index > 0) divs[index - 1].hide();
index++;
});
});
$(document).ready(function() {
$(".page").hide();
$("#page1").show();
});
$(document).on('click', "#next", function(){
var pageCount = $(".page").length;
var position = $(".page:visible").data('position');
$(".page:visible").hide();
if(position < pageCount){
$("#page" + (position+1)).show();
}
else
{
$("#page1").show();
}
});
$(document).on('click', "#prev", function(){
var position = $(".page:visible").data('position');
var pageCount = $(".page").length;
$(".page:visible").hide();
if(position > 1){
$("#page" + (position-1)).show();
}
else
{
$("#page" + pageCount).show();
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="page1" data-position="1" class="page">a</div>
<div id="page2" data-position="2" class="page">b</div>
<div id="page3" data-position="3" class="page">c</div>
<div id="prev">prev</div>
<div id="next">next</div>
I have a few click handler events on my page that simply add an active class to an element. I only want the event to trigger if the current section has the class active. I have this working ok but what I am doing is running the same for loop and if statement check for the active class on my section for the different click events. Looking for the simplest way to re-use it using just javascript not jquery.
<section class="section section-1 active">
<div class="button">
<div class="hidden-background"></div>
</div>
<div class="hidden-content"></div>
</section>
<section class="section section-2">
<div class="button">
<div class="hidden-background"></div>
</div>
<div class="hidden-content"></div>
</section>
<section class="section section-3">
<div class="button">
<div class="hidden-background"></div>
</div>
<div class="hidden-content"></div>
</section>
The button click event checks for the active section and just finds the first div tag (hidden-background) and applies an active class to it.
var section = document.querySelectorAll('.section');
var button = document.querySelectorAll('.button');
for (var s = 0; s < section.length; s++) {
if (section[s].classList.contains('active')) {
for (var b = 0; b < button.length; b++) {
button[b].addEventListener('click', function(){
this.getElementsByTagName('div')[0].classList.add('active');
});
}
}
}
The second click event again checks for the active section class and then adds the class active to the hidden-content div.
var section = document.querySelectorAll('.section');
var hiddenContent = document.querySelectorAll('.hidden-content');
for (var s = 0; s < section.length; s++) {
if (section[s].classList.contains('active')) {
for (var h = 0; h < hiddenContent.length; h++) {
hiddenContent[h].addEventListener('click', function(){
this.classList.add('active');
});
}
}
}
Thank you
I would do something like this:
const makeActive = function(evt) {
evt.target.parentElement
.querySelectorAll('.hidden-background, .hidden-content')
.forEach( el => el.classList.add('active'));
};
document
.querySelectorAll('.section.active .button')
.forEach( btn => btn.addEventListener('click', makeActive) );
And assuming the active sections also are toggled by javascript. (The above would no longer work if someone changed the active section, since the eventListener is still bound to the old section)
const makeActive = function(evt) {
if(
evt.target.className.contains('button') &&
evt.target.parentElement.className.contains('active')
){
evt.target.parentElement
.querySelectorAll('.hidden-background, .hidden-content')
.forEach( el => el.classList.add('active'));
}
};
document
.querySelectorAll('.section')
.forEach( section => section.addEventListener('click', makeActive) );
Of course, this whole thing would be easier with only css:
.hidden-background, .hidden-content { display: none; }
.active .hidden-background, .active .hidden-content { display: block; }
but I suppose that is a different question altogether...
This question already has answers here:
JavaScript and getElementById for multiple elements with the same ID
(13 answers)
Closed 4 years ago.
i am trying to create a filter with a checkbox when someone clicks on the check box it will hide all the div1
//so far i have used
function div1hide() {
document.getElementById("dive1").style.display ='none';
}
var hider = document.getElementById("div1");
document.addEventListener("click", dive1hide, false);
< id="div1">test</div>
< id="div1">test</div>
< id="div1">test</div>
< id="div1">test</div>
it only hides the first one i m not sure why its not hiding all the other ones...
Something like this maybe?
<div class="div1">test</div>
<div class="div1">test</div>
<div class="div1">test</div>
<div class="div1">test</div>
<input type="checkbox" id="hider" />
<script>
var div1 = document.getElementsByClassName("div1"); // divs to control
var hider = document.getElementById("hider"); // checkbox
div1.toggleStatus = "on"; // let's go!
hider.onclick = function(){ // what happen when hitting the checkbox
switch(div1.toggleStatus){ // two options
case "on": // 1: hide it!
div1.toggleStatus="off"; // hit the checkbox again and jump to 2nd option
for (i = 0; i < div1.length; i++) { // choose all elements
div1[i].style.display = "none"; // hide them
}
break;
case "off": // 1. show it!
div1.toggleStatus="on"; // hit the checkbox again and jump to 1st option
for (i = 0; i < div1.length; i++) { // choose all elements
div1[i].style.display = "block"; // show them
}
break;
}
}
</script>
Change this to look more like this. getElementsByClassName returns an object, which can then be iterated through to change the display of all the elements in that selection.
function div1hide() {
var els = document.getElementsByClassName("div1");
for(const el in els){
els[el].style.display = "none";
}
}
var hider = document.getElementsByClassName("div1");
document.addEventListener("click", div1hide, false);
<div class="div1">test</div>
<div class="div1">test</div>
<div class="div1">test</div>
<div class="div1">test</div>
function div1hide() {
var els = document.getElementsByClassName('div1');
for(var i = 0; i < els.length; i++){
els[i].style.display = 'none';
}
}
document.getElementById('hide').addEventListener('click', div1hide, false);
<div class="div1">test</div>
<div class="div1">test</div>
<div class="div1">test</div>
<div class="div1">test</div>
<div id="hide">Click to hide.</div>
I wanted to write a program that would return a child elements position inside the parent element, but I am having problems. I tried writing the following code but it did not work as expected; Instead of returning the position value it returned the click event. Here is what I tried doing:
(P.S I wanted to solve this problem in raw JS)
(function () {
// body...
var x = document.getElementsByClassName("bubble");
for(var i=0; i<x.length; i++) {
x[i].addEventListener('click', function(i){
console.log(i);
});
}
})();
HTML:
<div id=holder>
<div class="bubble"></div>
<div class="bubble"></div>
<div class="bubble"></div>
<div class="bubble"></div>
</div>
If you are wanting to find the position as in the x and y coordinates, you can do the following:
make sure the parent div (#holder) is positioned
Make use of offsetLeft and offsetTop
If you are wanting to find position as in array position, you can use
Array.prototype.indexOf.call(collection, element)
(function() {
// body...
var x = document.getElementsByClassName("bubble");
for (var i = 0; i < x.length; i++) {
x[i].addEventListener('click', function(a) { // change the variable name here otherwise you have a local var i conflicting with the loop var i
console.log(this.offsetLeft, this.offsetTop); // this is the element clicked
console.log(Array.prototype.indexOf.call(x, this) + 1); // this is the position as an index (plus 1)
});
}
})();
#holder {
position:relative; /* position the parent */
}
<div id="holder">
<div class="bubble">1</div>
<div class="bubble">2</div>
<div class="bubble">3</div>
<div class="bubble">4</div>
</div>
i in your listener's function stands for the whole element and his events, not for the index from your for loop. Logging it may crash/lag your browser.
I would suggest you to use ES6 treasures with Array#forEach.
const elems = document.querySelectorAll('#holder .bubble');
Array.from(elems).forEach((v, i) => v.addEventListener('click', () => {
console.log(`Child position: ${i}`);
}));
<div id="holder">
<div class="bubble">a</div>
<div class="bubble">b</div>
<div class="bubble">c</div>
<div class="bubble">d</div>
</div>
However, if you really want to use for loop, do not pass any arguments into your listener's function and change var i inside your loop into let i.
const x = document.getElementsByClassName("bubble");
for (let i = 0; i < x.length; i++) {
x[i].addEventListener('click', function() {
console.log(i);
});
}
<div id="holder">
<div class="bubble">a</div>
<div class="bubble">b</div>
<div class="bubble">c</div>
<div class="bubble">d</div>
</div>
You can use this funcion: https://developer.mozilla.org/en-US/docs/DOM/element.getBoundingClientRect
https://jsfiddle.net/dt1224Ld/
(function () {
// body...
var x = document.getElementsByClassName("bubble");
for(var i=0; i<x.length; i++) {
x[i].addEventListener('click', function(i){
var element = this.getBoundingClientRect();
console.log(element.top, element.right, element.bottom, element.left);
});
}
})();
I have a search page, and I found a script for a tab component which seperates the TV-Show search page and Movie search page. When a user clicks on lets say the "Movie" tab, and perform a search from there, I make the form add ?type=movie&... to the url. But, when they perform the search, the tab that's selected is the the "TV-Show" tab, and the have to click over to get to the other tab which has the results they want.
Here is the code, and in it is some of what I tried:
the HTML looks like this:
<article class="first">
<h2>Search</h2>
<hr/>
<div id="tabWrapper">
<div id="tabContainer">
<div class="tabs">
<ul>
<li id="tabHeader_1">TV Shows</li>
<li id="tabHeader_2">Movies</li>
</ul>
</div>
<div class="tabContent">
<div class="tabpage" id="tabpage_1">
<?php
if (isset($sortFilt['year']))
unset($sortFilt['year']);
if ($sortField=="year")
$sortField==" ";
DisplaySearchPage("shows", $terms, $sortField, $sortDir, $sortFilt, $page, $perPage);
?>
</div>
<div class="tabpage" id="tabpage_2">
<?php
DisplaySearchPage("movies", $terms, $sortField, $sortDir, $sortFilt, $page, $perPage);
?>
</div>
</div>
</div>
</div>
</article>
<script src="tabs.js"></script>
And this is the the tabs.js script:
window.onload=function() {
// get tab container
var container = document.getElementById("tabContainer");
// set current tab
var navitem = container.querySelector(".tabs ul li");
//store which tab we are on
var ident = navitem.id.split("_")[1];
navitem.parentNode.setAttribute("data-current",ident);
//set current tab with class of activetabheader
navitem.setAttribute("class","tabActiveHeader");
//hide two tab contents we don't need
var pages = container.querySelectorAll(".tabpage");
for (var i = 1; i < pages.length; i++) {
pages[i].style.display="none";
}
//this adds click event to tabs
var tabs = container.querySelectorAll(".tabs ul li");
for (var i = 0; i < tabs.length; i++) {
tabs[i].onclick=displayPage;
}
// This below is is what I tried.
var selTab = (getUrlVars()["type"] == "movies") ? 2 : 1;
var selTab = (getUrlVars()["type"] == "movies") ? 1 : 0; // Tried this too.
tabs[selTab].click();
// its seems like it should have worked, what am I doing wrong.
}
// on click of one of tabs
function displayPage() {
var current = this.parentNode.getAttribute("data-current");
//remove class of activetabheader and hide old contents
document.getElementById("tabHeader_" + current).removeAttribute("class");
document.getElementById("tabpage_" + current).style.display="none";
var ident = this.id.split("_")[1];
//add class of activetabheader to new active tab and show contents
this.setAttribute("class","tabActiveHeader");
document.getElementById("tabpage_" + ident).style.display="block";
this.parentNode.setAttribute("data-current",ident);
}
How can I adapt this script to let me decide which tab is displayed when the page is loaded based on what the type variable is in the URL parameters?
I found the answer. My problem was with getUrlVars["type"], it failed to give me the value of the 'type' url variable, so I created my own function for it. Here is the working code if anyone else is wondering how to get variables from the url.
function getURLParameter(name)
{
return decodeURI(
(RegExp(name + '=' + '(.+?)(&|$)').exec(location.search)||[,null])[1]
);
}
window.onload = function()
{
// Get tab container
var container = document.getElementById("tabContainer");
// Set the current tab.
var navitem = container.querySelector(".tabs ul li");
// Store which tab is selected.
var ident = navitem.id.split("_")[1];
navitem.parentNode.setAttribute("data-current", ident);
// Set the current tab with a class of 'activetabheader'.
navitem.setAttribute("class", "tabActiveHeader");
// Hide the tab contents we don't need.
var pages = container.querySelectorAll(".tabpage");
for (var i = 1; i < pages.length; i++) {
pages[i].style.display = "none";
}
// This adds the click event handler to the tabs.
var tabs = container.querySelectorAll(".tabs ul li");
for (var i = 0; i < tabs.length; i++) {
tabs[i].onclick = displayPage;
}
// Selects tab based on 'type' url variable.
if (getURLParameter("type") == "movies") {
tabs[1].click();
}
}
// OnClick() event handler for tabs.
function displayPage()
{
var current = this.parentNode.getAttribute("data-current");
// Remove class of 'activetabheader' and hide the old contents.
document.getElementById("tabHeader_" + current).removeAttribute("class");
document.getElementById("tabpage_" + current).style.display = "none";
var ident = this.id.split("_")[1];
// Add a class of 'activetabheader' to new active tab and show contents.
this.setAttribute("class", "tabActiveHeader");
document.getElementById("tabpage_" + ident).style.display = "block";
this.parentNode.setAttribute("data-current", ident);
}