I'm trying to create a chain of buttons:
First options;
- Button 1
- Button 2
IF chosen Button 1:
- Button 1a
- Button 1b
IF chosen Button 1a:
- Button 1aa
- Button 1ab
IF chosen Button 1b:
- Button 1ba
- Button 1bb
And so on.. same goes for Button 2.
Thus far I got this but my .js is not working out for me.
I tried it in two ways.
WAY 1:
HTML (onclick="nextPush" is going to change in way 2)
<div class="buttons1-2">
<button id="btn1" class="btn btn1" onclick="buttonPushed(this)">Button 1</button>
<button id="btn2" class="btn btn2" onclick="buttonPushed(this)">Button 2</button>
</div>
<div class="buttons1a-b">
<button id="btn1a" class="btn btn1a" onclick="nextPush(this)">Button 1a</button>
<button id="btn1b" class="btn btn1b" onclick="nextPush(this)">Button 1b</button>
</div>
<div class="buttons2a-b">
<button id="btn2a" class="btn btn2a">Button 2a</button>
<button id="btn2b" class="btn btn2b">Button 2b</button>
</div>
<div class="buttons1aa-ab">
<button id="btn1aa" class="btn btn1a">Button 1aa</button>
<button id="btn1ab" class="btn btn1b">Button 1ab</button>
</div>
<div class="buttons1ba-bb">
<button id="btn1ba" class="btn btn2a">Button 1ba</button>
<button id="btn1bb" class="btn btn2b">Button 1bb</button>
</div>
WAY 1: .JS
function buttonPushed(btn) {
var replacewith = "buttons1a-b";
if (btn.id == "btn2") {
replacewith = "buttons2a-b";
}
function nextPush(btn) {
var replacewith = "buttons1aa-ab";
if (btn.id == "btn1b") {
replacewith = "buttons1ba-bb";
}
var allChildren = document.getElementsByClassName('buttons')[0].children;
for (var i = 0; i < allChildren.length; i++) {
var child = allChildren[i];
if (child.className != replacewith) {
child.style.display = "none";
} else {
child.style.display = "inline";
}
}
}
WAY 2: HTML (notice the onclick="nextPush" is gone)
<div class="buttons1-2">
<button id="btn1" class="btn btn1" onclick="buttonPushed(this)">Button 1</button>
<button id="btn2" class="btn btn2" onclick="buttonPushed(this)">Button 2</button>
</div>
<div class="buttons1a-b">
<button id="btn1a" class="btn btn1a" onclick="buttonPushed(this)">Button 1a</button>
<button id="btn1b" class="btn btn1b" onclick="buttonPushed(this)">Button 1b</button>
</div>
<div class="buttons2a-b">
<button id="btn2a" class="btn btn2a">Button 2a</button>
<button id="btn2b" class="btn btn2b">Button 2b</button>
</div>
<div class="buttons1aa-ab">
<button id="btn1aa" class="btn btn1a">Button 1aa</button>
<button id="btn1ab" class="btn btn1b">Button 1ab</button>
</div>
<div class="buttons1ba-bb">
<button id="btn1ba" class="btn btn2a">Button 1ba</button>
<button id="btn1bb" class="btn btn2b">Button 1bb</button>
</div>
WAY 2 .JS
function buttonPushed(btn) {
/* btn = Id: btn1, btn2, btn1a or btn1b */
let replacewith = "buttons1a-b";
if (btn.id == "btn2") {
replacewith = "buttons2a-b";
}
else if (btn.id == "btn1a") {
replacewith = "buttons1aa-ab";
}
else if (btn.id == "btn1b") {
replacewith = "buttons1ba-bb";
}
}
let allChildren = document.getElementsByClassName('buttons')[0].children;
for (let i = 0; i < allChildren.length; i++) {
let child = allChildren[i];
if (child.className != replacewith) {
child.style.display = "none";
} else {
child.style.display = "inline";
}
}
.CSS for BOTH WAYS:
.buttons1a-b {
display: none;
}
.buttons2a-b {
display: none;
}
.buttons1aa-ab {
display: none;
}
.buttons1ba-bb {
display: none;
}
Sorry for the long post, hope you can help me out :) If you know a better way to do this, please also do let me know.
Building on your example, and the one from Michael, you could also use another approach of declaring what div you want displayed by attaching an attribute to the button, and then add an event listener to all buttons with that attribute. This makes the HTML slightly smaller and more declarative, and makes it easier to switch what element you want to display next instead of relying on a particular schema of id's.
(function(document) {
// get all buttons that have the attribute data-next
const buttons = document.querySelectorAll('[data-next]');
for (const item of buttons) {
// get references to the parent item and next item to hide/show
const parentId = item.getAttribute('data-parent');
const parent = document.querySelector(`#${parentId}`);
const nextDivId = item.getAttribute('data-next');
const nextDiv = document.querySelector(`#${nextDivId}`);
if (!nextDiv) {
console.error('could not find next div for button ', item);
}
// attach an event listener for click that toggles visibility of the above elements
item.addEventListener('click', function() {
nextDiv.classList.toggle('hidden');
parent.classList.toggle('hidden');
});
}
})(document);
.hidden {
display: none;
}
<div id="base">
<button data-next="option-a" data-parent="base">Option A</button>
<button data-next="option-b" data-parent="base">Option B</button>
</div>
<div id="option-a" class="hidden">
<p>Option A</p>
</div>
<div id="option-b" class="hidden">
<p>Option B</p>
</div>
If you want to add new buttons dynamically (or change what your next items should be) you will need to attach the event listener when you create your other buttons. For instance, you can do something like the following:
(function(document) {
function onButtonClicked(event) {
const item = event.target;
// get references to the next item to show
const nextDivId = item.getAttribute('data-next');
const nextDiv = document.querySelector(`#${nextDivId}`);
if (!nextDiv) {
console.error('could not find next div for button ', item);
}
// The function toggle on classList either removes a class if it exists
// or adds it if it does not exist in the list of classes on the element
nextDiv.classList.toggle('hidden');
// check if container has an attribute for loading next buttons lazily
const lazyLoadLevel = nextDiv.getAttribute('data-level');
// if we found the attribute, load the contents
if (lazyLoadLevel) {
// cast lazyLoadedLevel to an integer (with +) since getAttribute returns a string
loadLevel(+lazyLoadLevel, nextDiv);
// since we have populated the container we can remove the attribute so that elements do not get added again
nextDiv.removeAttribute('data-level');
}
// get references to the parent item to hide
const parentId = item.getAttribute('data-parent');
const parent = document.querySelector(`#${parentId}`);
if (parent) {
parent.classList.toggle('hidden');
}
}
function addButton(parent, nextElementId, text) {
const newItem = document.createElement('button');
newItem.setAttribute('data-next', nextElementId);
newItem.setAttribute('data-parent', parent.getAttribute('id'));
newItem.textContent = text;
newItem.addEventListener('click', onButtonClicked);
parent.appendChild(newItem);
}
function loadLevel(level, container) {
switch (level) {
// depending on level you can define other buttons to add here
case 2:
{
addButton(container, 'option-a', 'Goto option a');
break;
}
}
}
// get all *existing* buttons that have the attribute data-next
// this is run once when the script loads, and will not attach listeners to dynamically created buttons
const buttons = document.querySelectorAll('[data-next]');
for (const item of buttons) {
// attach an event listener for click that toggles visibility of parent and next elements
// notice that we pass a reference to onButtonClicked. Even though it is a function we shouldn't call it *here*
item.addEventListener('click', onButtonClicked);
}
})(document);
.hidden {
display: none;
}
<div id="base">
<button data-next="option-a" data-parent="base">Option A</button>
<button data-next="option-b" data-parent="base">Option B</button>
</div>
<div id="option-a" class="hidden">
<p>Option A</p>
<button data-next="option-b" data-parent="option-a">Option B</button>
</div>
<div id="option-b" class="hidden" data-level="2">
<p>Option B. The contents of this div is loaded lazily based on the value of the attribute data-level</p>
</div>
At first, I was thinking this should be done entirely dynamically -- where the next container of buttons is created and inserted into the DOM when the button is clicked. But judging by your current attempts, it seems like you want to have all the buttons hardcoded into the source, hidden with CSS, and shown with DOM during the click event. Here is one way you can achieve that:
function handleButtonClick(button) {
const clickedID = button.id.substring(3);
const nextDiv = document.getElementById("buttons" + clickedID);
if (nextDiv) {
nextDiv.style.display = "block";
}
}
.hidden {
display: none;
}
<div id="buttons">
<button id="btn1" onclick="handleButtonClick(this)">Button 1</button>
<button id="btn2" onclick="handleButtonClick(this)">Button 2</button>
</div>
<div id="buttons1" class="hidden">
<button id="btn1a" onclick="handleButtonClick(this)">Button 1a</button>
<button id="btn1b" onclick="handleButtonClick(this)">Button 1b</button>
</div>
<div id="buttons2" class="hidden">
<button id="btn2a" onclick="handleButtonClick(this)">Button 2a</button>
<button id="btn2b" onclick="handleButtonClick(this)">Button 2b</button>
</div>
<div id="buttons1a" class="hidden">
<button id="btn1aa" onclick="handleButtonClick(this)">Button 1aa</button>
<button id="btn1ab" onclick="handleButtonClick(this)">Button 1ab</button>
</div>
<div id="buttons1b" class="hidden">
<button id="btn1ba" onclick="handleButtonClick(this)">Button 1ba</button>
<button id="btn1bb" onclick="handleButtonClick(this)">Button 1bb</button>
</div>
<div id="buttons2a" class="hidden">
<button id="btn2aa" onclick="handleButtonClick(this)">Button 2aa</button>
<button id="btn2ab" onclick="handleButtonClick(this)">Button 2ab</button>
</div>
<div id="buttons2b" class="hidden">
<button id="btn2ba" onclick="handleButtonClick(this)">Button 2ba</button>
<button id="btn2bb" onclick="handleButtonClick(this)">Button 21bb</button>
</div>
This just identifies which button was clicked, and uses that information to determine the next div to show, until there are no more divs that correspond to the one that was clicked.
Related
How can I add a for-loop to just pick the first buttons of the div where the .mybuttons class is located?
var mapNumber;
const mybuttons = document.querySelectorAll('.mybuttons button');
mybuttons.forEach(mybutton => {
mybutton.addEventListener('click', processClick);
});
function processClick() {
window.mapNumber = this.id; // the id of the clicked button
}
<div class="mybuttons">
<button id="One">One</button>
<button id="Two">Two</button>
<button id="Three">Three</button>
<button id="Four">Four</button>
<button id="Five">Five</button>
</div>
I'm using a bootstrap modal.
The Function what I want to dynamically create a button at body tag when I click the modal button.
Description about function what I apply: As soon as I click the bluebutton, I want to create it at the body tag('beside the '+' button')
window.onlaod = function(){
var blue = document.getElementById('blue');
blue.onclick = function(){
blue.onclick = null;
var result = document.getElementById('result');
var newblue = document.createElement('span');
newblue.id = 'newblue';
newblue.innerHTML += '<button type="button" class="btn btn-primary btnWH " id="blue"></button>';
result.appendChild(newblue);
};
};
-> This is the code about event after click the bluebutton.
<!-- label color -->
<div class="modal-body">
<button type="button" class="btn btn-primary btnWH " id="blue"></button>
</div>
-> This is the code about bluebutton.
<div class="card border-secondary mb-3" style="max-width: 20rem;">
<div class="card-header">Header</div>
<div class="card-body">
<div id="result">
<span id="first">
<button type="button" class="btn btn-primary plusbtn" data-toggle="modal" data-target="#mymodal"> +
</button>
</span>
</div>
</div>
</div>
-> This is the code about '+'button.
This will create a button when click on add button inside div id of result code as follows:
<html>
<body>
<button type="button" id="blue">add</button>
<div id="result"></div>
<script>
window.onload = function() {
return addEvent();
}
function addEvent() {
var blueButton = document.getElementById('blue');
blueButton.addEventListener("click", addButton)
}
function addButton() {
var result = document.getElementById('result');
var newBtn = document.createElement('span');
newBtn.id = 'newblue';
newBtn.innerHTML += '<button type="button" id="blue">test</button>';
result.appendChild(newBtn);
}
</script>
</body>
</html>
I have an array of buttons, which each hold a different value.
I need to add an event listener to listen for when it has been clicked.
The value of the button clicked will be pushed into a different array.
I feel like I need forEach, but can't quite fit it in.
function placeBet() {
var betBtn_nodelist = document.querySelectorAll('.bet_amount > button');
var betButtonsArr = Array.prototype.slice.call(betBtn_nodelist);
for (var i = 0; i < betButtonsArr.length; i++) {
betButtonsArr[i];
}
}
<div class="bet_amount">
<button class="five" value="5">5</button>
<button class="ten" value="10">10</button>
<button class="fifty" value="50">50</button>
<button class="hundred" value="100">100</button>
</div>
You have to attach a click event handler for every item from your array.
result = [];
function placeBet(){
var betBtn_nodelist = document.querySelectorAll('.bet_amount > button');
var betButtonsArr = Array.prototype.slice.call(betBtn_nodelist);
for (let i = 0; i < betButtonsArr.length; i++) {
betButtonsArr[i].onclick = function(){
result.push(this.value);
console.log(result);
}
}
}
placeBet();
<div class="bet_amount">
<button class="five" value="5">5</button>
<button class="ten" value="10">10</button>
<button class="fifty" value="50">50</button>
<button class="hundred" value="100">100</button>
</div>
You can do it this way using jquery :
var values = []
$(document).on('click', 'button', function() {
values.push(this.value)
console.log(values)
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js"></script>
<div class="bet_amount">
<button class="five" value="5">5</button>
<button class="ten" value="10">10</button>
<button class="fifty" value="50">50</button>
<button class="hundred" value="100">100</button>
</div>
how can I set a global click listener to grab the value?
Yes, you have to set a global click listener for all buttons in only one object – <div class="bet_amount">. If you set one click listener for each button then it is bad for the browser perfomance.
With e.target.nodeName == 'BUTTON' you can recognize the click on buttons inside "bet_amount" class element.
var result = [];
function placeBet()
{
var betAmount = document.querySelector('.bet_amount');
betAmount.onclick = function(e)
{
if(e.target.nodeName == 'BUTTON')
{
result.push(+e.target.value); //"+" is converting to integer
console.log(result.join(','))
}
};
}
placeBet();
<div class="bet_amount">
<button class="five" value="5">5</button>
<button class="ten" value="10">10</button>
<button class="fifty" value="50">50</button>
<button class="hundred" value="100">100</button>
</div>
I have list of buttons (or div):
<button type="button" class="btn" id="btn1">Details1</button>
<button type="button" class="btn" id="btn2">Details2</button>
<button type="button" class="btn" id="btn3">Details3</button>
<button type="button" class="btn" id="btn4">Details4</button>
I want to have next:
when I press btn1 it's background color changes to white. When I press btn2 - btn2 background color becomes white and btn1 background color changes back to normal.
Another solution, still using jQuery :
HTML
<button type="button" class="btn" id="btn1" onClick="activate( this )">Details1</button>
<button type="button" class="btn" id="btn2" onClick="activate( this )">Details2</button>
<button type="button" class="btn" id="btn3" onClick="activate( this )">Details3</button>
<button type="button" class="btn" id="btn4" onClick="activate( this )">Details4</button>
JS
function activate( element ){
clearAll();
$( element ).addClass( 'active' );
}
function clearAll(){
$( '.btn' ).removeClass( 'active' );
}
https://jsfiddle.net/33eup40e/6/
And a solution using AngularJS :
JS
angularApp.controller( 'WhiteButtonCtrl', function( $scope ){
$scope.buttons = [
{ id: 'btn1', value: 'Details1' },
{ id: 'btn2', value: 'Details2' },
{ id: 'btn3', value: 'Details3' },
{ id: 'btn4', value: 'Details4' }
]
$scope.activeBtn = undefined;
$scope.activate = function( str ){
$scope.activeBtn = str;
}
});
HTML
<div ng-controller="WhiteButtonCtrl">
<button ng-repeat="button in buttons" ng-class="{ 'active' : activeBtn === button.id }"
ng-click="activate( button.id )" type="button" class="btn" id="{{button.id}}">
{{button.value}}
</button>
</div>
https://jsfiddle.net/33eup40e/13/
Create a class with background color.
Then attach a listener to every div, on click you will add that special class to them.
Every time you click div, you need to remove that class from any other div, after that, apply class to selected div.
Get your button collections by document.getElementsByClassName and catch click by addEventListener .Also can change css background by element.style.background
<button type="button" class="btn" id="btn1">Details1</button>
<button type="button" class="btn" id="btn2">Details2</button>
<button type="button" class="btn" id="btn3">Details3</button>
<button type="button" class="btn" id="btn4">Details4</button>
<script>
var btn = document.getElementsByClassName("btn");
for(var i =0 ; i < btn.length;i++){
btn[i].addEventListener("click",function(){
toggle(this.id);
});
}
function toggle(id){
for(var i =0 ; i < btn.length;i++){
btn[i].style.background = "";
}
document.getElementById(id).style.background = "white";
}
</script>
simply two line of code would work for your problem
$('.btn').click(function() {
$('.btn').removeClass('active');
$(this).addClass('active');
});
.btn {
background-color: lightblue;
border: none;
cursor: pointer;
}
.btn.active {
background-color: white;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button type="button" class="btn" id="btn1">Details1</button>
<button type="button" class="btn" id="btn2">Details2</button>
<button type="button" class="btn" id="btn3">Details3</button>
<button type="button" class="btn" id="btn4">Details4</button>
I am trying to replicate the following HTML code by using only Javascript (no jQuery).
I want the buttons to appear as a group,but it looks like they are being appended individually.
I've read up on bootstrap button groups (http://getbootstrap.com/components/#btn-groups) and the btn-group classs is being called on the html. So therefore my javascript DOM manipulation is incorrect.
Can someone help me to understand why my buttons are not appearing correctly? Please note that this is only a snippet of the entire code. the HTML elements are nested in a "row" div and "container" div.
HTML
<div>
<div class="btn-group btn-group-lg">
<button type="button" class="btn btn-default">Left</button>
<button type="button" class="btn btn-default">Middle</button>
<button type="button" class="btn btn-default">Right</button>
</div>
</div>
Javascript
var divTwo = document.createElement('div');
row.appendChild(divTwo);
col.appendChild(divTwo);
var btnGroupFour = document.createElement('div');
btnGroupFour.className = 'btn-group btn-group-lg';
divTwo.appendChild(btnGroupFour);
var btnLeft = document.createElement('button');
var textLeft = document.createTextNode('Left');
btnLeft.appendChild(textLeft);
btnLeft.className = 'btn btn-default';
var btnMiddle = document.createElement('button');
var textMiddle = document.createTextNode('Middle');
btnMiddle.appendChild(textMiddle);
btnMiddle.className = 'btn btn-default';
var btnRight = document.createElement('button');
var textRight = document.createTextNode('Right');
btnRight.appendChild(textRight);
btnRight.className = 'btn btn-default';
btnGroupFour.appendChild(btnLeft);
btnGroupFour.appendChild(btnMiddle);
btnGroupFour.appendChild(btnRight);
jsfiddle link:
https://jsfiddle.net/bchang89/eh7uhs43/2/
You can use cloneNode() on the parent element .btn-group and set it to a deep copy. Deep copy will create a copy of the target node as well as it's descendants. The only limitation is that it will not copy any event listeners added to either the target node or it's descendants.
// Collect all .btn-group into a NodeList (btnGrp)
var btnGrp = document.querySelectorAll('.btn-group');
// Determine the last .btn-grp by using the .length property -1
var lastGrp = btnGrp.length - 1;
// Reference the index in the btnGrp NodeList
var tgt = btnGrp[lastGrp];
// Create a clone of tgt and set the parameter to true for deep copy
var dupe = tgt.cloneNode(true);
// Append the clone to the body or any other element you wish.
document.body.appendChild(dupe);
EDIT
// Appendinding to `.container` since it looks better and makes more sense.
var box = document.querySelector('.container');
box.appendChild(dupe);
Fiddle
Snippet
var box = document.querySelector('.container');
var btnGrp = document.querySelectorAll('.btn-group');
var lastGrp = btnGrp.length - 1;
var tgt = btnGrp[lastGrp];
var dupe = tgt.cloneNode(true);
box.appendChild(dupe);
.btn-default {
color: #007aff;
background-color: #fff;
border-color: #007aff;
}
.btn-default:hover,
.btn-default:focus,
.btn-default:active {
color: #fff;
background-color: #007aff;
border-color: #007aff;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" />
<div class="container">
<div class="row">
<div class="col-md-12">
<div>
<div class="btn-group">
<button type="button" class="btn btn-default">1</button>
<button type="button" class="btn btn-default">2</button>
<button type="button" class="btn btn-default">3</button>
<button type="button" class="btn btn-default">4</button>
</div>
<div class="btn-group">
<button type="button" class="btn btn-default">5</button>
<button type="button" class="btn btn-default">6</button>
<button type="button" class="btn btn-default">7</button>
</div>
<div class="btn-group">
<button type="button" class="btn btn-default">8</button>
</div>
</div>
<hr>
<div>
<div class="btn-group btn-group-lg">
<button type="button" class="btn btn-default">Left</button>
<button type="button" class="btn btn-default">Middle</button>
<button type="button" class="btn btn-default">Right</button>
</div>
</div>
</div>
</div>
</div>