When I first load the page it takes two clicks to show the content but then after that, every click will either show or hide. So it works... just not right away.
function navClick() {
var content = document.querySelector('.dropdown-content');
if (content.style.display == 'none') {
content.style.display = 'block';
} else {
content.style.display = 'none';
}
};
.dropbtn {
position: relative;
float: right;
font-size: 35px;
color: #fff;
margin-top: -50px;
padding-bottom: 15px;
;
margin-right: 30px;
cursor: pointer;
z-index: 2;
display: nne;
}
<a class="dropbtn" onclick="navClick()"><i class="ion-ios-menu"></i></a>
<div class="dropdown col">
<ul class="dropdown-content">
<li>Guitars</li>
<li>Drums</li>
<li>Amps</li>
<li>Gear</li>
<li>Featured</li>
<li class="find-us">Find Us</li>
</ul>
</div>
What is happening here and how can I make the function work the first time a user clicks?
The problem is that content.style.display isn't defined, so it isn't none when you click, so it is set as none, next time through it is none so it changes to block. I would recommend using classList.toggle instead though:
function navClick() {
var content = document.querySelector('.dropdown-content');
content.classList.toggle('hidden');
};
.hidden {
display: none;
}
<a class="dropbtn" onclick="navClick()">Toggle Menu</a>
<div class="dropdown col">
<ul class="dropdown-content">
<li>Guitars</li>
<li>Drums</li>
<li>Amps</li>
<li>Gear</li>
<li>Featured</li>
<li class="find-us">Find Us</li>
</ul>
</div>
I think it happens because ul tag doesn't have style attribute, so you can add it as follow:
<ul class="dropdown-content" style="display: block;">
You can also change in css:
display: nne;
to
display: none;
Related
I'm trying to make a search bar. No matter what I type in search box it shows the "Dropdown" as result and it doesn't show the items inside that list when I search. What am I doing wrong?
https://jsfiddle.net/5xh86fkn/
var dropdown = document.getElementsByClassName("dropdown-btn");
var i;
for (i = 0; i < dropdown.length; i++) {
dropdown[i].addEventListener("click", function() {
this.classList.toggle("active");
var dropdownContent = this.nextElementSibling;
if (dropdownContent.style.display === "block") {
dropdownContent.style.display = "none";
} else {
dropdownContent.style.display = "block";
}
});
}
function myFunction() {
var input, filter, ul, li, a, i;
input = document.getElementById("mySearch");
filter = input.value.toUpperCase();
ul = document.getElementById("myMenu");
li = ul.getElementsByTagName("li");
for (i = 0; i < li.length; i++) {
a = li[i].getElementsByTagName("a")[0];
if (a.innerHTML.toUpperCase().indexOf(filter) > -1) {
li[i].style.display = "";
} else {
li[i].style.display = "none";
}
}
}
<div class="sidenav">
<input type="text" id="mySearch" onkeyup="myFunction()" placeholder="Search.." title="Type in a category">
<ul id="myMenu">
<li>About</li>
<li>Services</li>
<li>Clients</li>
<li>Contact</li>
<button class="dropdown-btn">Dropdown
<i class="fa fa-caret-down"></i>
</button>
<div class="dropdown-container">
<li>Link 1</li>
<li>Link 2</li>
<li>Link 3</li>
</div>
<li>Search</li>
</ul>
</div>
This is a working demo of your attempt of filtering the menu items in real time by typing suggestions on the input text.
The main problem was using the correct strategy to fetch the menu items from dom. The element you wanted to partecipate in the filtering, wasn't a <LI> element.
Plus the list you embedded inside the Dropdown button wasn't included in a ol container and was breaking the correct behaviour.
I slightly refactored your html and focused on the single js function in charge of filtering the list according to the input typed:
function f(filter){
menuItems = document.querySelectorAll('#myMenu > li');
for(const menuItem of menuItems){
const textContent = menuItem.textContent.trim().toUpperCase();
//console.log(`"${textContent}" "${filter}" "${textContent.indexOf(filter)}"`);
if (textContent.indexOf(filter.toUpperCase()) > -1) {
menuItem.classList.remove('hidden');
}else{
menuItem.classList.add('hidden');
}
}
}
.hidden{
display: none;
}
body {
font-family: "Lato", sans-serif;
}
/* Fixed sidenav, full height */
.sidenav {
height: 100%;
width: 200px;
position: fixed;
z-index: 1;
top: 0;
left: 0;
background-color: #111;
overflow-x: hidden;
padding-top: 20px;
}
/* Style the sidenav links and the dropdown button */
.sidenav a, .dropdown-btn {
padding: 6px 8px 6px 16px;
text-decoration: none;
font-size: 20px;
color: #818181;
display: block;
border: none;
background: none;
width: 100%;
text-align: left;
cursor: pointer;
outline: none;
}
/* On mouse-over */
.sidenav a:hover, .dropdown-btn:hover {
color: #f1f1f1;
}
/* Main content */
.main {
margin-left: 200px; /* Same as the width of the sidenav */
font-size: 20px; /* Increased text to enable scrolling */
padding: 0px 10px;
}
/* Add an active class to the active dropdown button */
.active {
background-color: green;
color: white;
}
/* Dropdown container (hidden by default). Optional: add a lighter background color and some left padding to change the design of the dropdown content */
.dropdown-container {
display: none;
background-color: #262626;
padding-left: 8px;
}
/* Optional: Style the caret down icon */
.fa-caret-down {
float: right;
padding-right: 8px;
}
/* Some media queries for responsiveness */
#media screen and (max-height: 450px) {
.sidenav {padding-top: 15px;}
.sidenav a {font-size: 18px;}
}
<div class="sidenav">
<input type="text" id="mySearch" onkeyup="f(this.value)" placeholder="Search.." title="Type in a category">
<ul id="myMenu">
<li>About</li>
<li>Services</li>
<li>Clients</li>
<li>Contact</li>
<li>
<button class="dropdown-btn">
Dropdown
<i class="fa fa-caret-down"></i>
</button>
<div class="dropdown-container">
<ol>
<li>Link 1</li>
<li>Link 2</li>
<li>Link 3</li>
</ol>
</div>
</li>
<li>
Search
</li>
</ul>
</div>
For simplicity I removed code not related to the Search question.
I would suggest a slightly different approach here.
Use the textContent of the nodes so that you would not match the HTML other than that.
Leverage the data attribute and some CSS to make the code smaller by setting them to a true/false string and show/hide based upon that.
Use a descender selector to find only a that is directly inside an li by using li>a - I would strongly suggest classes instead of element selectors however for the "searchable" elements.
Note I hide the parent li by a toggle of the dataset value
I removed the JavaScript from the HTML as a best practice
Note this code can be further reduced but I left it verbose for clarity.
document.getElementById("mySearch").addEventListener('keyup', (event) => {
const findMe = event.target.value.toUpperCase();
const searchable = document.querySelectorAll('li>a');
searchable.forEach(function(searchItem) {
searchItem.parentElement.dataset.isfound = searchItem.textContent.toUpperCase().includes(findMe) ? "true" : "false";
});
});
li[data-isfound="true"] {
background-color: yellow;
}
li[data-isfound="false"] {
display: none;
}
<div class="sidenav">
<input type="text" id="mySearch" placeholder="Search.." title="Type in a category">
<ul id="myMenu">
<li>About</li>
<li>Services</li>
<li>Clients</li>
<li>Contact</li>
<li><button class="dropdown-btn">Dropdown
<i class="fa fa-caret-down"></i>
</button></li>
<ul class="dropdown-container">
<li>Link 1</li>
<li>Link 2</li>
<li>Link 3</li>
</ul>
<li>Search</li>
</ul>
</div>
What I am trying to do is, when I click on green element I want the purple one with the same id be removed. Now my problem is I can not loop through purple element's id and find the one which match with green one and then remove it from the DOM. I tried to use querySelectorAll but it doesn't work with addEventListener and when I use querySelector it just returns always the first element.So the goal is to remove both elements green and purple that has the same id.
if you see in HTML code inside the ul tag there is another one with the id container actually this is the problem the first ul tag with id main is the original one and the one inside it with id container it will be generated automatically with jQuery plugin if I set any new attribute to class main the class container will copy it. my goal is to click on green one and delete two elements from DOM. The one which I am clicking and another with same id. is there any way for that?
Has anyone solution for that how to remove simultaneously another element with the same id of clicked element?
document.addEventListener("DOMContentLoaded", () => {
document.querySelector("ul").addEventListener("click", getItem)
})
function getItem(e) {
let li = e.target.closest(".visible")
let span = e.target
let getID = span.attributes.id.value
console.log("This is visible element", getID)
if (li) {
li.remove()
}
}
#main {
background-color: skyblue;
}
.hidden {
border: solid 2px black;
list-style: none;
margin: 2px;
background-color: #7d34eb;
}
#container {
background-color: #3483eb;
margin-top: 15px
}
.visible {
border: solid 2px black;
list-style: none;
margin: 2px;
background-color: #12a370;
}
span {
position: relative;
left: 1rem;
padding: 50%;
color: red;
cursor: pointer;
}
<div class="content">
<ul id="main">
<li class="hidden">
<span id="1">A</span>
</li>
<li class="hidden">
<span id="2">B</span>
</li>
<li class="hidden">
<span id="3">C</span>
</li>
<ul id="container">
<li class="visible">
<span id="1">A</span>
</li>
<li class="visible">
<span id="2">B</span>
</li>
<li class="visible">
<span id="3">C</span>
</li>
</ul>
</ul>
</div>
I changed all your spans to div to fill up the LI element. I also changed all id to data-id, because id should be a unique.
EDIT: Based on the comment. In your original post, you added a click listener on the first UL that querySelector returns, which is #main. I made that more clear in the code. As the comment, in my answer, suggest, it's better to add a click listener to ul#container instead.
EDIT 2: Based on another comment. :P I added code for looping through and removing all elements with matching data-id.
document.addEventListener("DOMContentLoaded", () => {
document.querySelector("ul#main").addEventListener("click", getItem);
})
function getItem(e) {
let divEl = e.target;
let dataset = divEl.dataset;
let visibleLi = divEl.parentElement;
let isVisibleElement = visibleLi.classList.contains('visible');
let matchingDatasetDivs = document.querySelectorAll(`[data-id="${dataset.id}"]`);
if (isVisibleElement)
console.log("This is visible element", dataset.id);
if (isVisibleElement && matchingDatasetDivs.length) {
for (let i = 0; i < matchingDatasetDivs.length; i++) {
let containerLi = matchingDatasetDivs[i].parentElement;
containerLi.remove();
}
}
}
#main {
background-color: skyblue;
}
.hidden, .visible {
border: solid 2px black;
list-style: none;
margin: 2px;
background-color: #7d34eb;
}
.visible {
background-color: #12a370;
}
#container {
background-color: #3483eb;
margin-top: 15px
}
li > div {
position: relative;
left: 1rem;
/* padding: 50%; */
color: red;
cursor: pointer;
text-align: center; /* ADDED */
}
<div class="content">
<ul id="main">
<li class="hidden">
<div data-id="1">A</div>
</li>
<li class="hidden">
<div data-id="2">B</div>
</li>
<li class="hidden">
<div data-id="3">C</div>
</li>
<ul id="container">
<li class="visible">
<div data-id="1">A</div>
</li>
<li class="visible">
<div data-id="2">B</div>
</li>
<li class="visible">
<div data-id="3">C</div>
</li>
</ul>
</ul>
</div>
I got the code from w3scgool and modified it. The dropdown menu opens but when I click inside of it - submenu, then it closes. Here is the pure JavaScript code.
var dropdown = document.getElementsByClassName('dropdown-btn');
var i;
for (i = 0; i < dropdown.length; i++) {
dropdown[i].addEventListener('click', function() {
this.classList.toggle('active');
var dropdownContent = this.nextElementSibling;
if (dropdownContent.style.display === 'block') {
dropdownContent.style.display = 'none';
} else {
dropdownContent.style.display = 'block';
}
});
}
nav.side-nav {
order: 0;
display: flex;
flex: 1 1;
flex-direction: column;
align-self: stretch;
margin-bottom: 0.67rem;
}
nav.side-nav ul {
margin: 0;
}
nav.side-nav li {
border-bottom: 1px solid #d9dadc;
border-left: 1px solid #d9dadc;
border-right: 1px solid #d9dadc;
list-style: none;
padding: 5px 15px;
font-size: 17px;
line-height: 24px;
}
nav.side-nav li:first-child {
background: #092a31;
color: white;
border: none;
font-size: 20px;
padding: 15px;
line-height: 1.1;
}
nav.side-nav li:not(:first-child):hover {
background: #cda600;
color: white;
cursor: pointer;
}
/*dropdown menu*/
.dropdown-container {
display: none;
background-color: #ffffff;
padding-left: 8px;
}
<html>
<nav class="side-nav">
<ul>
<li style="text-align:left;">some1</li>
<li href="#">some1</li>
<li href="#">some1</li>
<li href="#">some1</li>
<li id="navDrop" class="dropdown-btn">
Menu</li>
<div class="dropdown-container">
<form>
<a class="dropdown-container-link" id="navItem1" href="#">Submenu1</a><br>
<a class="dropdown-container-link" id="navItem2" href="#">Submenu2</a><br>
<a class="dropdown-container-link" id="navItem3" href="#">Submenu3</a><br>
<a class="dropdown-container-link" id="navItem4" href="#">Submenu4</a>
</form>
</div>
<li href="#">Menu</li>
</ul>
</nav>
</html>
I am new to JS. Could someone navigate/show how to edit the code to prevent dropdown from closing when click on its submenu.
Update: took out the onclick feature. Took from my code too.
Any suggestions about the code because it stays the same. In this case I am using just JS without jquery library.
After making the modifications suggested by #Heretic Monkey and #Ganesh chaitanya, you can simplify your code by using map() instead of a for loop, and again classList.toggle() instead of else if.
just modify your css a little with a new class that you add to your div. Like that
var dropdown = document.getElementsByClassName("dropdown-btn");
// here dropdown.map() don't work, use
Array.prototype.map.call(dropdown, function(drop) {
drop.addEventListener("click", function() {
drop.classList.toggle("active");
var dropdownContent = drop.nextElementSibling;
//use classList.toggle with the new class added at the div
dropdownContent.classList.toggle("disp-container");
});
});
nav.side-nav li:not(:first-child):hover {
background: #cda600;
color: white;
cursor: pointer;
}
/*dropdown menu*/
/*remove display here*/
.dropdown-container {
background-color: #ffffff;
padding-left: 8px;
}
/*create a new class and add display here*/
.disp-container {
display: none;
}
<nav class="side-nav">
<ul>
<li style="text-align:left;">some1</li>
<li href="#">some1</li>
<li href="#">some1</li>
<li href="#">some1</li>
<li id="navDrop" class="dropdown-btn">
Menu
</li>
<!-- add your new class here -->
<div class="disp-container dropdown-container">
<form>
<a class="dropdown-container-link" id="navItem1" href="#">Submenu1</a><br />
<a class="dropdown-container-link" id="navItem2" href="#">Submenu2</a><br />
<a class="dropdown-container-link" id="navItem3" href="#">Submenu3</a><br />
<a class="dropdown-container-link" id="navItem4" href="#">Submenu4</a>
</form>
</div>
<li id="navDrop2" class="dropdown-btn">
Menu
</li>
<!-- add your new class here -->
<div class="disp-container dropdown-container">
<form>
<a class="dropdown-container-link" id="navItem1" href="#">Submenu1</a><br />
<a class="dropdown-container-link" id="navItem2" href="#">Submenu2</a><br />
<a class="dropdown-container-link" id="navItem3" href="#">Submenu3</a><br />
<a class="dropdown-container-link" id="navItem4" href="#">Submenu4</a>
</form>
</div>
</ul>
</nav>
So essentially I can't figure out why this menu won't dropdown when I click on the hamburger icon, any help will be greatly appreciated
Javascript:
function myFunction(){
var hamburger=document.getElementById('nav-btn')
var dropdownContent=document.getElementsByClassName('nav')
hamburger.onclick=dropdownContent.classList.toggle("show");
//or hamburger.onclick=dropdownContent.style.display("block");
}
CSS:
#nav-btn {
display: none;
}
#media (max-width: 1099px) {
li {
display: none;
}
#nav-btn {
display: inline;
position: absolute;
right: 10px;
bottom: 110px;
}
#nav-btn:hover {
content: url('Menu.png');
}
HTML:
<html>
<body>
<span id="nav-btn"><image src="Menugreen.png" input type="button" onclick="myFunction()"/></span>
<div class="nav">
<ul>
<li id="Programs"> Programs </li>
<li> T-Shirts </li>
<li> About </li>
</ul>
</div>
</body>
</html>
Again I am just asking for advice on why the dropdown span id of nav-btn doesn't dropdown the content of ul everything else works fine. Thank you!
You are trying to toggle the show class, but don't have a show class defined. toggleClass() is for adding or removing a CSS class by its name.
// Get DOM references
var hamburger = document.getElementById('nav-btn')
var dropdownContent = document.querySelector('.nav')
// Set up event handler
hamburger.addEventListener("click", function(){
dropdownContent.classList.toggle("hide");
});
#nav-btn {
display: none;
}
#media (max-width: 1099px) {
.hide {
display: none;
}
#nav-btn {
display: inline;
position: absolute;
right: 10px;
bottom: 110px;
}
/* Change the image when you hover over the image, not the span*/
#nav-btn > img:hover {
content: url('Menu.png');
}
}
<span id="nav-btn">
<image src="Menugreen.png" alt="menu">
<input type="button" value=" - - -">
</span>
<div class="nav">
<ul>
<li id="Programs">Programs</li>
<li> T-Shirts </li>
<li> About </li>
</ul>
</div>
I'm trying to create a menu that targets an iframe, but will also show text in a separate div once clicked.
For example:
• Click on Menu item 1.
• "https://wikipedia.org" is loaded in an iframe.
• The address of the wikipedia page shows in a separate div.
Using some of the code I've found here, I've been able to make the menu to show the text how I want it, but I can't target an iframe at the same time.
Maybe it'd be better to use query?
Any help would be amazing!
(The Javascript function turns the clicked link to red).
var Lst;
function changecolor(obj) {
if (Lst) Lst.style.color = "#663399";
obj.style.color = "red";
Lst = obj;
}
a:link {
text-decoration: none;
}
a:visited {
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
a:active {
text-decoration: underline;
}
.menu {
font-size: 13px;
width: 260px;
height: 350px;
left: 8px;
}
#tabs p {
display: none;
font-size: 13px;
}
#tabs p.tab1:target {
display: block;
}
#tabs p.tab2:target {
display: block;
}
#tabs p.tab3:target {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<div id="tabs" class="menu">
<a href="#tab1" class="nav-tab tab1" onclick="changecolor(this)">
Menu item 1<br><br></a>
<a href="#tab2" class="nav-tab nav-tab-active tab2" onclick="changecolor(this)">
Menu item 2<br><br></a>
<a href="#tab3" class="nav-tab nav-tab-active tab3" onclick="changecolor(this)">
Menu item 3<br><br></a>
<p id='tab1' class='tab1'>
"https://www.wikipedia.org"
</p>
<p id='tab2' class='tab2'>
"http://dictionary.reference.com"
</p>
<p id='tab3' class='tab3'>
"http://www.thesaurus.com"
</p>
</div>
</body>
This is how I would do it using JQuery:
$("a").click(function(){
$("iframe").attr("src", $($(this).attr("href")).find("a").attr("href"));
});
Here is the JSFiddle demo
(Note that the two other links u added besides wikipedia are not loaded on their own, they they are not loading in the iframe either. U may wanna try using other links :) )