(HTML/Js) Cycling element visibilities - javascript

var terminal = document.getElementById('terminal');
var vncScreen = document.getElementById('screen');
var video = document.getElementById('video');
var vncToggle = document.getElementById('vncToggle');
var termToggle = document.getElementById('terminalToggle');
termToggle.onclick = function toggleTerminal() {
if (terminal.classList.contains('hide')) {
terminal.classList.remove('hide');
if (vncScreen.classList.contains('hide')) {} else {vncScreen.classList.add('hide')}
if (video.classList.contains('hide')) {} else {video.classList.add('hide')}
} else {
terminal.classList.add('hide');
if (video.classList.contains('hide')) {video.classList.remove('hide')} else {}
}
}
vncToggle.onclick = function toggleVNC() {
if (vncScreen.classList.contains('hide')) {
vncScreen.classList.remove('hide');
if (terminal.classList.contains('hide')) {} else {terminal.classList.add('hide')}
if (video.classList.contains('hide')) {} else {video.classList.add('hide')}
} else {
vncScreen.classList.add('hide');
if (video.classList.contains('hide')) {video.classList.remove('hide')} else {}
}
}
.black-box {
background: black;
height: 500px;
width: 500px;
position: absolute;
}
.green-box {
background: green;
height: 500px;
width: 500px;
position: absolute;
}
.blue-box {
background: blue;
height: 500px;
width: 500px;
position: absolute;
}
.hide {
display: none;
}
<button class="button" id="terminalToggle" title="Toggle Terminal">Toggle terminal</button>
<button class="button" id="vncToggle" title="Toggle Terminal">Toggle vnc</button>
<div id='video' class="black-box"></div>
<div id='screen' class="green-box hide"></div>
<div id='terminal' class="blue-box hide"></div>
basically when you click "Toggle terminal" it should show blue and then if you click again go back to black; when you click "Toggle vnc" it should show green and then if you click again go back to black. If you click "Toggle vnc" and it is already blue, it should turn green and vice versa (but clicking "Toggle terminal")
I currently have the following Js:
var terminal = document.getElementById('terminal'); //video-like element
var vncScreen = document.getElementById('screen'); //video-like element
var video = document.getElementById('video'); //video-like element
var vncToggle = document.getElementById('vncToggle'); //button
var termToggle = document.getElementById('terminalToggle'); //button
termToggle.onclick = function toggleTerminal() {
terminal.classList.toggle('hide');
vncScreen.classList.toggle('hide');
video.classList.toggle('hide');
}
vncToggle.onclick = function toggleVNC() {
vncScreen.classList.toggle('hide');
terminal.classList.toggle('hide');
video.classList.toggle('hide');
}
and css:
.hide {
display: none;
}
When I had just two different HTML elements, this class toggling methodology worked. Now that there are 3, I'm not sure it will work as desired.
video is initially visible i.e. hide is not in its classList
terminal is initially hidden i.e. hide is in its classList
vncScreen is initially hidden i.e. hide is in its classList
When toggleTerminal() is called:
video becomes hidden
terminal becomes visible
vncScreen becomes visible (but it should not)
If toggleVNC() is called (after toggleTerminal()):
video becomes visible again (but it should not)
terminal becomes hidden
vncScreen becomes hidden
Note how if the either of the function calls were toggled only by themselves, this method would work (provided I removed vncScreen.classList.toggle('hide'); in toggleTerminal() and terminal.classList.toggle('hide'); in toggleVNC()).
The problem is I need to account for any order of button-presses of termToggle and vncToggle. Essentially my goal is to "cycle" these elements such that:
1) Toggling of the "selected" element (i.e. termToggle corresponds to visibility of terminal element && vncToggle corresponds to visibility of vncScreen element) hides the remaining two elements (video && vncScreen || terminal && video respectively)
2) The order of toggling of "selected" elements does not affect 1)
3) A second toggle of the "selected" element will hide itself and the other element that is not video
Any ideas on how to best accomplish this?
At one point I thought about doing some logic that evaluated whether hide was contained in the appropriate classList's and just manually add or remove the hide class accordingly but this seemed kind of sloppy to me (idk, maybe its not?).

