Nav bar toggle javascript - javascript

I want to make toggle nav but unfortunately not working
function navtoggle(){
document.getElementsByClassName('sidebar').classList.toggle('active');
}
</script>
.sidebar.active {
width:0px;
}

document.getElementsByClassName('sidebar').classList is a HTMLCollection, you must loop through it or pick a specific index
function navtoggle(){
document.getElementsByClassName('sidebar')[0].classList.toggle('active');
}
.active {
color: red;
}
<div class="sidebar">Hello</div>
<button onClick="navtoggle();">Click Me</button>

document.getElementsByClassName() will return a HTMLCollection instead of the single sidebar element you're trying to target. Because classList isn't a property of HTMLCollection, you'll simply get a TypeError when trying to toggle a class on this collection.
If you are sure there is only one element with .sidebar on the page, or that the sidebar you're trying to target is the first in the DOM, you could use document.getElementsByClassName('sidebar')[0]. An alternative approach would be to use document.querySelector('.sidebar'), where you can also pass a more specific selector, such as document.querySelector('aside.sidebar'), to ensure you've selected the right element. For example:
function navtoggle() {
document.querySelector('aside.sidebar').classList.toggle('active');
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: sans-serif;
}
body {
width: 100vw;
height: 100vh;
}
.sidebar {
background: #CCC;
width: 15%;
height: 100%;
padding: 1rem;
overflow: hidden;
}
.sidebar.active {
width: 0;
padding: 0;
}
main {
position: absolute;
right: 0;
top: 0;
width: 85%;
height: 100%;
padding: 1rem;
}
button {
padding: .5rem;
margin-top: .5rem;
}
<aside class="sidebar">
This is the sidebar
</aside>
<main>
This is not the sidebar <br>
<button onclick="navtoggle()">Toggle the sidebar</button>
</main>

Related

How do I bring the block up to the header by scrolling when the button is clicked?

I'm trying to make it so that when you click on the button with the class .booking__button, the block scrolls up under the header. Position should not change, only scroll. This is done so that the search results of the booking module, which, would be visible to the user. I found the code that does the scrolling, but it works with the exact number, now 100px, but you understand that this distance will be different for everyone, depending on the height of the screen.
document.querySelector('.booking__button').addEventListener('click', () => {
window.scrollTo(0, 100);
});
body {
margin: 0;
}
.header {
position: fixed;
top: 0;
left: 0;
right: 0;
height: 60px;
background: #002164;
}
.hero {
min-height: calc(100vh - 100px);
background: #fff;
}
.booking__module {
display: flex;
justify-content: center;
align-items: center;
background: #BC0B3C;
}
.booking__search {
height: 600px;
background: #ccc;
}
.booking__button {
height: 20px;
margin: 40px;
}
.others {
height: 200vh;
}
<header class="header"></header>
<main class="hero"></main>
<section class="booking">
<div class="booking__module">
<button class="booking__button">booking</button>
</div>
<div class="booking__search"></div>
</section>
<section class="others"></section>
One approach is below, with explanatory comments in the code. Note that while I changed the background-color of the <header> element, that's simply to visualise the functionality and is not at all required:
// we pass a reference to the Event Object ('evt') to the function:
document.querySelector('.booking__button').addEventListener('click', (evt) => {
// we retrieve the closest ancestor <section> element of the element
// to which the event-handler is bound, and retrieve the 'top' property
// of its bounding-client rect:
let {top} = evt.currentTarget.closest('section').getBoundingClientRect();
// we then scroll to that value:
window.scrollTo(0, top);
});
body {
margin: 0;
}
.header {
position: fixed;
top: 0;
left: 0;
right: 0;
height: 60px;
/*background: #002164;*/
background-color: hsl(200deg 70% 70% / 0.4);
}
.hero {
min-height: calc(100vh - 100px);
background: #fff;
}
.booking__module {
display: flex;
justify-content: center;
align-items: center;
background: #BC0B3C;
}
.booking__search {
height: 600px;
background: #ccc;
}
.booking__button {
height: 20px;
margin: 40px;
}
.others {
height: 200vh;
}
<header class="header"></header>
<main class="hero"></main>
<section class="booking">
<div class="booking__module">
<button class="booking__button">booking</button>
</div>
<div class="booking__search"></div>
</section>
<section class="others"></section>
JS Fiddle demo.
References:
Element.closest().
Element.getBoundingClientRect().
Event.
Event.currentTarget.
EventTarget.addEventListener().
Window.scrollTo.

Html,css3, jquery how to create on click event

