How could a vertical list of dropdown text be created? - javascript

I'm trying to understand how this sort of dropdown list could be produced, possibly without Js.
To be more clear, I'm trying to make something like this:
<Clickable Text Subject Name>
<Hidden Description>
<Clickable Text Subject Name>
<Hidden Description>
<Clickable Text Subject Name>
<Hidden Description>
Whereby the "Hidden Description" shifts the elements below it, when the subject is clicked.
Also, when trying to add more than one dropdown text element, with my attempt, they are placed horizontally
My attempt:
.dropbtn {
cursor: pointer;
display: inline-block;
}
.dropdown {
position: relative;
display: inline-block;
}
.dropdown-content {
display: none;
position: relative;
z-index: 1;
}
.dropdown:hover .dropdown-content {
display: block;
}
<div class="dropdown">
<p class="dropbtn">Subject name1</p>
<div class="dropdown-content">
<p>The subject description in all it's glory</p>
</div>
</div>
If you have any ideas, please let me know, thanks!

<script>
let isOpen = false;
function something() {
isOpen = !isOpen;
let result = isOpen ? 'block':'none'
document.getElementById("dropdown").style.display = result;
}
</script>
<div class="dropdown">
<button class="dropDownButton" onclick="something()">DROPDOWN</button>
<div class="dropDownContent" id="dropdown">
Lorem ipsum dolor sit amet.
</div>
</div>

I ended up modifying the given example of collapsible elements, so I could get what I was looking for. Here's what I'm using, based on the link I tried to provide
<html>
<head>
<script>
function ToggleDesc(ref){
var content = ref.nextElementSibling;
if (content.style.display === "block") {
content.style.display = "none";
} else {
content.style.display = "block";
}
}
</script>
<style>
.subject {
border: none;
text-align: left;
font-size: 25px;
width: 100%;
cursor: pointer;
}
.desc {
padding: 0 18px;
display: none;
overflow: hidden;
background-color: #f1f1f1;
}
</style>
</head>
<body>
<button type="button" class="subject" onClick="ToggleDesc(this)">Subject 1</button>
<a class="desc">A very descriptive description</a>
<button type="button" class="subject" onClick="ToggleDesc(this)">Subject 2</button>
<a class="desc">A very descriptive description</a>
</body>
</html>

Related

Button click open and close function not working

