activate and deactivate in the same button - javascript

I am trying to make this button to do two things, I want it to be green and says "activate" and when I press it the button turns red and says "deactivate" and changes a column in the data to 1, and vice versa .
and if the column in the database is 1 it needs to be red and if it is 0 it needs to be green .
if someone just can tell what's the term so I can look for it because I searched a lot and I didn't come across what I need .

As mentioned in the comments by #yiffyiffyiff, the term you are looking for is called toggling. It sounds like you want to toggle the state of the button from active to deactive and vice-versa.

Using event delegation and classList.toggle.
document.addEventListener("click", handle);
function handle(evt) {
if (evt.target.classList.contains("toggleBtn")) {
return toggleBtn(evt.target);
}
}
function toggleBtn(btn) {
btn.classList.toggle("red");
/** ... more actions **/
}
.toggleBtn {
background-color: #B8F4B8;
border: none;
padding: 5px;
}
.toggleBtn:before {
content: "Activate";
}
.toggleBtn.red {
background-color: red;
color: white;
}
.toggleBtn.red:before {
content: "Deactivate";
}
<button class="toggleBtn"></button>

Related

Simplest way to toggle functionality in vanilla JS

Anyways I’m trying to make a lightbulb. It’s just a circle, I have an onclick event on a button, and the event function toggled a class, changing the color. But I want the text in the button to toggle as well when that class is activated.
I finally made it work as I was writing this question. But it still isn’t working how I want it. I only want to have one if statement.
I only want to solve it this specific way, by checking if a class is activated, and if yes, then change the text content of the button, if not, then leave it how it is.
let bulb = document.getElementById("light");
let lightSwitch = document.getElementById("switch");
function activity(event) {
bulb.classList.toggle("lightOn");
if (bulb.classList.contains("lightOn")) {
lightSwitch.textContent = "OFF";
} else if (bulb.classList.contains("lightOff")) {
lightSwitch.textContent = "ON";
}
}
.lightOn {
background: yellow;
}
<div id="light" class="lightOff"></div>
<button id="switch" onclick="activity()">ON</button>
How can I write it with only one if statement, Also, is there a way easier than this? Just vanilla not jQuery.
like this?
...
function activity(event) {
bulb.classList.toggle("lightOn");
lightSwitch.textContent = bulb.classList.contains("lightOn") ? "OFF" : "ON";
}
...
Your code can be simplified by extracting the bulb-specific default styles into a light class, then only toggle a new lightOn class. The default styles describe what to show if the bulb is off, but you can override those styles with !important in the lightOn class. Just like this:
let bulb = document.getElementById("light");
let lightSwitch = document.getElementById("switch");
lightSwitch.addEventListener('click', function() {
bulb.classList.toggle('lightOn');
lightSwitch.textContent = bulb.classList.contains("lightOn") ? "OFF" : "ON";
});
.light {
width: 100px;
height: 100px;
border-radius: 100%;
background: gray;
}
.lightOn {
background: yellow !important;
}
<div id="light" class="light"></div>
<button id="switch">ON</button>
You can also shorten your if-statement into a ternary expression, which is a better choice for this situation because only one value changes.

Toggle switch with JS

I'm trying to learn some JS, and would like to know if anyone could help me, please.
I would like to do, in a dashboard admin, an control with toggle switch to show on the index of the site whether the service is online or offline.
When on, put a "online" text in a green tag. And when not working, "offline" with a red tag.
How can I do this? With event listener? Thanks!
Example
Here's a simple exaple to show you an approach.
document.getElementById(`status`).addEventListener(`click`, function(){
const classes = this.classList;
if (classes.contains(`offline`)) {
this.textContent = `Online`;
classes.remove(`offline`);
classes.add(`online`);
} else if (classes.contains(`online`)) {
this.textContent = `Offline`;
classes.remove(`online`);
classes.add(`offline`);
}
});
#status {
color: white;
}
.online {
background: green;
}
.offline {
background: red;
}
<span id='status' class='offline'>Offline</span>