See code snippet in question for functionality, Js redundantly posted here:
var terminal = document.getElementById('terminal');
var vncScreen = document.getElementById('screen');
var video = document.getElementById('video');
var vncToggle = document.getElementById('vncToggle');
var termToggle = document.getElementById('terminalToggle');
termToggle.onclick = function toggleTerminal() {
if (terminal.classList.contains('hide')) {
terminal.classList.remove('hide');
if (vncScreen.classList.contains('hide')) {} else {vncScreen.classList.add('hide')}
if (video.classList.contains('hide')) {} else {video.classList.add('hide')}
} else {
terminal.classList.add('hide');
if (video.classList.contains('hide')) {video.classList.remove('hide')} else {}
}
}
vncToggle.onclick = function toggleVNC() {
if (vncScreen.classList.contains('hide')) {
vncScreen.classList.remove('hide');
if (terminal.classList.contains('hide')) {} else {terminal.classList.add('hide')}
if (video.classList.contains('hide')) {} else {video.classList.add('hide')}
} else {
vncScreen.classList.add('hide');
if (video.classList.contains('hide')) {video.classList.remove('hide')} else {}
}
}

Related

JS Overlay background

I want to ask you a very simple question. Im trying to make a nav-mobile which opens whenever you touch the hamburger button. Everything works fine but I wanted to add a "darker" background to the main page.
I ended up doing something like:
JS CODE:
var Opened = document.getElementById('menu-open');
var Closed = document.getElementById('menu-close');
function OpenNav()
{
if (Opened.getAttribute('src') == "news-homepage-main/assets/images/icon-menu.svg"){
document.getElementById('nav-mobile').style.width = '250px';
document.body.style.backgroundColor = "black";
}
}
function CloseNav()
{
if (Closed.getAttribute('src') == "news-homepage-main/assets/images/icon-menu-close.svg"){
document.getElementById('nav-mobile').style.width = '0';
document.body.style.backgroundColor = "";
}
}
BLACK COLOR CHOICE IS ONLY A TEST, the color I chose is to let you see how the results is. Still doesn't work, look at the image.
Thanks!
I tried so far to change the:
document.body.style.backgroundColor = "black";
to a filter. Still not working. I tried to make even an overlay div, but still with no success.
My guess on what you want here is an overlay with a light dark background that will be placed in front of your main page when the side nav is opened and hidden when the side nav is closed. I would suggest an absolute element that takes full width and height of the page. Something like this:
<div id="overlay"></div>
With the rules below:
#overlay {
width: 100%;
height: 100%;
background: rgba(0,0,0,0.7);
position: absolute;
top: 0;
left: 0;
display: none;
z-index: 2;
}
Have in mind you need to adjust your side-navs z-index to be less than the z-index of the overlay so it will be in front.
And in your function that open and closes the sidebar you should show and hide it accordingly. Something like this:
function OpenNav()
{
if (Opened.getAttribute('src') == "news-homepage-main/assets/images/icon-menu.svg"){
document.getElementById('nav-mobile').style.width = '250px';
document.getElementById('overlay').style.display = 'block';
}
}
function CloseNav()
{
if (Closed.getAttribute('src') == "news-homepage-main/assets/images/icon-menu-close.svg"){
document.getElementById('nav-mobile').style.width = '0';
document.getElementById('overlay').style.display = 'none';
}
}

show and hide toTopButton according the scrolling but window.onscroll not work ..i can not fix the real problem

