Toggle visibility for multiple divs with one function: navigation bar - javascript

My Assignment: Hi! I am doing an assignment in school where I am supposed write code in Javascript in order to toggle visibility for the submenus each belonging to their own topmenu in a navigation bar for a webpage. The visibility should be set to hidden by default and should be shown when a topmenu is clicked on.
I know how to toggle visibility for ONE submenu belonging to a topmenu, but fail to make my code work for multiple elements. My HTML-code:
<a class="left_top1" onclick = "toggle()">Opinion</a><br>
<div class="left_submenu_1" style="display: none;">
<a class="left_sub1">Leaders</a><br>
<a class="left_sub1">Debates</a><br>
</div>
<br>
<a class="left_top2" onclick = "toggle()">Economy</a><br>
<div class="left_submenu_2" style="display: none;">
<a class="left_sub2">News</a><br>
<a class="left_sub2">Your Economy</a><br>
</div>
My Problem: The topmenus I speak of are "Opinion" and "Economy". The visibility of the div with the class "left_submenu_1" should be toggled when you click the topmenu "left_top1". Thus should the visibilily of the div with the class "left_submenu_2" be toggled when you click the topmenu "left_top2". This is what I fail to do. My Javascript code is so far:
function toggle() {
var e = document.querySelectorAll("div.left_submenu_1, div.left_submenu_2");
for (var i=0; i < e.length; i++) { // I know this will enable/disable the visibility for ALL elements selected from the querySelectorAll, which should NOT happen
if(e[i].style.display == "none") {
e[i].style.display = "block";
} else if(e[i].style.display == "block") {
e[i].style.display = "none";
}
}
}
Anyone who knows how to solve this issue of mine? I know there are errors in the for-loop (as I wrote next to it), but this is the best I can manage for now.
Please note: We are NOT allowed to use jQuery or to give the topmenus id:s, as the idea is to use one general function to toggle the visibility. Furthermore, the code which enables the toggle-function should be done in Javascript.

I would approach it by passing the class name of the div to be shown (or hidden) into the function to begin with.
HTML
<a class="left_top1" onclick = "toggle('.left_submenu_1')">Opinion</a>
Then in the function you can grab the element and toggle it's display state.
JavaScript
function toggle(qs) {
var e = document.querySelector(qs);
e.style.display = e.style.display === 'block' ? 'none' : 'block';
}
The e.style.display === 'block' ? 'none' : 'block' part is saying if the elements display state is equal to block, return none, otherwise return block.
The return value is set as the new element display state due to the e.style.display = beforehand.

Tring to make it work modifying it as less as possible :
- use onClick="toggle(this)" in the anchors tags
- use a bit different toggle function like:
function toggle (el) {
var e = document.querySelectorAll('.' + el.className.replace('top', 'submenu_'))[0];
e.style.display = e.style.display.match(/none/) ? '' : 'none';
}
hope it helps, but I have to suggest You to make a small step forward and search for event delegation. Bye

Related

NWJS JS script not functioning right

