I'm currently trying to create a double-dropdown menu using JavaScript & HTML lists. I know there is a lot about it in the internet, but these solutions don't fit me or use jQuery (and I'm doing this for JavaScript practice mostly). I've created something like that:
JS Code:
function clear_id() {
document.getElementById("first").style.display = "none";
document.getElementById("second").style.display = "none";
}
function dropdown_id(id) {
var element = document.getElementById(id);
if (element.style.display === "block") {
element.style.display = "none";
} else {
clear_id();
element.style.display = "block";
}
}
function clear_class(element) {
for (var i = 0; i < element.length; ++i) {
element[i].style.display = "none";
}
}
function dropdown_class(id, num) {
var element = document.getElementsByClassName(id);
if (element[num].style.display === "block") {
element[num].style.display = "none";
} else {
clear_class(element);
element[num].style.display = "block";
}
}
CSS Code:
ol,
ul {
display: none;
}
#main {
display: block;
}
li {
list-style-type: none;
}
HTML Code:
<ol id="main">
<li>
First
<ul id="first">
<li>
fir
<ol class="one">
<li>f</li>
<li>s</li>
</ol>
</li>
<li>
sec
<ol class="one">
<li>f</li>
<li>s</li>
</ol>
</li>
</ul>
</li>
<li>
Second
<ul id="second">
<li>fir
<ol class="two">
<li>f</li>
<li>s</li>
</ol>
</li>
<li>
sec
<ol class="two">
<li>f</li>
<li>s</li>
</ol>
</li>
</ul>
</li>
</ol>
So at this point, I simply have to expand and roll (depending on display state) after click. Here is my solution for that problem.
It works fine, but I feel that it can be done simpler, just don't know JavaScript good enough and I'm blocked by my C++ approach (recently moved from C++ to web because of curiosity). So here is my question: can it be done easier and simpler(maybe more correct)? If anyone can show me the right path, I would be very grateful.
Here is another implementation, I pass in the DOM element using the this keyword which I then use in my javascript function. It is also a bit shorter than your solution but not necessarily better.
function toggle (el) {
if (el.childNodes[1].className === 'disappear') {
el.childNodes[1].classList.remove('disappear');
} else {
el.childNodes[1].classList.add('disappear');
}
}
.disappear {
display: none;
}
li:hover{
color:red
}
<ul>
<li onclick="toggle(this);">first
<ul class="disappear">
<li>1</li>
<li>2</li>
</ul>
</li>
<li onclick="toggle(this);">second
<ul class="disappear">
<li>1</li>
<li>2</li>
</ul>
</li>
</ul>
Hopefully this is helpful for you!
Related
This question already has answers here:
Why can't I call a function named clear from an onclick attribute?
(3 answers)
Closed 1 year ago.
The 'X' is unable to display "none" to the UL element. Is there a problem with the getElement? or should I use query selector.
function clear() {
var hide = document.getElementById("myUL1");
hide.style.display = "none";
}
span {
cursor: pointer;
}
<div>
<ul id="myUL1">
<li>list</li>
<li>HTML</li>
<li>CSS</li>
<li>JavaScript</li>
</ul>
<div>Clear list <span onclick="clear()">X</span></div>
</div>
Rename the function. - there is already a clear function that interferes with yours
function clearIt() {
var hide = document.getElementById("myUL1");
hide.style.display = "none";
}
span {
cursor: pointer;
}
<div>
<ul id="myUL1">
<li>list</li>
<li>HTML</li>
<li>CSS</li>
<li>JavaScript</li>
</ul>
<div>Clear list <span onclick="clearIt()">X</span></div>
</div>
Better alternative is to not have inline event handlers
document.getElementById("container").addEventListener("click",function(e) {
const tgt = e.target;
if (tgt.classList.contains("clear")) {
tgt.closest("div").querySelector("ul").classList.add("hide")
}
})
span {
cursor: pointer;
}
.hide { display:none; }
<div id="container">
<ul id="myUL1">
<li>list</li>
<li>HTML</li>
<li>CSS</li>
<li>JavaScript</li>
</ul>
Clear list <span class="clear">X</span>
</div></div>
Try this - it is better to use JavaScript eventlisteners when possible:
const targetSpan = document.getElementById("mySpan");
const hide = document.getElementById("myUL1");
targetSpan.addEventListener("click", function() {
hide.style.display = "none";
}, false);
span {
cursor: pointer;
}
<div>
<ul id="myUL1">
<li>list</li>
<li>HTML</li>
<li>CSS</li>
<li>JavaScript</li>
</ul>
<div>Clear list <span id="mySpan">X</span></div>
</div>
My first go at making my own mini webpage from scratch, specifically looking to understand how onmouseover/onmouseout works using .display.opacity. I would like to hover my mouse over each element and it displays text specified text while the rest of the webpage disappears. Hope I gave enough information first time using StackOverflow.
my first element works perfectly with the function created showHilton().
however my second element and function "showInnovel();" does not
I currently have 3 elements and would like this to work with all if possible
<ul>
<li onmouseover="showHilton();" onmouseout="showHilton();"class="hiltonGrand" id="HGV">Hilton Grand Vacations</li>
<li id="hilton" style="opacity:0; background: black; color: white; text-align:right;">hello</li>
<li onmouseover="showInnovel();" onmouseout="showInnovel();"class="in" id="inSol">Innovel Solutions</li>
<li id="iS" style="opacity:0; background: black; color: white; text-align:right;">innovel</li>
<li class="DR" id="Dr">Diamond Resorts</li>
<li id="diamond" style="opacity:0; background: black; color: white; text-align:right;">Diamond</li>
</ul>
</div>
<div>
<!--Back button-->
<!--Home Button-->
<!--Customer Service-->
</div>
<script type="text/javascript">
var hilton = document.getElementById("hilton");
var innovel = document.getElementById("inSol");
var Dr = document.getElementById("Dr");
var hGV = document.getElementById("HGV");
var iS = document.getElementById("iS");
function showHilton() {
if(hilton.style.opacity == 0){
//element.style.display = "block";
hilton.style.opacity= 1;
innovel.style.opacity = 0;
Dr.style.opacity=0;
} else {
//element.style.display = "none";
hilton.style.opacity=0;
innovel.style.opacity=1;
Dr.style.opacity=1;
}
}
function showInnovel() {
if(iS.style.visibility == 0){
//element.style.display = "block";
iS.style.opacity = 1;
hGV.style.opacity = 0;
Dr.style.opacity=0;
} else {
//element.style.display = "none";
iS.style.opacity=0;
hGV.style.opacity=1;
Dr.style.opacity=1;
}
}
Your current setup uses a HTML structure like so:
<ul>
<li>Toggle 1</li>
<li>Content 1</li>
<li>Toggle 2</li>
<li>Content 2</li>
</ul>
This makes it quite hard to toggle the next element, whichc would require some js as you've already stated in your question.
I would re-work the html, to something like:
<ul>
<li>
Toggle 1
<p>Content 1</p>
</li>
<li>
Toggle 2
<p>Content 2</p>
</li>
</ul>
This way we can use native css to toggle the display property on the child elements to get the desired output:
/* Hide */
li > p {
display: none;
background: black;
color: white
}
/* Show on hover */
li:hover > p {
display: block;
}
<div>
<ul>
<li class="hiltonGrand" id="HGV">
Hilton Grand Vacations
<p>hello</p>
</li>
<li class="in" id="inSol">
Hilton Grand Vacations
<p>innovel</p>
</li>
<li class="DR" id="DR">
Hilton Grand Vacations
<p>Diamond</p>
</li>
</ul>
</div>
<div>
<!--Back button-->
<!--Home Button-->
<!--Customer Service-->
</div>
I have some nested lists. Some go as deep as 4-5 level deep. For example:
<ul>
<li>
<span class="is-parent">parent</span>
<ul class="children">
<li class="no-child">child</li>
<li class="no-child">child</li>
<li class="no-child">child</li>
</ul>
</li>
<li>some child</li>
<li>another child</li>
<ul>
This list is displayed in a css grid column, the first one to be specific. I have set the columns using
grid-template-columns: repeat(5, 1fr);
When I click on parent, I want the nested <ul> to display on the next column.
What is the best way to do that using vanila JavaScript?
Something like the example here: https://mynameistechno.github.io/finderjs/#examples
But without the use of a library or plugin.
HTML
<ul>
<li>
<span class="is-parent">parent</span>
<ul class="children hide">
<li class="no-child">child</li>
<li class="no-child">child</li>
<li class="no-child">child</li>
</ul>
</li>
<li>some child</li>
<li>another child</li>
<ul>
CSS
ul {
grid-template-columns: repeat(auto-fill, 1fr);
}
.hide {
display: none;
}
JS
document.querySelectorAll('is-parent').forEach(node =>
node.parentNode.addEventListener('click', (ev) => {
let cl = ev.currentTarget.querySelector('ul').classList
cl.contains('hide') ? cl.remove('hide') : cl.add('hide')
}
}
It's really hard to do this without the jQuery library.
But here I wrote an example using only javascript.
The idea is when you click on is-parent you clone the Children and append to container.
You could build on this example.
I hop this help you somehow
var x = document.getElementsByClassName("is-parent");
var container = document.getElementsByClassName("container")[0];
function bind(items){
new Array(items).forEach(function(item, index){
item = item[0]
item.addEventListener("click", function(){
var children= [].filter.call(item.parentElement.childNodes, function(node) {
return node.className == "children"
})[0];
var i= children.cloneNode(true);
container.appendChild(i);
i.style.display = "block";
i.className = index;
});
});
}
bind(x);
.children{
display:none;
}
ul{
pointer:default;
}
div{
display: grid;
grid-template-columns: auto auto auto;
background-color: #2196F3;
padding: 10px;
}
<div class="container">
<ul>
<li>
<span class="is-parent">parent</span>
<ul class="children">
<li class="no-child">child</li>
<li class="no-child">child</li>
<li class="no-child">child</li>
</ul>
</li>
<li>some child</li>
<li>another child</li>
</ul>
</div>
My code javascript not working.
I want the functions work if will be over 500px width screen.
<ul>
<li class="dawid">Dawid</li>
<li class="piotrek">Piotr</li>
<li class="to">Tomek</li>
</ul>
AND JAVASCRIPT CODE- NOT WORKING
document.getElementById("dawid").addEventListener("click",displaytwo);
document.getElementById("piotrek").addEventListener("click",displayone);
function displaytwo(){
document.getElementById("piotrek").style.display='none';
document.getElementById("tomek").style.display='none';
}
function displayone(){
document.getElementById("dawid").style.display='none';
document.getElementById("tomek").style.display='none';
}
RESIZE NOT WORKING
function screen_resize(){
var w = parseInt(window.innerWidth);
if(w > 500)
{
displaytwo();
displayone();
}}
$(window).resize(function(e) {
screen_resize();
});
$(document).ready(function(e) {
screen_resize();
});
In order to use .getElementById you need ids on your elements:
<ul>
<li class="da" id="dawid">Dawid</li>
<li class="pi" id="piotrek">Piotr</li>
<li class="to" id="piotrek">tomek</li>
</ul>
The ids are missing in your elements li, add the IDs:
<li class="dawid" id="dawid">Dawid</li>
<li class="piotrek" id="piotrek">Piotr</li>
<li class="to" id="tomek">Tomek</li>
document.getElementById("dawid").addEventListener("click", displaytwo);
document.getElementById("piotrek").addEventListener("click", displayone);
function displaytwo() {
document.getElementById("piotrek").style.display = 'none';
document.getElementById("tomek").style.display = 'none';
}
function displayone() {
document.getElementById("dawid").style.display = 'none';
document.getElementById("tomek").style.display = 'none';
}
function screen_resize() {
var w = parseInt(window.innerWidth);
if (w > 500) {
displaytwo();
displayone();
}
}
$(window).resize(function(e) {
screen_resize();
});
$(document).ready(function(e) {
screen_resize();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li class="dawid" id="dawid">Dawid</li>
<li class="piotrek" id="piotrek">Piotr</li>
<li class="to" id="tomek">Tomek</li>
</ul>
You need to declare IDs on your HTML elements, or else getElementByID() will not work.
<ul>
<li id="dawid" class="da">Dawid</li>
<li id="piotr" class="pi">Piotr</li>
<li id="tomek" class="to">Tomek</li>
</ul>
It looks like you are also using jQuery and already assigned them classes, so you could also use this code to grab DOM elements by class:
$(".da").click(displaytwo);
$(".pi").click(displayone);
function displaytwo(){
$(".piotrek").css('display','none');
$(".tomek").css('display','none');
}
function displayone(){
$(".dawid").css('display','none');
$(".tomek").css('display','none');
}
I am learning JavaScript and CSS and got stuck somewhere-
I have three different lists top_menu, submenu3 and submenu4, when I click on item no 3 I want submenu 3 to show up and when I click on item no 4 I want submenu4 to show up and submenu3 should vanish.
My HTML Code is-
<ul id="top_menu">
<li onclick="arrow(1)">item no 1
</li>
<li onclick="arrow(2)">item no 2
</li>
<li onclick="arrow(3)">item no 3
</li>
<li onclick="arrow(4)">item no 4
</li>
</ul>
<ul id="submenu1" style="display:none;"></ul>
<ul id="submenu2" style="display:none;"></ul>
<ul id="submenu3" style="display:none;">
<li>A3
</li>
<li>B3
</li>
<li>C3
</li>
<li>D3
</li>
<li>E3
</li>
</ul>
<ul id="submenu4" style="display:none;">
<li>A4
</li>
<li>B4
</li>
<li>C4
</li>
<li>D4
</li>
<li>E4
</li>
</ul>
and JavaScript implementation for function arrow() is
function arrow(x) {
for (i = 1; i <5; i++) {
if (i==x) {
document.getElementById("submenu"+i).style.display = "block";
}
else {
document.getElementById("submenu"+i).style.display = "none";
}
}
}
Could someone tell where the mistake is?
Thanks!
The for statement should be
for (i = 1; i <5; i++)
Apart from that it seems to be working for me.
A non elegant solution would be to declare your function at the global scope :
window.arrow=function(x){
for (i = 1; i <5; i++) {
if (i==x) {
document.getElementById("submenu"+i).style.display = "block";
}
else {
document.getElementById("submenu"+i).style.display = "none";
}
}
}