I have a task in school and I think Javascript is really hard. Now in the beginning I need to google everything and I only find solutions in different libraries.
In this case I need to use Vanilla JS. When I click on logout button it need to toggle and show the login button.
In the task I cant change the HTML only add JS.
// student
<button class="signin-btn is-hidden">Log in </button>
<button class="signout-btn">Log out </button>
You can add click event listeners to both of the buttons to change its own display to none and display the other button.
var login = document.querySelector('.signin-btn'),
logout = document.querySelector('.signout-btn');
login.addEventListener('click', function(e){
this.classList.add('is-hidden');//adds is-hidden class
logout.classList.remove('is-hidden');//removes is-hidden class
});
logout.addEventListener('click', function(e){
this.classList.add('is-hidden');
login.classList.remove('is-hidden');
});
.is-hidden{
display: none;
}
<button class="signin-btn is-hidden">Log in </button>
<button class="signout-btn">Log out </button>
here's a extremely basic way to do it, I would recommend using more advanced techniques later
function change() {
document.getElementById('but').style.display = "none"
document.getElementById('butother').style.display = "block"
}
function changeother() {
document.getElementById('butother').style.display = "none"
document.getElementById('but').style.display = "block"
}
<html>
<body>
<button id="but" onclick='change()'>log in </button>
<button id="butother" onclick='changeother()'>log out </button>
</body>
</html>
Related
I have an issue with document.getElementById(). Basically I have different forms each one with a different id and I'm using a bit of Javascript to replace some classes and add dinamically file name after upload.
That should be really easy, but I don't know why even if the ids are totally unique I get a weird behavior: whatever is the form in which I submit a file javascript will apply changes always on the first of them.
function spinnerLoad(){
document.getElementById('file-name[[${id}]]').textContent = this.files[0].name;
document.getElementById('spinner[[${id}]]').classList.replace('fas', 'spinner-border');
document.getElementById('spinner[[${id}]]').classList.replace('fa-file-upload', 'spinner-border-sm');
document.getElementById('uploadForm[[${id}]]').submit()
}
/*I'm using Bootstrap for my styling rules*/
/*${id} variable is server-side and it's there to make unique each form, I'm using Thymeleaf template engine*/
<form th:id="'uploadForm'+${id}" method="post" enctype="multipart/form-data" th:action="#{/upload/{id} (id=${id})}">
<label for="file-upload" class="btn btn-outline-success">
<span th:id="'spinner'+${id}" class="fas fa-file-upload"></span> <b>Upload file:</b> <i th:id="'file-name'+${id}">No file selected</i>
</label>
<input id="file-upload" type="file" name="multipartFile" accept="application/pdf" style="display: none" th:onchange="spinnerLoad()"/>
</form>
I googled the problem but I didn't manage to find a specific answer to my issue, so that's why I'm here bothering you.
I hope someone can help my figure this out, thank you.
You get a lot of repeating code and that can be hard to maintain. Here I placed the event listener on the the parent <div> to all the buttons. Then I need to test if is a button. And there is no need for an id for each button.
Actually, if you are just replacing a class name you don't even need to do the test (if()), because replace() will only do the replacement when the old value is present. This should be fine:
buttons.addEventListener('click', e => {
e.target.classList.replace('btn-success', 'btn-danger');
});
But here is the full example with the test:
var buttons = document.getElementById('buttons');
buttons.addEventListener('click', e => {
if (e.target.nodeName == 'BUTTON') {
e.target.classList.replace('btn-success', 'btn-danger');
}
});
.btn-success {
background-color: green;
}
.btn-danger {
background-color: red;
}
<div id="buttons">
<button class="btn-success">Button 1</button>
<button class="btn-success">Button 2</button>
<button class="btn-success">Button 3</button>
</div>
You're missing the css that would make this work, but otherwise your example is functional. However, it can be done more simply by working on the buttons as a class instead of individually.
var btns = document.getElementsByClassName("btn");
var addDanger = function(){
this.classList.replace('btn-success', 'btn-danger')
};
for (var i = 0; i < btns.length; i++) {
btns[i].addEventListener('click', addDanger, false);
};
.btn {height:20px; width: 50px;}
.btn-success {background-color:green}
.btn-danger {background-color:red}
<button id="btn1" class="btn btn-success"></button>
<button id="btn2" class="btn btn-success"></button>
<button id="btn3" class="btn btn-success"></button>
I want to receive information from my users using buttons, so i created two sections for that. When the user clicks a button i need it to change its style so the user will see a difference in what they clicked even when they click another button in the other section. The problem is that when another button is clicked the other section looses its style (so the user wouldn't know what he previously clicked). I pasted the html code of the part with the problem(below)
<div>
<p><strong>Network</strong></p>
<button class="btn25" onclick = "gfg_Run()">
MTN
</button>
<button class="btn25">
Glo
</button>
<button class="btn25">
9 Mobile
</button>
<button class="btn25">
Airtel
</button>
</div>
<div>
<p><strong>Data</strong></p>
<button class="btn25">
1Gb
</button>
<button class="btn25">
2Gb
</button>
<button class="btn25">
3Gb
</button>
<button class="btn25">
5Gb
</button>
<button class="btn25">
10Gb
</button>
</div>
i need it to change its style so the user will see a difference
Create a class called active and then set the buttons to use that class when the user selects them.
The problem is that when another button is clicked the other section looses its style
The issue is that you need to separate out each group. I added a class on the parent div that distinguishes the two groups: "data" or "speed". The button background will change to blue for each of the groups because it is limited to that class in the query as ".data" does here:
document.querySelectorAll('.data .btn25');
Here is an example snippet showing the basic technique.
const dataChoices = document.querySelectorAll('.data .btn25');
dataChoices.forEach(function(choice) {
choice.addEventListener('click', function() {
removeClass(dataChoices);
this.classList.add('active');
});
});
const speedChoices = document.querySelectorAll('.speed .btn25');
speedChoices.forEach(function(choice) {
choice.addEventListener('click', function() {
removeClass(speedChoices);
this.classList.add('active');
});
});
function removeClass(dataGroup) {
dataGroup.forEach(function(choice) {
choice.classList.remove('active');
});
}
.active {
background-color: lightblue;
}
div {
float: left;
margin-right: 10px;
}
<div class="data">
<p><strong>Data</strong></p>
<button id="1" class="btn25">1Gb</button>
<button id="2" class="btn25">2Gb</button>
<button id="3" class="btn25">3Gb</button>
<button id="4" class="btn25">5Gb</button>
<button id="5" class="btn25">10Gb</button>
</div>
<div class="speed">
<p><strong>Speed</strong></p>
<button id="1" class="btn25">1Mbps</button>
<button id="2" class="btn25">2Mbps</button>
<button id="3" class="btn25">3Mbps</button>
<button id="4" class="btn25">5Mbps</button>
<button id="5" class="btn25">10Mbps</button>
</div>
I have an alternate way to do this, but honestly Christopher Taleck's answer is perfectly fine as well, I just had a different conception of how to solve the problem and figured that would be informative for others facing a similar situation.
Here is a link to a JSFiddle with a working example: JSFiddle
Here is the complete code, an explanation of everything is provided below:
index.html
<!DOCTYPE html>
<html>
<head>
<title>Button Practice</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="network-container">
<h2>Network</h2>
<button type="button" class="btn25">MTN</button>
<button type="button" class="btn25">Glo</button>
<button type="button" class="btn25">9 Mobile</button>
<button type="button" class="btn25">Airtel</button>
</div>
<div class="speed-container">
<h2>Speed</h2>
<button type="button" class="btn25">1Mbps</button>
<button type="button" class="btn25">2Mbps</button>
<button type="button" class="btn25">3Mbps</button>
<button type="button" class="btn25">5Mbps</button>
<button type="button" class="btn25">10Mbps</button>
</div>
<script type="text/javascript" src="script.js"></script>
</body>
</html>
script.js
function ButtonContainer(element) {
this.element = element;
this.selectedButton = null;
this.element.addEventListener('click', function(e) {
if (e.target.type !== 'button') return;
if (this.selectedButton) this.selectedButton.classList.remove('active');
e.target.classList.add('active');
this.selectedButton = e.target;
});
}
const networkContainer = new ButtonContainer(document.querySelector('.network-container'));
const speedContainer = new ButtonContainer(document.querySelector('.speed-container'))
style.css
.active {
background-color: #9AD58E;
}
GENERAL CODE EXPLANATION
First, I would suggest removing this call to gfg_Run() from the .html file:
// index.html
<button class="btn25" onclick = "gfg_Run()">
And creating a separate file to hold your JS. Then, you can just link that file like so, right before the closing <body> tag (I created a file called script.js for this purpose):
// index.html
<script type="text/javascript" src="script.js"></script>
Also, I would suggest adding a descriptive class based on the type of buttons that each <div> holds, like so:
// index.html
<div class="network-container">
------ rest of the container ------
<div class="speed-container">
------ rest of the container ------
To handle the change of style on the button click, you can create a class that is added to the clicked button. I will use .active as that is a pretty common convention. This can be in a style.css file that you link from the head of the HTML document:
// style.css
.active {
background-color: #9AD58E;
}
In that script.js file, my approach would be to create a constructor function that represents the container that holds the buttons:
// script.js
function ButtonContainer(element) {
this.element = element;
this.selectedButton = null;
this.element.addEventListener('click', function(e) {
if (e.target.type !== 'button') return;
if (this.selectedButton) this.selectedButton.classList.remove('active');
e.target.classList.add('active');
this.selectedButton = e.target;
});
}
ButtonContainer CONSTRUCTOR FUNCTION EXPLANATION
We set the ButtonContainer up with two properties, element and selectedButton. element represents the DOM element which contains the buttons (in our case, a <div>), and the selectedButton represents the last <button> in this <div> that was clicked.
The eventListener will fire whenever the <div> is clicked anywhere inside it's borders. We only want to handle clicks on a <button> element within this <div>, so we exit the listener if the target of the event was not a button with the line below:
if (e.target.type !== 'button') return;
Next, we want to see of there is already a selectedButton in this <div>, and if so, we need to remove the .active class from it so we don't have two buttons in the same <div> that have colored backgrounds:
if (this.selectedButton) this.selectedButton.classList.remove('active')
Finally, we set the .active class on the <button> that triggered the event, and set the selectedButton property of this ButtonContainer object to that button, so that we can keep track of the currently selected button in this <div>:
e.target.classList.add('active');
this.selectedButton = e.target;
Then simply create two instances of the ButtonContainer that represent the <div> elements containing each group of buttons (each <div> should have a class representing the type of buttons it holds):
const networkContainer = new ButtonContainer(document.querySelector('.network-container'));
const speedContainer = new ButtonContainer(document.querySelector('.speed-container'));
In this way, you don't have to loop through the buttons and add event listeners to each, you simply allow each container to handle it's own button events. I like this approach because we seem to be treating the buttons like two separate groups, and this logically mirrors that.
Here's my button:
<button type="button" id="myButton" class="myButtonCSS" onclick="handleMyButtonClick()"> myButton! </button>
In my handleMyButtonClick() function I have a bit of logic, but what I want to accomplish is to add a waiting icon while it's doing that logic. I found out how to do this with this code:
<i class="fa fa-spinner fa-spin"></i>
If I add that to my original button statement it works, but it's ALWAYS there. I only want this to show up when clicked. I'm trying to add the "i class" to the button within my JavaScript on click function. I've tried to use .classList.add() but I must be doing it wrong, or approaching it wrong entirely. How can I do this?
What you need to do is update the inner html of button in the beginning of your method handleMyButtonClick()
var btn = document.getElementById('myButton');
btn.innerHTML = '<i class = "fa fa-spinner fa-spin"></i> Please wait...';
Then when you are done with your logic, reset the button back to the original state.
btn.innerHTML = 'myButton!';
Have a look at this complete code. Works just as you wanted.
function handleMyButtonClick(){
// Get button element
btn = document.getElementById('myButton');
// Set the spinner
btn.innerHTML = '<i class = "fa fa-spinner fa-spin"></i> Please wait...';
// Do the work. A sample method to wait for 3 second.
setTimeout(function(){
console.log("work done");
// When the work is done, reset the button to original state
btn.innerHTML = 'myButton!';
}, 3000);
}
<button type="button" id="myButton" class="myButtonCSS" onclick="handleMyButtonClick()"> myButton! </button>
I guess this will work out for you please check
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
</head>
<body>
<button type="button" id="myButton" class="" onclick="handleMyButtonClick()"> <span id='spin'></span>myButton! </button>
</body>
<script>
function handleMyButtonClick(){
$("#spin").addClass("fa fa-spinner fa-spin");
setTimeout(()=>{
//Do some logic
$("#spin").removeClass("fa fa-spinner fa-spin");
},5000)
}
</script>
</html>
As javascript uses single thread, and if your code is synchronous, you will not be able to see the style change immediately. Once the execution of the method is finished, then it will renders the UI with new style. So, in your case, it wont' show any difference. As you are showing and hiding by the end of the function. If you want show the spinner you have to hide the spinner in setTimeout().
Try following:
<button type="button" id="myButton" class="myButtonCSS" onclick="handleMyButtonClick()">
<i class="fa fa-spinner fa-spin"></i>
myButton!
</button>
function handleMyButtonClick() {
document.getElementById('myButton').classList.add('loading');
// your logic goes here
setTimeout(function() {
document.getElementById('myButton').classList.remove('loading');
}, 2000);
}
.myButtonCSS {
position: relative;
}
.myButtonCSS .fa-spinner {
display: none;
position: absolute;
left: 5px;
top: 5px;// you can modify according to your button height and width
}
.myButtonCSS.loading .fa-spinner {
display: inline-block;
}
Thank you for all of your suggestions but I have a far simpler answer.
tempButton = document.getElementById('myButton'); //snag button
tempButton.innerHTML = '<i class = "fa fa-spinner fa-spin"></i> Please wait...';
I'm VERY new to web programming. Sorry I cannot explain for you, but this 1 line change the code of my button within my JavaScript on click function instantly.
I have a stripe button and want to add my custom class. I found that you can manually create the CSS for it and it will work, although, I want to keep all the buttons on my site consistent by using my custom class.
Whatever I try I cannot remove the default button
<form action="/update-the-card" method="POST">
{{ csrf_field() }}
<script
src="https://checkout.stripe.com/checkout.js" class="stripe-button"
data-key="{{ env('STRIPE_KEY') }}"
data-name="My site"
data-panel-label="Update Card"
data-label="Update Card"
data-allow-remember-me=false
data-locale="auto">
</script>
</form>
My class is 'button fstyle1 thin' that id like on it
I've tried this but does not work.
$('button.stripe-button-el').removeAttr('style').addClass('button fstyle1 thin')
Found the answer. All you need to do is add your own custom submit button and just hide the one stripe provides you with. Very easy.
<form action="/update-the-card" method="POST">
{{ csrf_field() }}
<script src="https://checkout.stripe.com/checkout.js" class="stripe-button"
data-key="{{ env('STRIPE_KEY') }}"
data-amount="44040"
data-name="nameeee"
data-description="descriptionnn"
data-locale="auto">
</script>
<script>
// Hide default stripe button, be careful there if you
// have more than 1 button of that class
document.getElementsByClassName("stripe-button-el")[0].style.display = 'none';
</script>
<button type="submit" class="button green fsize-16 f-weight-400">Purchase Here!</button>
</form>
I think that is your class (button fstyle1 thin) level is lower then .stripe-button-el
Try add !important in you css.
or add more css combinators like: .a .b .c form .fstyle1
Hope to help you.
Its maybe your .button.stripe-button-el element is not exist in the DOM at the time of binding(means created dynamically).
So you can bind your event handler to a higher element $(document).
Try to use $(document) here...
$(document).find("button.stripe-button-el").removeAttr("style").addClass("button fstyle1 thin");
Like #victory said, the easier solution is to hide the button given by stripe by this line :
document.getElementsByClassName("stripe-button-el")[0].style.display = 'none';
If you have multiple stripe buttons on one page, this will do the job :
<script>
var all_buttons = document.getElementsByClassName("stripe-button-el");
for (var i = 0; i < all_buttons.length; i++) {
all_buttons[i].style.display = "none";
}
</script>
Happy coding !
Try this,
$(document).find("button.stripe-button-el").removeAttr("style").addClass("'button fstyle1 thin'");
$(".stripe-button-el").find("span").remove();
$(".stripe-button-el").html("Proceed to pay");
I don't know why this function is not working.
HTML:
<button id="welcomehomebtnlogin" type="button" onclick="loginformfunction()">Login</button>
JavaScript:
function loginformfunction()
{
document.getElementById("welcomehomebtndiv").style.display = "none";
document.getElementById("loginform").style.display = "block";
}
What I want to do is: if the user clicks on the "Login" button, one form will disappear with display = "none". The button is part of this form, and it will also disappear. Then a second form will be shown.
It's not working; any ideas why?
Your code look fine, check the basic example bellow.
Hope this helps.
function loginformfunction()
{
document.getElementById("welcomehomebtndiv").style.display = "none";
document.getElementById("loginform").style.display = "block";
}
document.getElementById("welcomehomebtnlogin").addEventListener('click', loginformfunction, false);
#loginform{
display: none;
}
<div id='welcomehomebtndiv'>
Welcome HOME div
<button id="welcomehomebtnlogin" type="button">Login</button>
</div>
<div id='loginform'>
Login div
</div>