Please I need your support as I write this code to create a button and when I press it I move to the top of page ...the button is created good and move to top of page ... But I want the button hide when the scrolling in the top of page and appear again when I scroll down ...the scroll function not work I do not know the reason … I support you with the code in JavaScript and CSS related to my question …you are genius if you can fix it.
First JavaScript code
//here i create a function to make scroll smooth...i can write it in css file but i want to show what is i lrarned:
const scrollSmoothly = function () {
const myHTML = document.querySelector("html");
myHTML.style.scrollBehavior = "smooth";
};
//create the to Top Button
//
scrollSmoothly();
function toTopButton_create() {
const toTopButton = document.createElement("botton");
const textnodeTOP = document.createTextNode("TO_Top");
toTopButton.appendChild(textnodeTOP);
//document.querySelector("footer").appendChild(toTopButton);
const rr = document.querySelector("footer");
rr.insertAdjacentElement("beforebegin", toTopButton);
toTopButton.setAttribute("id", "ourBtn");
toTopButton.addEventListener("click", test2);
}
toTopButton_create();
//below function to go to the top of sheet
function test2() {
document.body.scrollTop = 0;
document.documentElement.scrollTop = 0;
}
// below function to hide the (to top button) in the top and appear again when we scroll down
window.onscroll = function () {
scrollFunction();
};
function scrollFunction() {
if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) {
toTopButton.style.display = "block";
} else {
toTopButton.style.display = "none";
}
}
CSS code
#ourBtn {
padding: 16px;
right: 31px;
bottom: 10px;
font-size: 19px;
z-index: 98;
border-radius: 5px;
border: none;
outline: none;
display: block;
background-color: rgb(17, 199, 231);
color: rgb(29, 2, 2);
position: fixed;
cursor: pointer;
}
#ourBtn:hover {
background-color: rgb(219, 8, 8);
}
Note : when I change in CSS code and make display: none; the button hidden and when I change it to display: block; it appear again …this is not problem ...the real problem that the (to top button) not appear and hidden according to the scrolling ... I think the scroll function not work. Thanks for your support in advance.
Change this part of your code
// below function to hide the (to top button) in the top and appear again when we scroll down
window.onscroll = function () {
scrollFunction();
};
function scrollFunction() {
if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) {
toTopButton.style.display = "block";
} else {
toTopButton.style.display = "none";
}
}
To this
// below function to hide the (to top button) in the top and appear again when we scroll down
document.onscroll = scrollFunction;
function scrollFunction(event) {
if (event.srcElement.scrollingElement.scrollTop > 20 || document.documentElement.scrollTop > 20) {
toTopButton.style.display = "block";
} else {
toTopButton.style.display = "none";
}
}
Note:
Attach the event to the document object
Look for the scrollingElement (it might not be the body element)
The main problem in my code was the variable (toTopButton) this variable defined in the function ,so it is not declared or defined out the function ...when I create it a gain in the global area ...the function worked good

is there a way to change fixed element style when enter any section element on scroll

I have a chat or go to top svg btn with white border and some of my sections element have blue and other white background
what I want to do is when the fixed btn enter the section while scrolling check its background
and add different classes in each case .
how can I do that in javascript or jquery ?
thank you
The easiest thing to do would be to have the fixed button have a background color that looks good on all sections. That way you can just style it and leave it alone.
If you have to have the color change at different sections, there are a few ways of doing that, none are easy, and only a few would have good performance.
The best way of doing this that I can think of would be:
Have the background of the fixed button be the default color.
Add a class modifier so that when you add one class it changes the style to the new color. Example: .button becomes .button.red
On each section that has to change the background of the button, add a custom data-attribute Example: <section change-button-bg="red">
Then on load
Set up a .querySelectorAll(*[change-button-bg]) so that you can run
a check on each of the sections.
Add a global variable called currentTarget
Set up an Intersection Observer on all the sections.
Have the callback function for .isIntersecting do a few things.
Update the currentTaget variable
Update the color of the button
Add a scroll listener
In the scroll listener watch the bounds.bottom of currentTarget to see which color it should be.
Then in the Intersection Observer, if it's no longer intersecting, remove the scroll listener to prevent memory leaks.
Here is a working example.
window.addEventListener('load', (event) => {
const changeBG = document.querySelectorAll('*[change-button-bg]');
let currentTarget = null;
const Observer = new IntersectionObserver((entries, Observer) => {
for (const entry of entries) {
if (entry.isIntersecting) {
currentTarget = entry.target;
addColor(true);
window.addEventListener('scroll', watchTarget);
} else {
addColor(false);
window.removeEventListener('scroll', watchTarget)
}
}
}, {threshold: 0.15});
for (const element of changeBG) {
Observer.observe(element);
}
function watchTarget() {
const bounds = currentTarget.getBoundingClientRect();
if (bounds.bottom < window.innerHeight - 80) {
addColor(false);
} else {
addColor(true);
}
}
function addColor(add) {
const btn = document.getElementById('button');
if (add) {
btn.classList.add('red');
} else {
btn.classList.remove('red');
}
}
});
body {
margin: 0;
}
section {
width: 100vw;
height: 100vh;
background: red;
}
section:nth-child(even) {
background: blue;
}
button {
position:fixed;
right: 50px;
bottom: 50px;
padding: 15px 25px;
border: none;
color: white;
background-color: blue;
cursor: pointer;
}
button.red {
background-color: red;
}
<html>
<body>
<section></section>
<section change-button-bg="red"></section>
<section></section>
<section change-button-bg="red"></section>
<section></section>
<button id="button">Top</button>
</body>
</html>
this is the solution I was looking for I did it using Intersection Observer
document.addEventListener('DOMContentLoaded',()=>{
let options = {
root:null,
rootMargin:"-570px 0px -100px 0px",
threshold:0.05
};
let Observer= new IntersectionObserver(changColor,options);
document.querySelectorAll("section").forEach(section => {
Observer.observe(section);
});
});
function changColor(elements) {
elements.forEach(el => {
if (el.isIntersecting) {
let elbg=el.target.dataset.bg;
if (elbg=="blue") { //if section data-bg== blue
// change svg button style
document.getElementById("chatting_path_7").style.fill = "#fff";
document.getElementById("to_top_Ellipse_4").style.stroke = "#fff";
} else {
document.getElementById("chatting_path_7").style.fill = "#034ea2";
document.getElementById("to_top_Ellipse_4").style.stroke = "#034ea2";
}
}
})
}

