How to toggle a button to an active state using vanilla JS? - javascript

I have a list of 20 buttons on a page. When I click on a button I want it to switch to an "active" state. In this active state it will be a different color. I would like to do this using only vanilla javascript and css.
I have the following code to create the buttons:
var button;
createButtons();
function createButtons() {
for (i = 0; i < 20; i++) {
//creates a new button
button = document.createElement('Button');
//sets correct button number and button text
var index = i + 1;
var text = document.createTextNode('Button ' + index);
button.appendChild(text);
button.className += "button";
button.className += " default-button";
document.body.appendChild(button);
}
}

Modern browsers support the classList API now.
In order to use the classList API, try adding the following to your code:
var buttons = document.getElementsByClassName('button')
Array.prototype.forEach.call(buttons, function (button) {
button.addEventListener('click', function (event) {
button.classList.toggle('button-active')
})
})
If you want to only turn the active state on, switch the toggle method of classList to add. Read more on classList.
Breakdown of code example:
First I select all .button elements and store them in a NodeList data type.
Then I call array's forEach function (another way of doing the same would be [].forEach.call() but that creates new Array instance every time it runs). I add an event listener for click event upon which I toggle a new class name.
For a direct CSS manipulation, you can use button.style.color = 'red' - but I discourage you from this approach to keep your code maintainable.
Note from Phil (in the comments to this answer):
You can use NodeList.prototype.forEach() which shortens the line into buttons.forEach(function (button) {. Bear in mind that Internet Explorer does not support this.

CSS alternative without JavaScript:
input[type=checkbox] { display: none; }
input[type=checkbox] + label { background-color: cyan; }
input[type=checkbox]:checked + label { background-color: red; }
<input type=checkbox id=t1><label for=t1> Toggle 1 </label><br>
<input type=checkbox id=t2><label for=t2> Toggle 2 </label><br>
<input type=checkbox id=t3><label for=t3> Toggle 3 </label><br>
<input type=checkbox id=t4><label for=t4> Toggle 4 </label><br>
<input type=checkbox id=t5><label for=t5> Toggle 5 </label><br>

Assuming you only want one button "active" at a time, I would just use the CSS :focus / :active pseudo-class. For example
for (let i = 1; i <= 20; i++) {
let btn = document.createElement('button')
btn.textContent = `Button ${i}`
btn.classList.add('button', 'default-button')
document.body.appendChild(btn)
}
.button {
background-color: blue;
color: white;
font-weight: bold;
}
.button:active, .button:focus {
background-color: red;
}

You can use button.onclick = function(){ // do things here. };
I have included the code in a snippet below. Good luck.
var button;
createButtons();
function createButtons() {
for (i = 0; i < 20; i++) {
//creates a new button
button = document.createElement('Button');
//sets correct button number and button text
var index = i + 1;
var text = document.createTextNode('Button ' + index);
button.appendChild(text);
button.className += "button";
button.className += " default-button";
// --------------------------------------------------------
// on click check if it contains the class for the color
// and toggle it on or off.
button.onclick = function() {
if (this.classList.contains("enableColor")) {
this.classList.remove('enableColor');
} else {
this.classList.add("enableColor");
}
}
// --------------------------------------------------------
document.body.appendChild(button);
}
}
.enableColor {
background: red;
color: white;
}

.focus(), but most browsers actually block button click type behavior for security purposes. What you can do is set the button elements disabled = true attribute then when you get whatever action you are looking for toggle that attribute to disabled = false.
Here's a snippet you could adapt:
// enables submit button iif inputs meet validation contraints
function attachKeyupListenerToInputElements(){
var inputs = doc.querySelectorAll('input');
for (var i = 0; i < inputs.length; i++) {
inputs[i].addEventListener("keyup", keyupHandler);
}
function keyupHandler() {
if(this.value === ''){
this.setCustomValidity('Required Field');
} else {
this.setCustomValidity('');
}
//for dialog inputs
if(doc.querySelector(".mdc-dialog").classList.contains("mdc-dialog--open")){
//dialog is open
var thisSection = this.parentElement.parentElement;
var theseInputs = thisSection.querySelectorAll("input");
var inputsFull = true;
for (var i = 0; i < theseInputs.length; i++) {
if(!theseInputs[i].checkValidity()){
inputsFull = false;
}
}
if(inputsFull){
doc.getElementById("dialog-accept-button").disabled = false;
}
}
}
}

Related

How do I attach placeholder to the button through JS' DOM?

I am trying to figure out how to attach button 'Delete' to the each list element making so in advance that I will be able to make more buttons for additional list elements later.But when I create buttons,they appear without the text,just tiny rectangle box near the text.I wanted to fix through command 'document.getElementByClassName[list_number + "_button"].placeholder = "Delete",but I got an error even earlier trying to attach classnames to the buttons:
Uncaught TypeError: Cannot read property 'classList' of undefined
at addButton (script.js:74)
at script.js:82
But what's strange is that this error shows only at the [1] list object,not the the [0].For some reason with [0] object everything goes OK,although I didn't succeed in attaching name to it.I thought that the problem laid in list numeration,because the first button is actually "Send',but when I changed the value of var list_number = 0 from 0 to 1,it only got worse and gave an error right away.
How do I attach text in the buttons so they will look normal?
Note:the commands related to the buttons are at the end,everything earlier are command to add new elements to the list trhough input and make the elements line-through
CODE
var button = document.getElementById("button");
var modify_list = document.getElementById("userinput");
var ul = document.querySelector("ul");
var li = document.querySelectorAll("li");
var all_buttons = document.querySelectorAll("button");
var i = 0; //Attach classes to the li
while (li.length > i) {
li[i].classList.add(i);
li[i].classList.add('done');
li[i].classList.add('cursor');
i++
}
//Toggle the line-through function(later we will cal the function that will toggle once more when clicked on element of the list.
var n = 0
while (li.length > n) {
li[n].classList.toggle("done");
n++
}
//Command to add new elements to the list and make line-thorugh when clicked.
function inputLength() {
return modify_list.value.length;
}
function addToTheList() {
var li = document.createElement("li");
li.appendChild(document.createTextNode(modify_list.value));
ul.appendChild(li);
modify_list.value = '';
}
function addAfterClick() {
if (inputLength() === 0) {
alert("Please,don\'t enter the empty list");
} else {
addToTheList();
}
}
function addAfterEnter(key) {
if (key.keyCode === 13 && inputLength() > 0) {
addToTheList();
}
}
button.addEventListener("click", addAfterClick);
modify_list.addEventListener("keypress", addAfterEnter);
function toggle(number) {
li[number].classList.toggle("done");
}
ul.addEventListener("click", whenClicked);
function whenClicked(event) {
var li_number = event.target.className[0];
//In JS it doesn't matter in some occasions if it's a string or number,I suppouse.
// var li_number = Number(li_number_string);
// console.log(li_number);
toggle(li_number);
}
// Create buttons and their functions
function addButton(list_number) {
var button = document.createElement("button");
li[list_number].appendChild(button); //append button near the respective li objects
all_buttons[list_number].classList.add(list_number + "_button") //create class for the button
console.log(all_buttons[list_number].classList);
// document.getElementByClassName[list_number + "_button"].placeholder = "Delete"
}
var list_number = 0 // because under number 0 we have "Send" button
while (li.length > list_number) {
addButton(list_number);
list_number++;
}
// console.log(list_number);
.done {
color: red;
text-decoration: line-through;
}
.cursor {
cursor: pointer;
}
<!DOCTYPE html>
<html>
<head>
<title>DOM</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<h1>What plans do I have till the end of the summer?</h1>
<p>They are:</p>
<input type="text" name="add activities" id="userinput" placeholder="add activities">
<button id="button">Send</button>
<ul>
<li>Learn German</li>
<li>Learn Japanese</li>
<li>Learn Java Script</li>
<li>Physical activities</li>
</ul>
<script type="text/javascript" src="script.js"></script>
</body>
</html>
The text you want to be displayed on a programatically generated HTMLButtonElement can be set using it's .innerText property. The .placeholder property serves a different purpose.
Let's take a closer look at your addButton function:
function addButton(list_number){
var button = document.createElement("button");
li[list_number].appendChild(button); //append button near the respective li objects
all_buttons[list_number].classList.add(list_number + "_button") //create class for the button
console.log(all_buttons[list_number].classList);
// document.getElementByClassName[list_number + "_button"].placeholder = "Delete"
}
The first two lines are okay. Trouble starts here:
all_buttons[list_number].classList.add(list_number + "_button");
all_buttons is a HTML collection of buttons you initialized before you started adding dynamically generated button elements to the DOM thus it just contains the buttons set up via HTML. That means this array is outdated and would need to be updated every time you add or remove buttons.
Furthermore you don't need to use that array at all if you want to manipulate properties of your freshly generated button - you can directly access it using the variable button. I'd also recommend giving those buttons an unique id, so you can reference them later on and give it a click event listener for example. Also since there is already a global variable named button you should give the variable inside the function a different name e.g. localButton.
Here's an example:
var button = document.getElementById("button");
var modify_list = document.getElementById("userinput");
var ul = document.querySelector("ul");
var li = document.querySelectorAll("li");
var all_buttons = document.querySelectorAll("button");
var i = 0; //Attach classes to the li
while (li.length > i) {
li[i].classList.add(i);
li[i].classList.add('done');
li[i].classList.add('cursor');
i++
}
//Toggle the line-through function(later we will cal the function that will toggle once more when clicked on element of the list.
var n = 0;
while (li.length > n) {
li[n].classList.toggle("done");
n++;
}
//Command to add new elements to the list and make line-thorugh when clicked.
function inputLength() {
return modify_list.value.length;
}
function addToTheList() {
var li = document.createElement("li");
li.appendChild(document.createTextNode(modify_list.value));
ul.appendChild(li);
modify_list.value = '';
}
function addAfterClick() {
if (inputLength() === 0) {
alert("Please,don\'t enter the empty list");
} else {
addToTheList();
}
}
function addAfterEnter(key) {
if (key.keyCode === 13 && inputLength() > 0) {
addToTheList();
}
}
button.addEventListener("click", addAfterClick);
modify_list.addEventListener("keypress", addAfterEnter);
function toggle(number) {
li[number].classList.toggle("done");
}
ul.addEventListener("click", whenClicked);
function whenClicked(event) {
var li_number = event.target.className[0];
//In JS it doesn't matter in some occasions if it's a string or number,I suppouse.
// var li_number = Number(li_number_string);
// console.log(li_number);
toggle(li_number);
}
// Create buttons and their functions
function addButton(list_number) {
var localButton = document.createElement("button");
localButton.innerText = "Delete";
localButton.id = "myButton" + list_number;
li[list_number].appendChild(localButton);
}
var list_number = 0 // because under number 0 we have "Send" button
while (li.length > list_number) {
addButton(list_number);
list_number++;
}
.done {
color: red;
text-decoration: line-through;
}
.cursor {
cursor: pointer;
}
<h1>What plans do I have till the end of the summer?</h1>
<p>They are:</p>
<input type="text" name="add activities" id="userinput" placeholder="add activities">
<button id="button">Send</button>
<ul>
<li>Learn German</li>
<li>Learn Japanese</li>
<li>Learn Java Script</li>
<li>Physical activities</li>
</ul>

How to hide current content by clicking outside its area, and when I show another content in IE11?

Clicking on the button shows and hides the corresponding content.
function funC(id) {
var el = document.getElementById(id);
if(el.style.display == 'inline-block')
el.style.display = '';
else
el.style.display = 'inline-block';
}
button {margin:2px; outline:0; font-size:12px;}
span {padding:2px; border:1px solid silver;
font-size:12px;}
.cb {display:none;}
<button onclick="funC('cnt1');">b1</button><span id="cnt1" class="cb">content b1...</span>
<br />
<button onclick="funC('cnt2');">b2</button><span id="cnt2" class="cb">content b2...</span>
<br />
<button onclick="funC('cnt3');">b3</button><span id="cnt3" class="cb">content b3...</span>
fiddle example
1. But, how to hide content when clicking outside its area,
and as with showing the next content, hide the previous one?
2. Is it possible to do the same without using id?
Only pure javascript. Thank you.
This might not be a perfect solution but here is a proposition :
function hideAllContent() {
var elements = document.querySelectorAll(".cb");
for(var i =0, l = elements.length; i < l; i++) {
var element = elements[i];
element.visible = false;
element.style.display='none';
}
}
function funC(id, event) {
// We need to stop the event to avoid bubling until the body
event.stopPropagation();
// let's hide others before displaying the new one
hideAllContent();
var el = document.getElementById(id);
if(el.visible) {
el.visible = false;
el.style.display = 'none';
} else {
el.visible = true;
el.style.display = 'inline-block';
}
}
document.body.onclick = function(event) {
if (!event.target.classList.contains('cb')) {
hideAllContent();
}
}
button {margin:2px; outline:0; font-size:12px;}
span {padding:2px; border:1px solid silver;
font-size:12px;}
.cb {display:none;}
<button onclick="funC('cnt1', event);">b1</button><span id="cnt1" class="cb">content b1...</span>
<br />
<button onclick="funC('cnt2', event);">b2</button><span id="cnt2" class="cb">content b2...</span>
<br />
<button onclick="funC('cnt3', event);">b3</button><span id="cnt3" class="cb">content b3...</span>
About avoiding ids, you could use the target property on click event and find the sibling node or something like that or use a querySelector. But ids are safe and fine i would say.
No inline on-clicks attached.
No IDs use.
Used backward-compatible syntax for IE 11.
// JavaScript
// get all button and span tags
var btns = document.querySelectorAll('button');
var otherSpans = document.querySelectorAll('span');
// Detect all clicks on the document
document.addEventListener("click", function(event) {
const spanElems = document.querySelectorAll('span');
const spanElemsArray = Array.prototype.slice.call(spanElems);
let matches = event.target.matches ? event.target.matches('button') : event.target.msMatchesSelector('button');
// If user clicks inside the element, do nothing
if (matches) {
return;
} else {
// If user clicks outside the element, hide it!
spanElemsArray.forEach( function (spanElem) {
spanElem.classList.remove("open");
});
}
});
// convert buttons and spans variable objects to arrays
const btnsArray = Array.prototype.slice.call(btns);
const otherSpansArray = Array.prototype.slice.call(otherSpans);
// loop through every button and assign a click to each one
btnsArray.forEach( function (btn) {
btn.addEventListener('click', spanFunc)
});
// Pass the button clicked as a reference
function spanFunc(){
openSpan(this);
}
// toggle the display class on the span next to the button using nextElementSibling method
function openSpan(e) {
e.nextElementSibling.classList.toggle("open");
// hide every other spans
function otherSpanFunc() {
otherSpansArray.forEach( function (otherSpan) {
if (otherSpan !== e.nextElementSibling) {
otherSpan.classList.remove('open');
}
});
}
otherSpanFunc();
}
/* css */
button {margin:2px; outline:0; font-size:12px;}
span {padding:2px; border:1px solid silver;
font-size:12px;}
.cb {display:none;}
.open {display:inline-block;}
<!-- HTML -->
<button>b1</button><span class="cb">content b1...</span>
<br />
<button>b2</button><span class="cb">content b2...</span>
<br />
<button>b3</button><span class="cb">content b3...</span>
jsFiddle: https://jsfiddle.net/ypofz4d5/55/

HTML5 form required attribute. How to check required message has been shown?

I have a multi-page form with some input with required attribute. I want to hide or show buttons if input with required attribute are empty or not.
How can I do this with javascript?
Elements that fail validation will match the :invalid pseudoselector. You can match on that to hide the next element:
input:invalid {
border-color: red;
}
input:invalid + span {
display: none;
}
<input required>
<span>
<button>Submit</button>
</span>
If you have multiple elements and you want to show or hide something based on whether anything is bad, you should know that the <form> containing :invalid elements is also :invalid:
input:invalid {
border-color: red;
}
input:valid + span {
display: none;
}
form:invalid + div {
display: none;
}
<form>
<input required>
<span>First name required!</span>
<br>
<input required>
<span>Last name required!</span>
<br>
</form>
<div>
<button>Submit</button>
</div>
You should probably rename your question as it has nothing to do with "required message showing". In your case, you can try something like this:
var handlerFunction = function () {
var elements = document.querySelectorAll("#myForm input");
var isEmpty = false;
for (var i = 0; i < elements.length; i++) {
if (elements[i].value === '') {
hideButtons();
isEmpty = true;
break;
}
}
if (!isEmpty) {
showButtons();
}
};
var hideButtons = function () {
// hide buttons
};
var showButtons = function () {
// show buttons
};
var elements = document.querySelectorAll("#myForm input");
for (var i = 0; i < elements.length; i++) {
elements[i].addEventListener("keydown", handlerFunction);
}
To use it you have to change #myForm to your form's id or class.
Here's the javascript solution that you wanted, but the solution above that uses css is a lot better (in case you don't need to use javascript).
I would get the input and see if the content is equal to empty:
document.getElementById('inputRequire').innerText == '';
document.getElementById('inputRequire').value == '';
and then i show the other:
var hiddenElements = document.getElementsByTagName('hiddenOnes');
foreach(...){
element.style.display = 'block';
}
Something like that, i don't test the code but i think it can help you

How to leave one active button in the JavaScript?

I am beginner.
I have four buttons and I want to leave one active button every time with expression operator (if). One button must have active every time .
I tried to do it something like that. I am open to your ideas, if you can do without (if) .Help me!
var count = 4;
var flag = true;
function select(currentColor, changeColor){
if(count > 1 && flag === true){
var currentElement = angular.element(document.getElementsByClassName(currentColor));
currentElement.toggleClass(changeColor);
count--;
console.log(count);
console.log('From minus: ' + count);
}else{
flag = false;
}
if(count < 4 && flag === false) {
var currentElement = angular.element(document.getElementsByClassName(currentColor));
currentElement.toggleClass(changeColor);
count++;
console.log(count);
console.log('From plus: ' + count);
}else{
flag = true;
}
}
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<style>
.changeColor{
color: red !important;
}
.first{
color: #07888A;
}
.second{
color: #07888A;
}
.third{
color: #07888A;
}
.fourth{
color: #07888A;
}
h1{
display: inline;
margin-right: 20px;
}
</style>
</head>
<body>
<h1 class="first" onClick="select('first', 'changeColor')">First</h1>
<h1 class="second" onClick="select('second', 'changeColor')">Second</h1>
<h1 class="third" onClick="select('third', 'changeColor')">Third</h1>
<h1 class="fourth" onClick="select('fourth', 'changeColor')">Fourth</h1>
</body>
</html>
Add this bit:
function select(currentColor, changeColor) {
// Get the list of the `.changeColor` elements.
changed = document.querySelectorAll(".changeColor");
// Loop through all the elements with `changeColor` class.
for (i = 0; i < changed.length; i++)
// Remove the changeColor class from their class list.
changed[i].classList.remove("changeColor");
// Rest comes your code.
if(count > 1 && flag === true){
are you trying to get one button disabled when any three buttons are enabled ? if so, perhaps this could help. I highly suggest not to use the h1 tags for this purpose, and use something like a button or div, and removing the onclick attributes from your elements and incorporate them in your main js file similar to the js snippet found below.
(function() {
//an empty array to track the number of elements currently colored
var numberOfElesColored = [],
eles = document.querySelectorAll('h1'),
//the number of active elements allowed at once
numberOfActiveElementsAllowed = eles.length - 1;
//loop though all the elements and attach click event
[].forEach.call(eles, function(ele, i) {
ele.addEventListener('click', function(event) {
var currentEle = event.target;
//is there at least two other elements avaliable still ?
if (!(numberOfElesColored.length === numberOfActiveElementsAllowed)) {
//yes
//is the current clicked element not active already ?
if (!currentEle.classList.contains('changeColor')) {
//yes
//add 1 to tracking array
numberOfElesColored.push(1);
//activate element
return currentEle.classList.add('changeColor');
} else {
//no
//remove 1 from tracking array
numberOfElesColored.pop();
//deactivate elements
return currentEle.classList.remove('changeColor');
}
//are all the elements active already ?
} else if (numberOfElesColored.length === numberOfActiveElementsAllowed) {
//yes
//is the current element an active one ?
if (currentEle.classList.contains('changeColor')) {
//yes
//remove 1 from tracking array
numberOfElesColored.pop();
//deactivate element
return currentEle.classList.remove('changeColor');
}
}
});
});
})();

Javascript : on click check boxes adding divs dynamically with pure java script not Jquery

I am beginner for java script.
I have three check boxes on my page with different ids. when I checked first check box I need to show one div. when I checked second check box include first check box , I need to split one div to two divs. As well as when i checked three boxes split one div to three divs.
I need to add all these divs dynamically with java script.
observe the below image and same like i need
Please help me to achieve this with simple java script code not with Jquery.
this took a bit of coding ;)
basically you want to append a div to the wrapper when you check a box, and remove it when you uncheck the box. Every time the DOM is changed I am running a setWidth function to apply a class used in the css to correctly position the boxes within the wrapper
checkboxes and wrapper to append the divs
<input type="checkbox" value="1" />
<input type="checkbox" value="2" />
<input type="checkbox" value="3" />
<div id="wrapper"></div>
css
#wrapper {
width: 100%;
height: 100px;
}
.box {
border: 1px solid black;
height: 100%;
display: inline-block;
box-sizing: border-box;
}
.cols-1 {
width: 100%;
}
.cols-2 {
width: 50%;
}
.cols-3 {
width: 33%;
}
JS
var checkboxes = document.getElementsByTagName('input');
var wrapper = document.getElementById('wrapper');
for (var i = 0; i < checkboxes.length; i++) {
var checkbox = checkboxes[i];
checkbox.addEventListener('change', changed);
}
function changed(e) {
var el = e.target;
var num = el.value;
var checked = el.checked;
if (checked) {
addBox(num);
} else {
removeBox(num)
}
}
function addBox(num) {
var box = document.createElement('div');
box.className = 'box';
box.id = 'box-' + num;
wrapper.appendChild(box);
setWidth();
}
function removeBox(num) {
var box = document.getElementById('box-' + num);
wrapper.removeChild(box);
setWidth();
}
function setWidth() {
var children = wrapper.getElementsByTagName('div');
var i = 0, length = children.length;
for (i; i < length; i++) {
children[i].className = 'box cols-' + length;
}
}
see fiddle: http://jsfiddle.net/4hrp0qc8/1/

Categories

Resources