Using Javascript to open and close a navbar but it's not working in my new project
When i use devtools i can see the function active but my nav bar does not open or close. So funny because i've used it for an old project which is working fine. I have no idea why this time it's frustrating. I need your help please if any
This is the js code
let Menupopupup = document.getElementById("dropdownheadernav");
function opendropdownheadernav() {
Menupopupup.classList.add("Openmenudrops");
document.body.style.overflow = "hidden";
}
function closedropdownheadernav() {
Menupopupup.classList.remove("Openmenudrops");
document.body.style.overflow = "auto";
}
This is my HTML
<nav class="firstnavigationbar">
<button id="Showscroll" type="submit" class="barsbutton" onclick="opendropdownheadernav()">
<div class="barbtnimagecontainer" >
<img class="barbtn"
src="./B-NFT-IMGS/Screenshot 2022-11-29 at 07.00.30.png"
height="23"
width="22"
alt=""
/></div></button>
<ul class="firstunorderedlist" id="dropdownheadernav">
<button id="Closescroll" type="button" class="closemenubutton" onclick="closedropdownheadernav()"><span class="closemenuspan">&#x2715</span></button>
This is my Css
.firstunorderedlist {
margin-top: -40px;
display: none;
color: #1e2329;
list-style: none;
line-height: 3.5;
background-color: #fff;
width: 320px;
overflow: hidden;
}
The element UL must be closed with /ul. As for javascript, you need to find the element by id and then use style.display and make it equal to the desired value. I attached the neatified code below. It does what you need and is made shorter.
<!DOCTYPE html>
<html>
<head>
<style>
.firstunorderedlist {
margin-top: -40px;
display: none;
color: #1e2329;
list-style: none;
line-height: 3.5;
background-color: #fff;
width: 320px;
overflow: hidden;
}
</style>
</head>
<body>
<nav class="firstnavigationbar">
<button id="Showscroll" type="submit" class="barsbutton" onclick="openNav()">
<div class="barbtnimagecontainer" >
<img class="barbtn"
src="./B-NFT-IMGS/Screenshot 2022-11-29 at 07.00.30.png"
height="23"
width="22"
alt="">
</div>
</button>
<ul class="firstunorderedlist" id="dropdownheadernav">
<li>Code</li>
<li>Goes</li>
<li>Here</li>
</ul>
<button id="Closescroll" type="button" class="closemenubutton" onclick="openNav()">
<span class="closemenuspan">&#x2715</span>
</button>
<script>
let navOpened = false;
function openNav() {
if (navOpened) {
navOpened = false;
document.getElementById("dropdownheadernav").style.display = 'none';
} else {
navOpened = true;
document.getElementById("dropdownheadernav").style.display = 'initial';
}
}
</script>
</body>
</html>
function myFunction() {
var x = document.getElementById("myLinks");
if (x.style.display === "block") {
x.style.display = "none";
} else {
x.style.display = "block";
}
}
.mobile-container {
max-width: 480px;
margin: auto;
background-color: blue;
height: 500px;
color: white;
border-radius: 10px;
}
.topnav {
overflow: hidden;
background-color: red;
position: relative;
}
.topnav #myLinks {
display: none;
}
.topnav a {
color: white;
padding: 14px 16px;
text-decoration: none;
font-size: 17px;
display: block;
}
.topnav a.icon {
background: black;
display: block;
position: absolute;
right: 0;
top: 0;
}
.topnav a:hover {
background-color: #ddd;
color: black;
}
.active {
background-color: #04AA6D;
color: white;
}
<html>
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
</head>
<body>
<body>
<div class="mobile-container">
<div class="topnav">
Navbar
<div id="myLinks">
News
Contact
About
</div>
<a href="javascript:void(0);" class="icon" onclick="myFunction()">
<i class="fa fa-bars"></i>
</a>
</div>
<div style="padding-left:16px">
<h3>Vertical Mobile Navbar</h3>
<p>This example demonstrates how a navigation menu on a mobile/smart phone could look like.</p>
<p>Click on the hamburger menu (three bars) in the top right corner, to toggle the menu.</p>
</div>
</div>
</body>
<html>

Prototype Pollution script alert doesn't work