Create alert pop-up with blank background screen [duplicate]

This question already has answers here:
Why don't my alert message and background color change execute simultaneously?
(3 answers)
Closed 3 years ago.
I need to display an alert box and at the same time cover what is on my HTML page. Basically, I'd like to have a blank or white background when my alert pop-up appears. I tried something like below, but doesn't work.
if (something happens) {
changeBackgroundColor();
if (alert("My alert box")){
} else {
//Return to previous page
window.history.go(-1);
}
}
..
....
.....
function changeBackgroundColor() {
document.body.style.backgroundColor = "white";
}
Changing your background color will not hide any of the elements on your page. You will most likely need an overlay, which can be a simple div styled something like this:
.overlay {
position:fixed;
top:0;
left:0;
right:0;
bottom:0;
z-index:999; /* adjust the z-index as you need it */
background:#fff;
display:none;
}
you can then show the overlay before your alert and hide it afterwards
function toggleOverlay( show ){
document.querySelector('.overlay').style.display = (show === true) ? 'block' : 'none';
}
// ...
toggleOverlay(true);
// Kudos to Kobe for pointing out that the alert is triggered before the repaint
// simple way to solve the problem is a timeout, which will
// make the browser paint the changes before the alert is triggered
setTimeout(function(){
alert('Something');
toggleOverlay(false);
}, 0);
Here is a working jsFiddle: https://jsfiddle.net/UsernamesSuck/cpdrtgb8/2/
The problem is that when alert() is called the rest of the script pauses. A solution is to wrap it in a setTimeout() function to make it async to allow the rest of the code to be executed.
Take a look at the following Fiddle for a possible solution:
https://jsfiddle.net/hckevbtp/
You can create an absolutely positioned div with a z-index greater than all of your content to hide it:
const hide = () => {
var div = document.getElementById('hide')
div.style.display = 'block'
setTimeout(() => {
alert()
div.style.display = 'none'
}, 0)
}
.hide {
position: fixed;
width: 100vw;
height: 100vh;
top: 0;
left: 0;
background-color: blue;
z-index: 1000;
display: none;
}
<p>Content Content Content</p>
<button onclick="hide()">HIDE</button>
<div id="hide" class="hide"></div>
Since alert is blocking, you can immediately remove the style after the alert, which will take effect after the alert is closed.
you can use the display='none' for the container and call the alert in setTimeout() as follows -
function openAlert() {
document.getElementsByClassName('block')[0].style.display = 'none';
setTimeout(function() {
alert('hello world!');
document.getElementsByClassName('block')[0].style.display = 'block';
}, 100);
}
html -
<body>
<div class='block'>
<button onclick={openAlert()}>hello</button>
</div>
</body>
Try this:
if (something happens) {
changeBackgroundColor();
setTimeout(function() {alert("hey");}, 0)
}
..
....
.....
function changeBackgroundColor() {
document.body.style.opacity= "0";
}
You can use below code:
function showMessage() {
var div = document.getElementById('div');
if(div == null){
div = document.createElement('div');
div.id = "div";
}
div.classList.add('alert')
document.body.appendChild(div)
setTimeout(function() {
alert("alert text");
div.classList.remove('alert');
},0)
}
Style:
.alert {
width: 100%;
height: 100%;
top: 0;
left: 0;
position: absolute;
background-color: white;
}