Javascript: select others

I am working on an API where the plan is that the users fill in a short checklist with multiple options before a POST request is made. For each section the users gets multiple options / buttons, but only 1 of them can be selected.
The selected button will get the class marked (Which changes the background color to green) whilst the others remain white (unless one of them is clicked, in which case it turns green and the others become white)
I have tried two different Javascript functions, but so far none of them were able to get this behavior to work.
Attempt 1:
function Label(self, group) {
// mark button
let btns = document.getElementsByClassName(group);
for (el in btns) {
btns[el].classList.remove('marked')
}
self.classList.add('marked');
}
Attempt 2 (a more explicit check to see if self is involved)
function Label(self, group) {
// mark button
let btns = document.getElementsByClassName(group);
for (el in btns) {
if (btns[el] !== self) {
btns[el].classList.remove('marked')
}
}
self.classList.add('marked');
}
My reasoning was to first remove the .marked class from all elements, and then set it on the this element. As the function is called with the onclick command in the HTML it knows which of the elements it is.
<div class="group1">
<button onclick="Label(this, pt_toggle)" class="pt_toggle">Incorrect</button>
<button onclick="Label(this, pt_toggle)" class="pt_toggle">Partially correct</button>
<button onclick="Label(this, pt_toggle)" class="pt_toggle">Correct</button>
</div>
However, the functions did not behave as I hoped. It throws an Uncaught TypeError: Cannot read property 'remove' of undefined error and the class is not set.
Does anyone know what I am doing wrong?
You're running into a feature of the for..in loop syntax. When you perform:
for (el in btns) {
if (btns[el] !== self) {
btns[el].classList.remove('marked');
}
}
every property in the btns object will be iterated over, including the length property which you won't be able to remove a class name from btns["length"].
If you switch to using a normal for loop using btns.length as the limit, you won't iterate over the non-button element properties in the object:
for (var el = 0; el < btns.length; el++) {
if (btns[el] !== self) {
btns[el].classList.remove('marked');
}
}
There is an element which performs this same kind of thing natively: the radio button. This makes it easier to code a more concise solution (well, except the CSS to make it look like more a button, but that's optional):
var buttons = Array.from(document.querySelectorAll(".group1 .button"));
buttons.forEach((el) => {
el.addEventListener("click", function (e) {
buttons.forEach((button) => button.classList.toggle("marked", button.querySelector("input").checked));
});
});
/* Hide the radio button */
.button input { display: none; }
/* make it green when selected */
.button.marked {
background: green
}
/* make the label look more like a button */
.button {
font: caption;
font-size: smaller;
padding: 2px 6px;
border: 1px solid #999;
border-radius: 1px;
background: white;
}
.button:hover {
border-color: ThreeDDarkShadow;
}
<div class="group1">
<label class="button"><input type="radio" name="pt_toggle">Incorrect</label>
<label class="button"><input type="radio" name="pt_toggle">Partially correct</label>
<label class="button"><input type="radio" name="pt_toggle">Correct</label>
</div>
Adding "marked" class on click to your button:
Your html:
<button onclick="Label(event)" class="pt_toggle">Incorrect</button>
Your js:
function Label(event) {
event.target.classList.add("marked");
}

How to create a pre-choice selection?

I was interested in creating a temporary screen before a page where someone could choose an option that would determine what they're shown.
Example: Contact page where the screen asks "Are you interested in contacting us regarding a purchase or to talk to our customer team". Once they click an option it would display the corresponding contact form (one emails customer team, the other emails the purchase team).
I'm not sure how to code this as I'm new to HTML/CSS/JavaScript but based on what I've learned so far I'm assuming this is more advanced JavaScript.
I can provide a simple example to give you some sense about it, but I would suggest you to get more basic front end training first.
if (window.confirm('Do you want load form a?')) {
document.getElementById('a').style.display = 'block';
} else {
document.getElementById('b').style.display = 'block';
}
https://jsfiddle.net/8LmL4vdr/1/
I'm not entirely sure what you asking, but it sounds like if you changed the elements' z-index values on the click of the buttons, it would work.
You can read more about z-index here.
Or, you can use display.
Here is an example:
function layerPages(page) {
if (page == "one") {
document.getElementById("pageOne").style.display = "block"; // shows first page if that is what is called
} else if (page == "two") {
document.getElementById("pageTwo").style.display = "block"; // shows second page if that is what is called
} else {
window.alert("error, wrong useage");
}
document.getElementById("originalPage").style.display = "none"; // hides main page
}
document.getElementById("buttonOne").addEventListener("click", function
myfunction() {layerPages("one");}); // adds event listener that states that when the first button is clicked, the first page is shown and the original is hidden using the function "layerPages" (declared above)
document.getElementById("buttonTwo").addEventListener("click", function
myfunction() {layerPages("two");}); // adds event listener that states that when the second button is clicked, the second page is shown and the original is hidden using the function "layerPages" (declared above)
#originalPage {
background-color: black;
width: 100px;
height: 100px;
}
#pageOne, #pageTwo {
display: none; /*You need to make sure that both #pageOne and #pageTwo start out as display: none;*/
background-color: yellow;
width: 100px;
height: 100px;
}
#pageTwo {
background-color: orange;
}
<div id="originalPage">
<button id="buttonOne">Page One</button>
<button id="buttonTwo">Page Two</button>
</div>
<div id="pageOne"></div>
<div id="pageTwo"></div>
<!--The content goes into each div, I'm sure that you can figure that out-->