This below is my code.
<html>
<head>
<script src="https://code.jquery.com/jquery-3.5.1.js"></script>
<script src="https://raw.githack.com/alrusdi/jquery-plugin-query-object/9e5871fbb531c5e246aac2aaf056b237bc7cc0a6/jquery.query-object.js"></script>
<style>
.dropbtn {
background-color: #3498DB;
color: white;
padding: 16px;
font-size: 16px;
border: none;
cursor: pointer;
}
.dropbtn:hover, .dropbtn:focus {
background-color: #2980B9;
}
.dropdown {
position: relative;
display: inline-block;
}
.dropdown-content {
display: none;
position: absolute;
background-color: #f1f1f1;
min-width: 10px;
overflow: auto;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
}
.dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
font-size: small;
}
.dropdown a:hover {background-color: #ddd;}
.show {display: block;}
</style>
</head>
<body>
<h1 id="root"></h1>
<script>
function myFunction() {
document.getElementById("myDropdown").classList.toggle("show");
}
var pages = {
home: `HOME </br>
<div class="dropdown">
<button onclick="myFunction()" class="dropbtn">home</button>
<div id="myDropdown" class="dropdown-content">
about
contact
</div>
</div>`,
about: `ABOUT </br>
<div class="dropdown">
<button onclick="myFunction()" class="dropbtn">about</button>
<div id="myDropdown" class="dropdown-content">
home
contact
</div>
</div>`,
contact: `CONATCT </br>
<div class="dropdown">
<button onclick="myFunction()" class="dropbtn">contact</button>
<div id="myDropdown" class="dropdown-content">
home
about
</div>
</div>`
};
var pl = $.query.get('page');
// var pl = new URLSearchParams(window.location.search).get("page");
if (pl == null) {
document.location.search = "?page=home"
}
if(pages[pl] != undefined){
// $('#root').html(pages[pl])
document.getElementById("root").innerHTML = pages[pl];
}else{
document.location.search = "?page=home"
}
</script>
</body>
</html>
And when I try to do a prototype pollution attack on the above code,
example like this,
https://exaple.com?page=hol&__proto__[hol]=<img src=x onerror=alert(1)></img>
it works perfectly and gives an alert popup.
but when I use the script tag it doesn't give me an alert popup,
example like this,
https://exaple.com?page=hol&__proto__[hol]=<script>alert(1)</script>
Can anybody help that what's going on?
why the <img> tag work but not <script> tag?
The version with <script>alert(1)</script> is harmless because HTML5 specifies that a <script> tag inserted with innerHTML should not execute.
See mdn on innerHTML - Security considerations.

Keep getting "cannot read property style of null" error

I am working on my own website and not good with codes yet. When I am scrolling down I want to appear another content of the navbar and when I am on the top, original navbar is appearing. I want this to be done in pure JavaScript with no libraries or framewokrs. Please see codes below and I know that codes are not organised. I will do that later on.
var nav = document.querySelector("nav");
var hide = document.querySelector(".hide");
var appear = document.querySelector(".appear")
window.onscroll = function(){
if(document.body.scrollTop > 70){
hide.style.display = "block";
appear.style.display = "none"
} else {
hide.style.display = "none";
appear.style.display = "block"
}
}
nav{
list-style-type: none;
text-align: center;
background-color: #3FA9A5;
position: sticky;
top: 0;
}
.hide{
font-size: 70px;
font-family: 'Long Cang', cursive;
display: block;
}
.appear{
height: 70px;
display: none;
}
.appear img{
width: 210px;
}
ul{
margin: 0 auto;
padding: 0;
}
body{
margin: 0;
}
.container{
max-width: 1080px;
width: 95%;
margin: 10px auto;
display: grid;
grid-template-columns: 25% 50% 25%;
}
.text{
text-align: center;
}
.profile {
border: 1px solid black;
padding: 0 10px 20px 10px;
}
#main{
width: 100%;
}
.post{
margin-left: 4.165%;
}
#image{
width: 100%;
}
#post-divide{
margin-left: 10px;
margin-right: 10px;
}
.comments{
width: 100%;
margin-top: 68.5px;
padding-bottom: 293.5px;
border: 1px solid black;
}
h2{
text-align: center;
}
.center{
grid-column: 2;
}
<link rel="stylesheet" type="text/css" href="test.css">
<link href="https://fonts.googleapis.com/css?family=Indie+Flower|Long+Cang&display=swap" rel="stylesheet">
<title>test</title>
</head>
<body>
<nav>
<ul>
<li class="hide">Unknown</li>
<li class="appear"><img src="cat.png"></li>
</ul>
</nav>
<div class="container">
<div class="col-1">
<div class="profile text">
<img id="main" src="https://data.whicdn.com/images/86629641/superthumb.jpg?t=1384568664">
<hr>
<p>12 posts</p>
<p>instagram</p>
<button>Subscribe!</button>
</div>
</div>
<div class="col-1">
<div class="post">
<h2>TITLE</h2>
<div>
<img id="image" src="https://i.pinimg.com/originals/76/d4/8c/76d48cb2928845dfcfab697ac7cbcf1c.jpg">
</div>
<hr id="post-divide">
</div>
</div>
<div class="col-1">
<div class="comments text"></div>
</div>
<div class="col-1 center">
<div class="post">
<h2>TITLE</h2>
<div>
<img id="image" src="https://i.pinimg.com/originals/76/d4/8c/76d48cb2928845dfcfab697ac7cbcf1c.jpg">
</div>
<hr id="post-divide">
</div>
</div>
<div class="col-1">
<div class="comments text"></div>
</div>
</div>
I think I should add something to the JS code but don't know why
Would be thankful if you would advise me how could I write HTML/CSS code so I do not have to create 2 navbars if it is possible
The following instruction:
document.querySelector("hide");
Will query for elements like:
<hide></hide>
Since plain selectors without prefix (div, header, span) will query for the whole element tags, not for classes or attrbitues.
Maybe you meant to query for the class, using the .:
document.querySelector(".hide");
var hide = document.querySelector(".hide");
var appear = document.querySelector(".appear")
So you should use class selector
You are using "hide" and "appear" as selectors but they do not exist in your HTML.
Use ".hide" and ".appear" in your querySelector instead.
var hide = document.querySelector(".hide");
var appear = document.querySelector(".appear");
Since both navbars have a static data, I would suggest to keep both of them and follow with answers of guys, that suggested to update querySelector param. Or you can hide/show the data inside of navbar (in your case it's only ul element) and leave the whole navbar always visible. So you can put classes appear/hide on ul element instea of navbar and then in JS get them with document.querySelector('.navbar .hide') and document.querySelector('.navbar .appear').
Using framework/library will definitely simplify it.
However, if you still want to have only one navbar in pure js/html/css (or it's data just dynamic) I would probably do like this:
HTML:
<nav class="navbar">
<ul>
<li><img src="cat.png"></li>
</ul>
</nav>
somewhere in JS:
var navbarUl = document.querySelector('.navbar ul');
window.onscroll = function() {
if (document.body.scrollTop > 70) {
navbarUl.innerHtml = '';
navbarUl.appendChild(getTopNavbarHTML);
} else {
navbarUl.innerHtml = '';
navbarUl.appendChild(getNavbarHTML);
}
}
getNavbarHTML and getTopNavbarHTML - will return documentFragment with li elements, see for details https://www.w3schools.com/jsref/met_document_createdocumentfragment.asp
But changing DOM during a scroll event can drastically decrease performance of a web app

Accordion body by link

The content bodies of an accordion open by clicking on panels. This is usually what's best. What I am trying to do now is change this behavior so that the content bodies only get revealed by clicking on a link included in one of the panels (or anywhere else, really). Hope that makes sense.
First of all: Is this possible?
This is the code right now:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.accordion {
background-color: #fff;
color: #444;
cursor: pointer;
width: 103%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
transition: 0.4s;
margin: -5px;
}
.bg {
width: 100%;
}
.active,
.accordion:hover {
background-color: #fff;
}
.panel {
padding: 50px 0px;
display: none;
width: 100%;
background-color: white;
overflow: hidden;
border-style: groove;
}
.accordion.active+div {
display: block
}
.column {
float: left;
width: 20%;
padding: 10px;
}
/* Clear floats after the columns */
.row:after {
content: "";
display: table;
clear: both;
}
</style>
</head>
<body>
<button class="accordion"><div class="parent">Only the following link should open the content panel: link_1</button>
<div class="panel">
<p>Content 1</p>
</div>
<button class="accordion">Only the following link should open the content panel: link_2</button>
<div class="panel">
<p>Content 2</p>
</div>
<button class="accordion">Only the following link should open the content panel: link_3</button>
<div class="panel">
<p>Content 3</p>
</div>
<button class="accordion">Only the following link should open the content panel: link_4</button>
<div class="panel">
<p>Content 4</p>
</div>
<script>
function scrollElmVert(el,num) { // to scroll up use a negative number
var re=/html$/i;
while(!re.test(el.tagName) && (1 > el.scrollTop)) el=el.parentNode;
if(0 < el.scrollTop) el.scrollTop += num;
}
var acc = document.getElementsByClassName("accordion");
var i;
var open = null;
for (i = 0; i < acc.length; i++) {
acc[i].addEventListener("click", function() {
if (open == this) {
open.classList.toggle("active");
open = null;
} else {
if (open != null) {
open.classList.toggle("active");
}
this.classList.toggle("active");
open = this;
//Scroll to clicked element
open.scrollIntoView();
scrollElmVert(open,-68);
}
});
}
</script>
</body>
</html>
Few changes to the css, but overall its an html issue. You will need to have two different elements or at least different classes to distiguish between the one that opens your accordion and the one that doesn't
Hope this is what you were looking for. Happy to explain or help in a better solution if needed.
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.accordion {
background-color: #fff;
color: #444;
cursor: pointer;
border: none;
text-align: left;
outline: none;
font-size: 15px;
transition: 0.4s;
margin: -5px;
display: inline;
}
.not-accordion {
color: #444;
font-size: 15px;
display: inline-block;
}
.bg {
width: 100%;
}
.active,
.accordion:hover {
background-color: #fff;
}
.panel {
padding: 50px 0px;
display: none;
width: 100%;
background-color: white;
overflow: hidden;
border-style: groove;
}
.accordion.active+div {
display: block
}
.column {
float: left;
width: 20%;
padding: 10px;
}
/* Clear floats after the columns */
.row:after {
content: "";
display: table;
clear: both;
}
</style>
</head>
<body>
<div class="parent">
<p class='not-accordion'>Only the following link should open the content panel:</p> <button class="accordion">link_1</button>
<div class="panel">
<p>Content 1</p>
</div>
<p class='not-accordion'>Only the following link should open the content panel:</p> <button class="accordion">link_2</button>
<div class="panel">
<p>Content 2</p>
</div>
<p class='not-accordion'>Only the following link should open the content panel:</p> <button class="accordion">link_3</button>
<div class="panel">
<p>Content 3</p>
</div>
<p class='not-accordion'>Only the following link should open the content panel:</p> <button class="accordion">link_4</button>
<div class="panel">
<p>Content 4</p>
</div>
<script>
function scrollElmVert(el, num) { // to scroll up use a negative number
var re = /html$/i;
while (!re.test(el.tagName) && (1 > el.scrollTop)) el = el.parentNode;
if (0 < el.scrollTop) el.scrollTop += num;
}
var acc = document.getElementsByClassName("accordion");
var i;
var open = null;
for (i = 0; i < acc.length; i++) {
acc[i].addEventListener("click", function() {
if (open == this) {
open.classList.toggle("active");
open = null;
} else {
if (open != null) {
open.classList.toggle("active");
}
this.classList.toggle("active");
open = this;
//Scroll to clicked element
open.scrollIntoView();
scrollElmVert(open, -68);
}
});
}
</script>
</body>
</html>

Hide CSS dropdown menu with Javascript

I have a dropdown that works with CSS. I want it to disappear when an item in the dropdown is clicked, but still function correctly after words.
Here is what I have so far:
$("span").click(function(){
$(this).parent().hide();
$("#text").html("Try hovering over it again. Now it's broken, because the display attribute was set for the element.");
});
.dropDownContainer{
display: inline-block;
}
.dropDown{
display: none;
padding-left: 6px;
background-color: black;
color:white;
position: absolute;
}
.dropDownContainer:hover .dropDown {
display: block;
}
span{
cursor:pointer;
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="dropDownContainer">
hover over this
<div class="dropDown">
this is the dropdown<br><br>
click <span>this</span> to close drop down.
<br><br>
It doesn't work.
</div>
</div>
<div id="text">
</div>
You should add a timeout to remove the display none right after you hide. so the cursor wont be positioned in a way it will automatically reopen (on hover this) so its fine.
$("span").off().click(function(){
var dropdown = $(this).parent();
dropdown.hide();
setTimeout(function(){dropdown.removeAttr('style');}, 300);
$("#text").html("Try hovering over it again. Now it's broken, because the display attribute was set for the element.");
});
You didn't have any event handler to hover and open it first. If you close or open something with CSS, you should use CSS to open or close it as well, same goes for JS/jQ, otherwise they may conflict.
SNIPPET
$(".dropDownHeader").on('mouseenter', function() {
$(".dropDownContainer").show();
$("kbd").on("click", function() {
$('.dropDownContainer').hide();
});
});
.dropDownContainer {
display: none;
padding-left: 6px;
background-color: black;
color: white;
position: absolute;
}
.dropDownHeader:hover .dropDown {
display: block;
}
kbd {
cursor: pointer;
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<header class="dropDownHeader">
<h3>Hover over this</h3>
</header>
<div class="dropDownContainer">
<p>This is the dropdown</p>
<p>Click <kbd>this</kbd> to close drop down.</p>
<p>It doesn't work.</p>
</div>
<article id="text">
</article>
I have updated your code a bit see this fiddle: https://jsfiddle.net/dLcLoggx/1/
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="dropDownContainer">
<span class="trigger">hover over this</span>
<div class="dropDown">
this is the dropdown<br><br>
click <span>this</span> to close drop down.
<br><br>
It doesn't work.
</div>
</div>
<div id="text">
</div>
.dropDownContainer{
display: inline-block;
}
.dropDown{
display: none;
padding-left: 6px;
background-color: black;
color:white;
position: absolute;
}
span{
cursor:pointer;
color: red;
}
$(".dropDown span").click(function(){
$(this).parent().slideUp();
});
$("span.trigger").hover(function(){
$('.dropDown').slideDown();
});

Categories

Resources