add className on scroll in JavaScript

I'm trying to add a className on scroll. I keep getting a
document is undefined
edit: I found out I was getting the error from the typo. When I define document.getElementsByClassName("main-nav").scrollTop nothing comes up in the console. As well as the page does not get affected.
window.onscroll = function() {
windowScroll();
};
function windowScroll() {
if (document.getElementsByClassName("main-nav").scrollTop > 50 || document.documentElement.scrollTop > 50) {
document.getElementsByClassName("main-nav").className = "test";
} else {
document.getElementsByClassName("main-nav").className = "";
}
}
CSS is
.test {
background: pink
}
I'm not necessarily looking for the answer, I just want guidance
There are 2 problems:
getElementsByClassName returns an array of HTMLCollection and it has no property scrollTop. You probably want the first item so the code shoul be document.getElementsByClassName("main-nav")[0] (or document.querySelector(".main-nav"))
But if you try it, you will get an error:
Cannot read property 'scrollTop' of undefined
window.onscroll = function() {
windowScroll();
};
function windowScroll() {
if (document.getElementsByClassName("main-nav").scrollTop > 50 || document.documentElement.scrollTop > 50) {
document.getElementsByClassName("main-nav").className = "test";
} else {
document.getElementsByClassName("main-nav").className = "";
}
}
html, body {
height: 150%;
}
.test {
background: pink
}
<div class="main-nav"></div>
The reason is that you override the class attribute of .main-nav by this assignment:
document.getElementsByClassName("main-nav").className = "";
In this line you set the class attribute to empty string. You probably want to add / remove the test call but keeping the main-nav class.
There are 2 things you can do:
Set the id attribute to main-nav instead of the class attribute, then use document.getElementById method.
window.onscroll = function() {
windowScroll();
};
function windowScroll() {
if (document.getElementById("main-nav").scrollTop > 50 || document.documentElement.scrollTop > 50) {
document.getElementById("main-nav").className = "test";
} else {
document.getElementById("main-nav").className = "";
}
}
html, body {
height: 150%;
}
#main-nav {
position: fixed;
width: 100%;
}
.test {
background: pink
}
<div id="main-nav">Main Nav</div>
Toggle only the test class using classList.toggle.
window.onscroll = function() {
windowScroll();
};
function windowScroll() {
if (document.getElementsByClassName("main-nav")[0].scrollTop > 50 || document.documentElement.scrollTop > 50) {
document.getElementsByClassName("main-nav")[0].classList.add("test");
} else {
document.getElementsByClassName("main-nav")[0].classList.remove("test");
}
}
html, body {
height: 150%;
}
.main-nav {
position: fixed;
width: 100%;
}
.test {
background: pink
}
<div class="main-nav">Main Nav</div>
The final approach with some optimisations:
var mainNav = document.querySelector('.main-nav');
window.onscroll = function() {
windowScroll();
};
function windowScroll() {
mainNav.classList.toggle("test", mainNav.scrollTop > 50 || document.documentElement.scrollTop > 50);
}
html, body {
height: 150%;
}
.main-nav {
position: fixed;
width: 100%;
}
.test {
background: pink
}
<div class="main-nav">Main Nav</div>
The changes:
Store the .main-nav element on the global context (the window object). It will not change so you don't need to find it in any scroll.
Use querySelector so you will get a single DOM element, not collection.
Use classList.toggle to toggle the class by condition.
The issue with your console.log is that you're trying to pull the scrollTop for an HTML Collection (a collection of elements in your page) of 1 or more divs - therefore it can't check for the scrollTop as the console.log as it doesn't actually have that property.
Assuming you only have one element with the "main-nav" class (or there is a particular element with this class that you wish to apply it to), you would be better off using one of the following: document.getElementsByClassName("main-nav")[0] or document.getElementById("main-nav") (the latter would require you to create a main-nav id rather than a class).
For the first one, however, using className reassigns the class name rather than adding to that particular div, therefore you can use document.getElementsByClassName("main-nav")[0].classList.add("test") (and remove instead of add if it does not match your criteria).
If there is more than one element with the "main-nav" class, you can still use the first option I suggested - only you would need to wrap it around in a for loop and replace the 0 with your variable of choice.
for (i = 0; i < document.getElementsByClassName("main-nav").length; i++) {
//your code here using document.getElementsByClassName("main-nav")[i]
}

Categories

Resources