I want to make a button inside auto generated block to change overflow from hidden to auto.
I created recursive responsive auto-grid in Less, css like this:
.container {
.container-fixed();
[class*='col-'] {
float: right;
width: 100%;
}
.make-grid(#container-xs);
.make-grid(#container-sm);
.make-grid(#container-md);
.make-grid(#container-lg);
}
.container-fixed(#gap: #grid-gap-width) {
margin-right: auto;
margin-left: auto;
padding-left: (#gap / 2);
padding-right: (#gap / 2);
}
.generate-columns(#container-width;
#number-cols;
#i: 1) when (#i =< #number-cols) {
.col-#{i} {
#single-width: #container-width / #number-cols - 0.5;
width: #i * #single-width; // 800px
}
.generate-columns(#container-width;
#number-cols;
#i + 1);
}
.make-grid(#container-width) {
#media(min-width: #container-width) {
width: #container-width;
.generate-columns(#container-width, #grid-c);
}
}
[class*='col-'] {
text-align: center;
overflow: hidden;
height: 250px;
background: #color-h;
display: block;
margin: 1px;
color: #color-text;
position: relative;
}
And now I have long text in HTML inside one of blocks no matter which one, eg. col-9 where is part hidden because I used overflow:hidden;.
What I would like to do is to create a button and on click to change from overflow:hidden; to overflow: auto;.
My question is how to do that, to change from hidden to auto, on click and again to return back to previous state on new click.
I tried something like this but that is not good:
Less - >
[class*='col-'] {
text-align: center;
overflow: hidden;
height: 250px;
background: #color-h;
display: block;
margin: 1px;
color: #color-text;
position: relative;
.show {
overflow: auto;
}
}
JS - >
var content = document.getElementsByClassName("[class*='col-']");
var button = document.getElementbyID("show");
button.onclick = function() {
if (content.className == "show") {
content.className= "";
button.inerHTML = "Read";
} else {
content.className="show";
button.inerHTML = "Close";
}
};
html - >
<div class="col-9">
<a id="button-show">Read</a>
<script src="js/read.js"></script>
<p> some long text ........ </p>
</div>
I hope I am clear enough, what I want to do.
<-- language: lang-javascript -->
$("#button-show").click(function(){
$(".col-9").toggleClass("show")
})
<-- -->
so whenever you click the button, it will add or remove the class show on your elements with the col-9 classnames
You should use .toggle() to toggle the contents between show and hide. Here is an example
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
$(document).ready(function(){
$("#button-show").click(function(){
$("#show").toggle();
});
});
[class*='col-'] {
text-align: center;
overflow: hidden;
height: 250px;
background: #color-h;
display: block;
margin: 1px;
color: #color-text;
position: relative;
}
#show {
overflow: auto;
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="col-9">
<a id="button-show">Read</a>
<p id="show"> some long text ........ </p>
</div>
You have multiple problems in your code.
document.getElementsByClassName returns a list of elements (A.K.A. array), so your content.className is wrong as you accesing the array className property (which is non-existant) instead of the className property of each element inside the array. You have to iterate the array and access each element individually. Also, you are not accesing by class, but by selector (There's no class [class*='col-'], but class col-1, col-2, etc...). To select with selectors you have to use querySelector, which selects one element, or querySelectorAll which selects all elements.
Also, to hide an element you don't have to change overflow. overflow is for scrollbars. You have to change the display property to display: none and also as the class show is not a child element, it needs an & character:
[class*='col-'] {
text-align: center;
[...CSS THINGYS...]
position: relative;
&.show { // Note the & before the dot
display: none;
}
}
Your code don't has any jQuery actually. Is plain JS.
Also, the best way to attach events to HTML elements is via addEventListener, so:
var content = document.querySelectorAll("[class*='col-']");
var button = document.getElementbyID("show");
button.addEventListener("click", function() {
var anyShown = false;
content.forEach(function(element) {
if (element.className == "show") {
anyShown = true;
element.className= "";
} else {
element.className="show";
}
});
if (anyShown) {
button.inerHTML = "Read";
} else {
button.inerHTML = "Close";
}
});
If you want it in a more jQuery way you can do this, which do the same as above, but way shorter:
$("#show").on("click", function() {
if ($("[class*='col-']").hasClass("show")) {
$("#show").html("Read");
} else {
$("#show").html("Close");
}
$("[class*='col-']").toggleClass("show");
});
Relevant info:
addEventListener
getelementsbyclassname
querySelector
querySelectorAll
Less "&" operator
jQuery hasClass
jQuery toggleClass
I found solution:
JQ:
$(document).ready(function(){
$("button").click(function(){
$("p3").toggle();
});
});
CSS:
[class*='col-'] {
text-align: center;
overflow:auto;
height: 250px;
background: #color-h;
margin: 1px;
color: #color-text;
position: relative;
.border-radius(10px);
p3 {
margin: 10px ;
padding: 5px;
width: 95%;
text-align: justify;
display: none;
}
}
HTML:
<div class="col-9">
<button>Read</button>
<h1>TITLE</h1>
<p>some tekst.</p>
<p3>Tekst i want to hide ....</p3>
</div>

Display text in input of type number only on focus

Here is what I try to acomplish: I need an input field containing a value with a unit, that would look like this:
On focussing the input, I want it to move the unit to the right side, looking like this:
I can think of two ways to do so:
1. Replace input field with a Div that looks exactly like the input when focus is lost, and set the value of the input as its content:
$('#fakeInput').bind('click', changeToRealInput);
$('#realInput').bind('blur', changeToFakeInput);
$('#realInput').trigger('blur');
$('#unitAddon').html($('#realInput').attr('unit'));
function changeToFakeInput() {
// hide actual input and show a div with its contents instead
$('#fakeInput').show();
$('#realInputContainer').hide();
$('#fakeInput').html($('#realInput').val() + $('#realInput').attr('unit'));
}
function changeToRealInput() {
// hide fake-div and set the actual input active
$('#fakeInput').hide();
$('#realInputContainer').show();
$('#realInput').focus();
}
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
div#container {
display: flex;
background: #8aaac7;
padding: 10px;
width: 200px;
}
div#unitAddon,
input#realInput,
div#fakeInput {
font-family: sans-serif;
font-size: 26px;
padding: 5px;
width: 100%;
background-color: #FFFFFF;
border: none;
outline: none;
}
div#realInputContainer,
div#fakeInput {
border: 2px solid #dadada;
}
div#realInputContainer {
display: flex;
}
div#unitAddon {
width: auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div id="container">
<div id="fakeInput"></div>
<div id="realInputContainer">
<input type="number" unit="kg" id="realInput" value="3.3">
<div id="unitAddon"></div>
</div>
</div>
(also see this jsFiddle)
Problem here is (as you can see in the screenshot above) that, depending on your local settings, chrome automatically converts the decimal point into a comma (in the input, but not in the fake-div)
Another way I thought of is: When the focus is lost, set the size of the input field to match its content and, by doing so, pull the addon displaying the unit just behind the number.
Problem here is to get the size of the content of an input (cross-browser):
$('#realInput').bind('focus', changeToRealInput);
$('#realInput').bind('blur', changeToFakeInput);
$('#realInput').trigger('blur');
$('#unitAddon').html($('#realInput').attr('unit'));
function changeToFakeInput() {
// here is the question: what width should it be?
$('#realInput').css({'width' : '40%'});
}
function changeToRealInput() {
$('#unitAddon').css({'width' : 'auto'});
$('#realInput').css({'width' : '100%'});
}
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
div#container {
display: flex;
background: #8aaac7;
padding: 10px;
width: 300px;
}
div#unitAddon,
input#realInput{
font-family: sans-serif;
font-size: 26px;
padding: 5px;
width: 100%;
border: none;
outline: none;
}
div#realInputContainer {
border: 2px solid #dadada;
display: flex;
background-color: #FFFFFF;
}
div#realInputContainer.setAddonAway > div#unitAddon {
width: auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div id="container">
<div id="realInputContainer" class="setAddonClose">
<input type="number" unit="kg" id="realInput" value="3.3">
<div id="unitAddon"></div>
</div>
</div>
also see this jsFiddle
I could accomlish this with an input[type=text], but I dont want to loose the benefits of type[number] (min/max/step validation, on-screen keyboard, etc.)
Is there any way of getting around the flaws of my two ideas? Or is thre a more elegant way to do so?
The idea is to: (1) make the input box to cover the entire container; (2) create a helper element, and set it the same length as the input value via JS, and make it invisible as a place holder; (3) apply some style for moving around the unit box.
codepen
$(document).ready(function() {
$(".value").text($(".number").val());
$(".unit").text($(".number").attr("unit"));
$(".number").on("change keypress input", function() {
$(".value").text($(".number").val());
});
});
* {
box-sizing: border-box;
}
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
.container {
position: relative;
display: flex;
border: 4px solid teal;
width: 200px;
}
.container > * {
font-family: sans-serif;
font-size: 20px;
}
.number {
position: absolute;
left: 0;
top: 0;
width: 100%;
padding: 0;
border: 0;
outline: 0;
background: transparent;
}
.value {
visibility: hidden;
max-width: 100%;
overflow: hidden;
}
.unit {
position: relative;
flex: 1;
pointer-events: none;
background: white;
}
.number:focus ~ .value {
flex: 1;
}
.number:focus ~ .unit {
flex: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<input class="number" type="number" value="1.23" unit="kg">
<span class="value"></span>
<span class="unit"></span>
</div>

Having a DIV 'stick' for x amount of scrolls

I need a 'Page section' to stick in place for (x) amount of scrolling and then move onto the next section. I've tried putting them into the child theme but nothing... Can someone tell me a good way to do wthis that's not Javascript heavy?
CSS
.isSticky {
top: 0;
position: fixed;
}
HTML
<div>
<section id="top"></section>
<section id="test2"></section>
<section id="bottom"></section>
</div>
JS
$(document).ready(function () {
var el = $('#test2');
var elTop = el.position().top;
$(window).scroll(function () {
var windowTop = $(window).scrollTop();
if (windowTop >= elTop) {
el.addClass('isSticky');
} else {
el.removeClass('isSticky');
}
This answer might not be 100% pragmatic, due to current lack of support, but soon you will be able to use the position: sticky property of CSS, currently supported in Firefox and prefixed in Safari/iOS (Caniuse).
The feature was previously enabled in Chrome, but then subsequently removed in the interest of re-doing it more efficiently.
html, body {
margin: 0;
}
body * {
margin: 20px;
padding: 20px;
}
.header {
margin: 0;
padding: 20px;
background: #000;
}
.header span {
display: block;
color: #fff;
margin: 0 auto;
text-align: center;
padding: 0;
}
.placeholder {
border: 1px solid black;
margin: 0 auto;
text-align: center;
height: 300px;
}
.slider {
background: #006264;
color: white;
font-weight: bold;
margin: 0 auto;
position: sticky;
top: 0px;
}
<div class="header"><span>This is a header</span></div>
<div class="placeholder">This div holds place</div>
<div class="slider">This should slide up and then stick.</div>
<div class="placeholder">This div holds place</div>
<div class="placeholder">This div holds place</div>
<div class="placeholder">This div holds place</div>
<div class="placeholder">This div holds place</div>

JavaScript induced style changes are not permanent

Okay, I change the appearance of links using JavaScript. When I change the content of a hard-coded link, it sticks in that the changed color and underlining remains when the cursor is not hovering above it. However, when the content of a DIV has been changed using JavaScript, the style changes do not stick.
Here is the HTML code:
<!doctype html>
<html>
<head>
<title>Bla bla</title>
<meta charset="UTF-8">
<link href="style/kim.css" rel="stylesheet" type="text/css">
<script type="text/javascript" src="scripts/Kim.js"></script>
</head>
<body>
<div class="wrapper">
<div class="main">
<div class="nav">
<div class="topNav">
<ul>
<li onClick="changeNav('design')">Design</li>
<li onClick="changeNav('code')">Programming</li>
<li onClick="changeNav('science')">Science</li>
<li onClick="changeNav('Kim')">Kim</li>
</ul>
</div>
<div id="subNav">
<script>changeNav("design");</script>
</div>
</div>
<div class="content">
<p id="mainText">Test</p>
</div>
</div>
</div>
</body>
</html>
Here is the JS code:
var topNavNames = ["design", "code", "science", "Kim"];
var subNavCode = ["<ul><li onClick=\"loadPHP('design/websites.php', 'sub0')\">Websites</li><li onClick=\"loadPHP('design/graphics.php', 'sub1')\">Graphics</li><li onClick=\"loadPHP('design/flash.php', 'sub2')\">Flash</li></ul>",
"<ul><li onClick=\"loadPHP('code/interactive.php', 'sub0')\">Interactive applets</li><li onClick=\"loadPHP('code/statistics.php', 'sub1')\">Statistics</li><li onClick=\"loadPHP('code/wings.php', 'sub2')\">Wings</li><li onClick=\"loadPHP('code/3D.php', 'sub3')\">3D</li></ul>",
"<ul><li onClick=\"loadPHP('science/3D.php', 'sub0')\">3D</li><li onClick=\"loadPHP('science/ssd.php', 'sub1')\">Sexual Size Dimorphism</li><li onClick=\"loadPHP('science/shape.php', 'sub2')\">Wing shape</li><li onClick=\"loadPHP('science/phylogenetics.php', 'sub3')\"><i>Drosophila</i> phylogenetics</li><li onClick=\"loadPHP('science/communitygenetics.php', 'sub4')\">Community Genetics</li><li onClick=\"loadPHP('science/biodiversity.php', 'sub5')\">Biodiversity</li></ul>",
"<ul><li onClick=\"loadPHP('Kim.php', 'sub0')\">Who is Kim?</li><li onClick=\"loadPHP('animals/horses.php', 'sub1')\">Horses</li><li onClick=\"loadPHP('animals/birds.php', 'sub2')\">Birds</li><li onClick=\"loadPHP('private/outdoors.php', 'sub3')\">Outdoors</li><li onClick=\"loadPHP('contact.php', 'sub4')\">Contact</li></ul>"];
function changeNav(target) {
for (var i = 0; i<topNavNames.length; i++) {
if (target == topNavNames[i]) {
document.getElementById("subNav").innerHTML=subNavCode[i];
document.getElementById(topNavNames[i]).style.color="#F7EDAA";
document.getElementById(topNavNames[i]).style.borderBottom="thin solid #F7EDAA";
}
else {
document.getElementById(topNavNames[i]).style.color="#EEE";
document.getElementById(topNavNames[i]).style.borderBottom="thin solid #111";
}
}
}
function loadPHP(url, target) {
for (var i = 0; i<10; i++) {
if(document.getElementById(target)!=null) {
if (("sub"+i) == target) {
document.getElementById(target).style.color="#F7EDAA";
document.getElementById(target).style.borderBottom="thin solid #F7EDAA";
}
else {
document.getElementById(target).style.color="#EEE";
document.getElementById(target).style.borderBottom="thin solid #111";
}
}
}
}
if I subsequently remove the:
else {
document.getElementById(target).style.color="#EEE";
document.getElementById(target).style.borderBottom="thin solid #111";
}
from the loadPHP function, it changes the style, but does not reset it when the next link is clicked.
I observed this behavior in FireFox, Internet Exploder and Chrome.
Added: CSS code:
body {
background-color: #111111;
color: #DDD;
font-family: "Gill Sans", "Gill Sans MT", "Myriad Pro", "DejaVu Sans Condensed", Helvetica, Arial, sans-serif;
}
.wrapper {
overflow: auto;
}
.banner {
float: left;
position: relative;
width: 100px;
}
.main {
position: relative;
width: 80%;
left: 25px;
font-size: 14px;
font-weight: normal;
}
a {
text-decoration: none;
color: #EEE;
}
a:hover {
border-bottom: thin solid #F7EDAA !important;
color: #F7EDAA !important;
}
.topNav {
height: 45px;
position: relative;
left: 100px;
font-size: large;
border: thin solid #111;
}
#subNav {
height: 45px;
position: relative;
left: 100px;
top: 2px;
border: thin solid #111;
}
.topNav li, #subNav li {
float: left;
margin: 10px 15px;
}
.topNav ul, #subNav ul {
list-style: none;
padding: 0px 0px;
margin: 0px 0px;
position: relative;
left: -100px;
}
.content {
position: relative;
left: 15px;
padding: 0px 0px;
margin: 0px 0px;
}
.content p {
padding: 5px 5px;
margin: 10px 15px;
left: -100px;
}
In my opinion you´re using the wrong technology to achieve your goal. What you need to do is to write your styles in a css stylesheet, and then add or remove classes to your elements using js if you want. (You can also do this through something called specificity, a little far ahead from the scope of your question)
Also think that if there is some bug in your script, or a third party script called in your page, JS may break and it won´t process your styling changes.
So, add the basic styling to your elements through css in the initial markup, so you will be sure that your elements will have always a basic styling, and then if you want use the equivalent to .addClass or removeClass jQuery methods.
In that way you will be always sure that your frontend will have always a safe styling, won´t break if js is not loaded, and separation of concerns will be properly implemented.
Regards.
I figured it out. The following code does not do the right thing:
function loadPHP(url, target) {
for (var i = 0; i<subNavNames.length; i++) {
if (target == subNavNames[i]){
document.getElementById(target).className="selected";
} else {
document.getElementById(target).className="notSelected";
}
}
While this code does produce the right result:
function loadPHP(url, target) {
for (var i = 0; i<subNavNames.length; i++) {
if (target == subNavNames[i]) {
document.getElementById(subNavNames[i]).className="selected";
} else {
document.getElementById(subNavNames[i]).className="notSelected";
}
}
The difference is that in the first example, and in the example of the original question, I use the variable passed on in the method (target), to find the element. In the second, I use the appropriate element from a array that I have added to the list. I am not sure WHY this behaves differently, but it does.

Categories