I'm working with HTML and JavaScript and I need to make two instances of a toggle link. Here is my code for a single one:
<script language="javascript">
function toggle() {
var ele = document.getElementById("toggleText");
var text = document.getElementById("displayText");
if(ele.style.display == "block") {
ele.style.display = "none";
text.innerHTML = "link1";
}
else {
ele.style.display = "block";
text.innerHTML = "link1";
}
}
</script>
<body> <a id="displayText" href="javascript:toggle()" style="font-size:160%;">link1</a>
<div id="toggleText" style="display: none; font-size:160%;"><p>paragraph1</p></div><br></body>
I need the two toggle links to independently show/hide different paragraphs of text when each one is clicked. How can I add a second instance below the first?
Add an event handler and a data-toggle-id attribute to each link. In your event handler, get the value of the data-toggle-id and use that to find the paragraph that you would like to show. Then use the toggle method of the element's classList to add/remove a class that shows the paragraph.
var links = document.querySelectorAll('[data-toggle-id]');
for (var ix = 0; ix < links.length; ix++) {
links.item(ix).addEventListener('click', function() {
document.getElementById(this.dataset.toggleId).classList.toggle('show');
});
}
.toggleText {
display: none;
}
.show {
display: block;
}
<link href="//cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.4/skeleton.min.css" rel="stylesheet" />
<div class="container">
<a data-toggle-id="paragraph1">link1</a>
<div class="toggleText" id="paragraph1">
<p>paragraph1</p>
</div>
</div>
<div class="container">
<a data-toggle-id="paragraph2">link2</a>
<div class="toggleText" id="paragraph2">
<p>paragraph2</p>
</div>
</div>
<div class="container">
<a data-toggle-id="paragraph3">link3</a>
<div class="toggleText" id="paragraph3">
<p>paragraph3</p>
</div>
</div>
If you hate for loops, you can use Nick's suggestion and convert the NodeList to and array and use the forEach method:
Array.prototype.slice.call(document.querySelectorAll('[data-toggle-id]')).forEach(function(element) {
element.addEventListener('click', function(){
document.getElementById(this.dataset.toggleId).classList.toggle('show');
});
});
Related
I'm trying to write a function toggle_active to show the hidden content on a click, and collapse the content again on one more click. Sadly, it does not work. Could you help me modify it?
function toggle_active(this){
var x = this.nextSibling;
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
};
}
.daccord_b{
display:none;
}
<header class="ca_h" onclick="toggle_active(this);">
<i class="i i-plus ca_hi"></i>
Title
</header>
<div class="had daccord_b">Hidden content</div>
Use method nextElementSibling to return the next element. And it is not necessary to use the if {} operator.
Don't use this for arguments in functions.
The more correct way for your task is method toggle(), which your class uses in css .daccord_b.
function toggle_active(el) {
var x = el.nextElementSibling;
x.classList.toggle("daccord_b");
}
.daccord_b {
display: none;
}
<header class="ca_h" onclick="toggle_active(this);">
<i class="i i-plus ca_hi"></i>
Title
</header>
<div class="had daccord_b">Hidden content</div>
Second solution using style.display.
function toggle_active(el) {
var x = el.nextElementSibling;
x.style.display = x.style.display === 'block' ? 'none' : 'block';
}
.daccord_b {
display: none;
}
<header class="ca_h" onclick="toggle_active(this);">
<i class="i i-plus ca_hi"></i>
Title
</header>
<div class="had daccord_b">Hidden content</div>
js:
function toggle_active(id){
var x = document.getElementById(id);
if (x.style.display === "none" || x.style.display === "") {
x.style.display = "block";
} else {
x.style.display = "none";
};
}
html:
<header class="ca_h" onclick="toggle_active('HiddenContent');">
toggle
</header>
<div class="had daccord_b" id='HiddenContent'>Hidden content</div>
You're having some syntax errors in this code. First, I suggest you name the function arguments something other than this because this is a reserved keyword in JavaScript.
Secondly, I recommend consulting with W3School with such simple problems before reaching out, as most of the time, there is a simple solution :)
Here's a link that solves exactly the problem you're describing.
https://www.w3schools.com/howto/howto_js_collapsible.asp
And, here's an example and how you can achieve this:
let content = document.getElementById("content");
function handleClick() {
if (content.classList.contains("hide")) {
content.classList.remove("hide");
} else {
content.classList.add("hide");
}
}
.my-content {
display: block;
}
.my-content.hide {
display: none;
}
<button onclick="handleClick()">Toggle</button>
<div class="my-content" id="content">Hello, some content</div>
EDIT If you decide to introduce jQuery to your project, you can achieve it even with fever lines of code:
$("[data-collapse]").on('click', function () {
let target = $(this).data('collapse');
$(target).toggle();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button data-collapse="#content">Clicker</button>
<div id="content">
My Content
</div>
This makes it abstract and reusable, even allowing you to do things like separate containers:
$("[data-collapse]").on('click', function () {
let target = $(this).data('collapse');
$(target).toggle();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button data-collapse="#target1">Collapse #1</button>
<button data-collapse="#target2">Collapse #2</button>
<div id="target1">
<h1>I'm Target #1</h1>
</div>
<div id="target2">
<h1>I'm target #2</h1>
</div>
It is a good practice to use an Event object in you handler function when you can. Please read this post then try fixing your code accordingly: What exactly is the parameter e (event) and why pass it to JavaScript functions?
More about Event.currentTarget here: https://developer.mozilla.org/en-US/docs/Web/API/Event/currentTarget
function toggle_active(evt){
var x = evt.currentTarget.nextElementSibling;
x.classList.toggle('daccord_b');
}
.daccord_b {
display: none;
}
<header class="ca_h" onclick="toggle_active(event);">
<i class="i i-plus ca_hi"></i>
Title
</header>
<div class="had daccord_b">Hidden content</div>
Here is the concept of my content being shown/hidden. It also works.
https://jsfiddle.net/mplungjan/a7Lfjsgh/
It works in the small html code above. However, it does not work when I apply it to my larger HTML code. Does someone know why?
My goal is to have many list items with spans attached to the reveal answers button.
HTML:
<nav class="Rightbox" id="RightFrench">
<div id="Stage1">
<h1>Stage 1</h1>
<h5> <span class="HighlightBlue">Exercise 1 - </span></h5>
<h5><button class="AnswerTitle" id="AnswersFrenchStage1Ex1">Reveal Answers</button></h5>
<p class="Task">
<span class="HighlightBlue">Translate the following</span>
</p>
<ul>
<li>
<p> the passeport <textarea></textarea>
<span class="FrenchStage1Ex1">la passeport</span>
</p>
</li>
<li>
<p>the passeport <textarea></textarea>
<span class="FrenchStage1Ex1">la passeport</span>
</p>
</li>
</div>
</nav>
Javascript:
window.onload = function() {
var buttons = document.querySelectorAll(".AnswerTitle");
for (var i = 0; i < buttons.length; i++) {
buttons[i].onclick = function() {
var id = this.id.replace(/reveal/, "FrenchStage");
var answers = document.querySelectorAll("." + id);
for (var i = 0; i < answers.length; i++) {
answers[i].style.display = answers[i].style.display == "inline" ? "none" : "inline";
}
}
}
}
CSS:
.Rightbox ul li p span {display:none;}
the problem turns out to be I changed the id of the button, thinking that the javascript was not using the button id. turns out the
var id = this.id.replace(/reveal/, "FrenchStage")
really wanted the button to have an ID containing "reveal"
My HTML
<div class="chapter">text text text </div>
<div class="chapter">text text text </div>
<button id="button">button</button>
My js
var button = document.querySelector('#button');
var chapter = document.querySelectorAll('.chapter');
for(var i = 0; i < chapter.length; i++){
button.addEventListener('click', function(){
for(var i = 0; i < chapter.length; i++) {
chapter[i].classList.add('active');
}
});
}
This adds the class of "active" on clicking the button.
But toggle doesn't work. Instead of
chapter[i].classList.add('active');
When I do,
chapter[i].classList.toggle('active');
the class of "active" does not toggle. console shows no error.
So I tried to check the class of "active" first & remove the class if the class exists. I know I was trying to reinvent the toggle function; as stated above, toggle wasn't working so I tried it anyway.
if (chapter[i].contains('active')){
chapter[i].classList.remove('active');
And I got a slew of error messages. This is as far as I got. I somehow felt that this wasn't going to work but just tried it anyway.
I am stumped.
Can anyone point out why classList.toggle isn't working in my code & how this can be fixed?
Thanks.
You have one too many loop. Remove the outer one:
var button = document.querySelector('#button');
var chapter = document.querySelectorAll('.chapter');
button.addEventListener('click', function(){
for(var i = 0; i < chapter.length; i++) {
chapter[i].classList.toggle('active');
}
});
.active{
color: red;
}
<div class="chapter">text text text </div>
<div class="chapter">text text text </div>
<div class="chapter">text text text </div>
<div class="chapter">text text text </div>
<button id="button">button</button>
var button = document.querySelector('#button');
var chapters = document.querySelectorAll('.chapter');
button.addEventListener('click', function(){
for(var index = 0; index < chapters.length; index++) {
if(chapters[index].classList.contains('active')){
chapters[index].classList.remove('active');
}else{
chapters[index].classList.add('active');
}
}
});
.active {
color: red;
}
<div class="chapter">text text text </div>
<div class="chapter">text text text </div>
<button id="button">Toggle Color</button>
I have some links that will show a div when clicking it. When clicking another link, it should show the link's associated div and hide the previously shown div.
HTML
Text 1
Text 2
Text 3
<div id="text1" class="unhidden">
This will show up when the Text 1 link is pressed.
</div>
<div id="text2" class="hidden">
This will show up when the Text 2 link is pressed.
</div>
<div id="text3" class="hidden">
This will show up when the Text 3 link is pressed.
</div>
Javascript
function unhide(divID) {
var item = document.getElementById(divID);
if (item) {
item.className='unhidden';
}
}
CSS
.hidden { display: none; }
.unhidden { display: block; }
How can I accomplish this?
Try with:
function unhide(divID) {
var unhidden = document.getElementsByClassName('unhidden');
for (var k in unhidden) {
unhidden[k].className='hidden';
}
var item = document.getElementById(divID);
if (item) {
item.className='unhidden';
}
}
You can do something like this :
function unhide(divID) {
var divs = document.getElementsByTagName('div');
foreach(var div in divs){
div.className = 'hidden';
if(div.id == divID)
div.className = 'unhidden';
}
}
Be careful with document.getElementsByTagName('div');, it will return you all divs on your document. You could adapt it using a wrapper.
For example :
HTML
<div id="wrapper">
<div id="text1" class="unhidden">
This will show up when the Text 1 link is pressed.
</div>
<div id="text2" class="hidden">
This will show up when the Text 2 link is pressed.
</div>
<div id="text3" class="hidden">
This will show up when the Text 3 link is pressed.
</div>
</div>
JS :
var divs = document.getElementById('wrapper').getElementsByTagName('div');
Try this http://jsfiddle.net/L79H7/1/:
function unhide(divID) {
var divIds = [ "text1", "text2", "text3" ];
for ( var i = 0, len = divIds.length; i < len; i++) {
var item = document.getElementById(divIds[i]);
if (item) {
item.className = divID == divIds[i] ? 'unhidden' : 'hidden';
}
}
}
You could also store in an array the names of the divs you want to hide and iterate over it when unhiding one:
var divs= new Array("text1", "text2", "text3");
function unhide(divID) {
var item = document.getElementById(divID);
if (item) {
item.className='unhidden';
}
for (var i in divs){
if (divs[i] != divID){
item = document.getElementById(divs[i]);
if (item) {
item.className='hidden';
}
}
}
}
JSFiddle
You don't need exactly links for this, but if you insist change it to:
<a href="#" onclick='unhide("text3");'>Text 3</a>
Otherwise you can change it to:
<p onclick="unhide('text1')">Text 1</p>
<p onclick="unhide('text2')">Text 2</p>
<p onclick="unhide('text3')">Text 3</p>
<div id="text1" class="unhidden">
This will show up when the Text 1 link is pressed.
</div>
<div id="text2" class="hidden">
This will show up when the Text 2 link is pressed.
</div>
<div id="text3" class="hidden">
This will show up when the Text 3 link is pressed.
</div>
And your function should look like this to add or remove classes:
function unhide(id){
yourElement = document.getElementById(id);
if(yourElement.className == "unhidden"){
yourElement.className = "hidden";
}else{
yourElement.className = "unhidden";
}
}
demo
<div id="text1" class="hidden"> 1 </div>
<div id="text2" class="hidden"> 2 </div>
<div id="text3" class="hidden"> 3 </div>
.hidden{ display:none; }
#text1{ display: block; }
function show(id) {
var item = document.getElementById(id);
var all = document.getElementsByClassName('hidden');
for(var i=0; i<all.length; i++)all[i].style.display = 'none';
if(item)item.style.display = 'block';
}
you can use jquery try the code below and import the jquery library first
$('#text1').show();
$('#text2').hide();
it is the easiest way
I have Javascript tabs which show/hide divs instead of loading new pages. The tabs have a style which gives a hover effect. I now want to add an active style to match up with the curently visible div.
THE JAVASCRIPT, which does not work as it is from a version which loads pages:
function setActive() {
aObj = document.getElementById('nav').getElementsByTagName('a');
for(i=0;i < aObj.length;i++) {
if(document.location.href.indexOf(aObj[i].href) >= 0) {
aObj[i].className='active';
}
}
}
function showdiv(id){
document.getElementById(id).style.display = "block";
}
function hidediv(id){
document.getElementById(id).style.display = "none";
}
THE STYLE:
#pageAdmin { display:block; }
#userAdmin { display:none; }
THE HTML:
<ul id="nav">
<li><a onclick="showdiv('pageAdmin'); hidediv('userAdmin')"
href="#">Page Admin</a></li>
<li><a onclick="showdiv('userAdmin'); hidediv('pageAdmin')"
href="#">User Admin</a></li>
</ul>
<div id="pageAdmin">
<h1>Page admin</h1>
</div>
<div id="userAdmin">
<h1>User admin</h1>
</div>
This is my first question on SO, so I hope it is appropriate - please accept my apologies in advance if it is not!
Your setActive function isn't very helpful. And using location, href and hash it will be hard doing what you want.
You may change your script to
function showdiv(id){
var el = document.getElementById(id);
el.style.display = "block";
el.className = "active";
}
function hidediv(id){
var el = document.getElementById(id);
el.style.display = "none";
el.className = "";
}
Now it should do what you want.
However, you should take a look on jQuery.
Using jQuery you do eliminate the use of getElementById and you can much simpler attach an eventhandler for onclick's, as by using vanilla js. It is considered as bad practice to setup handlers in html attributes.
jQuery also handles you the splitting and joining the space separated className string, if you want to use multiple styles.
Using jQuery it looks like:
$("a", "#nav").click(function () {
var $navA = $(this);
var tabName = $navA.attr("data-tabName");
$(".tab").each(function () {
var $tab = $(this);
if ($tab.attr("id") === tabName) {
$tab.css({ display: 'block' }); // you may move this into active style
$tab.addClass("active");
$tab.removeClass("inactive");
}
else {
$tab.css({ display: 'none' }); // you may move this into inactive style
$tab.removeClass("active");
$tab.addClass("inactive");
}
});
});
The HTML for the jQuery example
<ul id="nav">
<li><a data-tabName="pageAdmin" href="#">Page Admin</a></li>
<li><a data-tabName="userAdmin" href="#">User Admin</a></li>
</ul>
<div class="tab" id="pageAdmin">
<h1>Page admin</h1>
</div>
<div class="tab" id="userAdmin">
<h1>User admin</h1>
</div>