Im using JS to make divs display as block or none onclick of certain inputs. When i only have it working for one input the scripts work find, but as soon as i impliment the code for the second input it glitches out and both buttons open up the div thats only supposed to work for the second button.
Some of my code:
<span name="FaviconSPAN" id="FaviconSPAN" class="FaviconSPAN" OnClick="showOrHide()">
<img src="ASSETS/IMAGES/FAVICON1.png" alt="FAVICON" name="FaviconPNG" id="FaviconPNG" class="FaviconPNG" />
</span>
<div name="SoftMenuWrapper1" id="SoftMenuWrapper1" class="SoftMenuWrapper1">
<input type="button" value="Favorites" name="SoftMenuInput1" id="SoftMenuInput1" class="SoftMenuInput1" ONCLICK="ShowAndHide()" />
<div name="SoftMenuContent1" id="SoftMenuContent1" class="SoftMenuContent1">
Link 1
Link 1
Link 1
</div>
</div>
<script type="text/javascript">
var faqPage = document.getElementById('SoftMenuContent1');
function showDiv() {
faqPage.style.display = "block";
}
function closeDiv() {
faqPage.style.display = "none";
}
function showOrHide() {
if (faqPage.style.display === "block") {
closeDiv()
}
else {
showDiv()
}
}
</script>
<SCRIPT>
function ShowAndHide() {
var x = document.getElementById('SectionName');
if (x.style.display == 'none') {
x.style.display = 'block';
} else {
x.style.display = 'none';
}
}
</SCRIPT>
First off the markup looks kinda messy. You don't need to add an ID, name, and class to everything. Only add those things if you need them.
name is rarely used, it's a way to connect to HTML elements. Like connected radio dials. You probably don't need this at all in this code.
class this should only be used if you need to add a specific CSS classname to adjust the styles. If you are not doing that, don't include it.
id should be assigned to a unique value that only occurs once on the page. it can be used to auto-scroll to that position of the page if the url contains #whatever and that matches an element with id="whatever". Though it is more commonly used just to target a specific element in your JavaScript. If you aren't doing either of those things, don't add it.
Another problem you have is order of execution. You can either define your JS first (<script> at the top) and then reference the functions with onclick in the HTML, or (more commonly), define your HTML first with ID's, then have your <script> at the bottom targeting the IDs (document.getElementById('asdf')).
Here is a cleaner version of your code.
<span id="faviconContainer">
<img src="assets/images/favicon1.png" alt="Image of an icon" />
</span>
<div>
<input type="button" value="Favorites" id="softMenuInput" />
<div id="faqPage">
Link 1
Link 2
Link 3
</div>
</div>
<script type="text/javascript">
/**
* Takes in an ID to find an element on the page, then shows/hides it.
*
* #param {string} id The element's ID
*/
function toggle (id) {
var el = document.getElementById(id);
if (el.style.display === 'block') {
el.style.display = 'none';
} else {
el.style.display = 'block';
}
}
var faviconContainer = document.getElementById('faviconContainer');
var softMenuInput = document.getElementById('softMenuInput');
faviconContainer.addEventListener('click', function () {
toggle('faqPage');
});
softMenuInput.addEventListener('click', function () {
toggle('sectionName');
});
</script>
This question isn't related to NW.js at all. It's just basic HTML and JavaScript.
I recommend you follow these resources to improve your skills. You can also rely on the world's largest programming community (HTML/JS) to ask these questions. Then when you have NW.js specific things, you can ask those here.
https://marksheet.io - HTML/CSS/Sass
https://freeCodeCamp.org - JavaScript

Dropdowm menu in Vanilla JavaScript - for unknown number of buttons

please, can you give me a hint with Vanilla JS?
I have dropdown menu opening via button click and have 2 issues:
1) Dropdown is opening by clicking on button with unique ID. I need to get it working on Class name, because it have to be working on multiple buttons - and the number of them is unknown (they will load from REST API).
In jQuery is it working, but I need it in Vanilla JS.
If I try to select button by Class name, it will return array of buttons, but I don't know how to select from array, which button was being clicked on.
2) Dropdown menu is opening only on the second click on the button (and then it is toggling like it should), but the first click doesn't do anything.
My code is here:
// select Button - now by ID - but I need unknown number of buttons - from REST API - and the code working for all of them
var btn = document.getElementById("dropBtn1");
// select Dropdown menu - next to the button - to be sure it will open the right menu no matter which button will be pressed
var menu = btn.nextSibling;
while(menu && menu.nodeType != 1) {
menu = menu.nextSibling
}
//toggle dropdown menu open/close
btn.addEventListener("click", function() {
if (menu.style.display == 'none') {
menu.style.display = 'block';
}
else {
menu.style.display = 'none';
}
});
And working prototype is here on Codepen:
https://codepen.io/vlastapolach/pen/EXdLMy
Please, do you have any ideas how to fix this?
Thank you!
Quite easy, you need a general function that works on the context (=this):
//toggle dropdown menu open/close
function toggle() {
var btn=this;
var menu = btn.nextSibling;
while(menu && menu.nodeType != 1) {
menu = menu.nextSibling
}
if(!menu) return;
if (menu.style.display != 'block') {//fix 2)
menu.style.display = 'block';
} else {
menu.style.display = 'none';
}
});
Now you can assign this functions as an event handler onto all your elements:
window.addEventListener("DOMContentLoaded",function(){
document.querySelectorAll(".sth").forEach(function(btn){
btn.addEventListener("click",toggle,true);
});
});
Note that NodeList.forEach is quite new, may use [].slice to create a real array...
And you need to assign the Handlers to the newly added elements manually, or you need to listen on window and trace back the target:
window.onclick=function(event){
if(event.target.classList.contains("sth")){
toggle.call(event.target);
}
};