How do I hide this drop down menu using javascript/jquery when any area outside of it is clicked?

Right now my I click #headerNav and menu drops down as expected but when I click any where outside of the menu it has no effect.
Where am I going wrong?
My HTML:
<header>
<div id='headerContent'>
<div id='LogoHolder'>
</div>
<nav id='headerNav'>
<ul>
<li id='photoThumbnail'></li>
<li id='currentUser'>
<ul class="dropdownMenu">
<li>link1</li>
<li>link2</li>
<li>link3</li>
<li>link4</li>
<li>link5</li>
<li>link6</li>
</ul>
</li>
</ul>
</nav>
</div>
</header>
My JS:
$("#headerNav").click(function(e) {
return $(".dropdownMenu").addClass('homeMenuClass').toggle()(e.stopPropagation());
});
$("html").click(function(e) {
return $(".dropDownMenu").addClass('menuGone').toggle();
});
CSS:
.homeMenuClass {
position:absolute;
background-color:white;
border: {
top: 2px solid $main-background-color;
right: 1px solid $main-background-color;
bottom: 1px solid $main-background-color;
left: 1px solid $main-background-color;
}
top:37px;
right:-40px;
height:245px;
width:200px;
font-weight:bold;
color:gray;
-webkit-box-shadow: 0 10px 6px -6px #777;
-moz-box-shadow: 0 10px 6px -6px #777;
box-shadow: 0 10px 6px -6px #777;
a {
color:gray;
}
}
.menuGone {
display:none !important;
}
I have looked at similar questions and tried solutions but none seem to work.
Kind regards
Update: (This is working 100% the way I want it to but for some reason it feels like I'm going about things the wrong way. e.g. the addClass('homeMenuClass') line.. Slightly confused about the toggle variable function.
$(function() {
var button = $("#headerNav"),
menu = $(".dropdownMenu", button),
toggle = function(e) {
e.stopPropagation();
if (menu.hasClass('open')) {
menu.toggle().removeClass('open').addClass('homeMenuClass');
} else {
menu.toggle().addClass('open').addClass('homeMenuClass');
}
};
button.click(toggle);
$(document).click(function(e) {
if (($(e.target).parents('#headerNav').length === 0 || e.target.id === 'headerNav') && menu.hasClass('open')) {
toggle.apply(button, [e]);
}
});
});
Here is a jsfiddle that does what you want.
Important notes
I defined the toggle function seperately to be able to reuse it.
Added the word 'Test' so I had something to click to open the menu
Always pass the event object to the toggle function since it needs to stop propagation to prevent an infinite loop.
The function is layed out as following:
jQuery(function($) {
"use strict";
var $menu = $("#headerNav"),
$dd = $(".dropdownMenu", $menu),
//Ddefine function for toggling display so we can reuse it
toggle = function(e) {
// Stop propagation will prevent the event to 'bubble' up through its parents again
// In this case it is needed to prevent an eternal loop (well jQuery will return an error at some point but regardless, this is how we prevent it)
// Normally click events when triggered are called on the direct element under the mouse, and then its parent, and its parent, because triggering one elements effectively triggers all its parents. Since we catch the click event at the highest level already we should prevent this when it is not needed, or when we click the menu itself, the toggle function will be triggered once because it was clicked and another time because at the highest level, document it might be triggered again
e.stopPropagation();
if ($dd.hasClass('homeMenuClass')) {
$dd.hide().removeClass('homeMenuClass');
} else {
$dd.show().addClass('homeMenuClass');
}
};
// Simply binds the already made function to the menu click
$menu.click(toggle);
// the document is the highest level in the DOM and most events propagate up till here unless stopped before
$(document).click(function(e) {
// Here we check if one of the parents of the target or the target itself is #headernav, if it is the function will be triggered by the menu click
// If #headerNav is not a parent or the target isn't headerNav itself it means that we clicked somewhere outside of it
if (($(e.target).parents('#headerNav').length === 0 || e.target.id === 'headerNav') && $dd.hasClass('homeMenuClass')) {
// Here we take the function toggle and apply $menu to it, make $menu `this` in the context of toggle, this isn't really nessacery for this particular case but I think its neater to call the function in the same context as the normal click would have...
// e is passed in an array(the brackets make it an array) as the first argument
// more on that here:http://trephine.org/t/index.php?title=JavaScript_call_and_apply
toggle.apply($menu, [e]);
}
});
});
Edit
Changed the function to use your classes and an instant hide/show -> this is what toggle() does but it's indescriminate of what state your element is in.
Your code looks somewhat weird, try this:
$("#headerNav").click(function(e) {
$(".dropdownMenu").addClass('homeMenuClass').show();
});
$("html").click(function(e) {
$(".dropDownMenu").addClass('menuGone').hide();
});
Unsure why you were returning anything from the event handlers and what that last () with preventDefault was about. Also, do you really need to add classes and toggle()? Also, I've switched to show/hide instead of toggle as you'll always want to hide when clicking outside and always show when clicking the menu.
Edit: If the classes are used to show/hide the menu you can (like I said) skip the call to toggle/show/hide and just use add/removeClass, like this:
$("#headerNav").click(function(e) {
$(".dropdownMenu").removeClass('menuGone').addClass('homeMenuClass');
});
$("html").click(function(e) {
$(".dropDownMenu").removeClass('homeMenuClass').addClass('menuGone');
});
Edit2: Note that when clicking #headerNav the click will bubble up to html as well unless you do e.stopPropagation(). You could also check in your html click handler if e.target was #headerNav or a child of #headerNav.
Try the onblur() js event.
$("#headerNav").blur(function(e) {
return $(".dropDownMenu").addClass('menuGone').toggle();
});
try removeClass()
$("html").click(function(e) {
return $(".dropDownMenu").removeClass('homeMenuClass');
});
Did you try :
$(document).click(function(e) {
return $(".dropDownMenu").addClass('menuGone').toggle();
});
Btw, you could use .on(), which remplace old event handlers : http://api.jquery.com/on/
It may also be a css problem : is your menuGone class applied ?

Categories

Resources