Div doesn't stay visible

I have 4 links. When I click the first link div 1 should be displayed and the other 3 hidden.
When I click link 2, div 2 should be displayed and the other 3 hidden, and so on...
What I did:
With CSS I've set the class of the 4 divs to display: none
Created 4 functions with javascript that set the display property of the correct div to block and the 3 others to none
Call the function when clicking the link
When I click a link, the div is shown for a quarter of a second but then it disappears again
CSS:
.CatDiv {
display:none;
}
JS function:
function showKadoballonnen() {
document.getElementById("Kadoballonnen").style.display = "block"
document.getElementById("Geschenkmanden").style.display = "none"
document.getElementById("Pampercadeaus").style.display = "none"
document.getElementById("OrigineleVerpakkingen").style.display = "none";
}
Calling the function:
Kadoballonnen
Div that has to be called:
<div id="Kadoballonnen" class="CatDiv">TEST</div>
function showKadoballonnen(e) {
e.preventdefault();
document.getElementById("Kadoballonnen").style.display = "block";
document.getElementById("Geschenkmanden").style.display = "none";
document.getElementById("Pampercadeaus").style.display = "none";
document.getElementById("OrigineleVerpakkingen").style.display = "none";
}
.CatDiv {
display: none;
}
Kadoballonnen
<div id="Kadoballonnen" class="CatDiv">TEST</div>
<div id="Geschenkmanden" class="CatDiv">TEST</div>
<div id="Pampercadeaus" class="CatDiv">TEST</div>
<div id="OrigineleVerpakkingen" class="CatDiv">TEST</div>
What am I missing?
All is easier than you think. In your tag you got "href" with empty parameter. It makes your page reloading while pressing on it.
So all you should do is to write "#" as a parameter.
Kadoballonnen
You should avoid empty href attribute on a link. Use a button instead.
If it still does not work, attach your method to window object. Also, I don't recommend this approach, you should handle it in your Javascript by targetting at your DOM elements using an ID for example and adding your event listener from here.
document.getElementById('myelement').addEventListener('click', showKadoBallonnen);
You have a few errors in your code, and you also need to stop your link (<a>) firing.
On your link, add return false;:
Kadoballonnen
<!-- ^ Also, add href="#" so you don't have an empty href -->
Also, add semicolons to the end of each line of your javascript:
document.getElementById("Kadoballonnen").style.display = "block";
document.getElementById("Geschenkmanden").style.display = "none";
document.getElementById("Pampercadeaus").style.display = "none";
document.getElementById("OrigineleVerpakkingen").style.display = "none";
I was running into this problem while writing some coffeescript in a rails application. Another answer helped me.
The solution is the event.preventDefault() as shown below:
app/views/posts/index.html.erb:
<%= link_to "Some link", '#', id: 'some-link' %>
<div class="some-div">
<h4>Some list</h4>
<ul id='some-list'>
<li>cats</li>
<li>and</li>
<li>dogs</li>
</ul>
</div>
app/assets/javascripts/posts.coffee:
$(document).on 'turbolinks:load', ->
$('#some-link').click (event) ->
event.preventDefault()
$('#some-list').toggle()
I managed to make it working: https://jsfiddle.net/ke81koj6/
function showKadoBallonnen() {
document.getElementById("one").style.display = "block";
document.getElementById("two").style.display = "none";
document.getElementById("three").style.display = "none";
document.getElementById("four").style.display = "none";
}
EDIT
Edited the fiddle and now works with the press on a button. It's better to use a button than an anchor with a empty href.
HTML:
<button id="button" onclick="showKadoBallonnen()">click here</button>
JS:
document.getElementById("button").onclick = showKadoBallonnen;

Javascript Collapsible Menu (hide the other elements)

I have the following working Javascript function:
function collapsible(zap) {
if (document.getElementById) {
var abra = document.getElementById(zap).style;
if (abra.display == "block") {
abra.display = "none";
} else {
abra.display = "block";
}
return false;
} else {
return true;
}
}
When I use the following in html code it displays or hides the "element" div:
<li>Element</li>
Thats working fine. But the problem is, that I want to use the function for multiple links, and then the other elements, that were clicked before, stay, open.
How can I reprogram the code, so that only one div stays open and the other gets closed if i click on another link?
Thanks beforehand!
If you could use jQuery and more importantly jQueryUI accordion I think it would accomplish exactly what you're looking for.
However, without using those two, here is how I would structure it. Like mentioned above, I would use classes to modify the styles of the divs you want shown or hidden. Then the js code can just toggle those classes on each of your elements. The slightly more difficult part (without jquery) is modifying class values since in your final application you may have lots of classes on each div. This is just a very crude example to get you going.
Working JSFiddle Example
Sample DOM
<div >
<li>Element1</li>
<div id='elem1' class='myelem visible'>
Element 1 contents
</div>
</div>
<div >
<li>Element2</li>
<div id='elem2' class='myelem'>
Element 2 contents
</div>
</div>
<div >
<li>Element3</li>
<div id='elem3' class='myelem'>
Element 3 contents
</div>
</div>
Sample JS
window['collapsible'] = function(zap) {
if (document.getElementById)
{
var visDivs = document.getElementsByClassName('visible');
for(var i = 0; i < visDivs.length; i++)
{
visDivs[i].className = visDivs[i].className.replace('visible','');
}
document.getElementById(zap).className += " visible";
return false;
}
else
return true;
}
Sample CSS:
.myelem {
display: none;
}
.visible {
display: block;
}
The way to go is to create a class(or maybe two), like collapsible and active or open that has this style(display: block or none) and then you working adding or removing the class.
The logic would be:
Links that has the class collapsible when clicked would add the active or open class which would give the behavior that remains opens(or active) by css.
If you want to hide others elements you would look for the elements with the class collapsible and then remove the active(or open) class if has any.
Here is my solution: http://jsfiddle.net/g5oc0uoq/
$('.content').hide();
$('.listelement').on('click', function(){
if(!($(this).children('.content').is(':visible'))){
$('.content').slideUp();
$(this).children('.content').slideDown();
} else {
$('.content').slideUp();
}
});
show() and hide() can be used instead of slideUp() and slideDown() if you have performance issues.

Display : None/Block Style Tab Menu Creation with Buttons and Javascript

function tab_menu(){
if (buttonObject.value == value){
document.getElementById("div1").style.display = "block";
}
}
i was trying when click to buttons check Button Value and show a div based on Button's Value and hide others divs it should show just one div at same time. I wonder there is a javascript Master who can solve this problem.
SCRIPT:
function tabmenu(buttonObject){
var value = buttonObject.value
var target = document.getElementById(value);
if(target) {
var siblings = target.parentNode.getElementsByTagName("DIV");
for(i=0;i<siblings.length;i++){
siblings[i].style.display = "none";
}
target.style.display = "block";
}
}
HTML:
<div>
<div id="tab1">Tab1</div>
<div id="tab2">Tab2</div>
<div id="tab3">Tab3</div>
</div>
<button onclick="tabmenu(this);" value="tab1">Tab1</button>
<button onclick="tabmenu(this);" value="tab2">Tab2</button>
find the tab to activate (assuming value = tab.id)
find the parent and hence it's siblings (assuming they are DIVs)
hide the siblings
show the target
You can see it working here: http://jsfiddle.net/4rWdQ/

Categories