once I add a group of dynamic buttons from an array and the querySelectorAll doesn't seem to get the list of buttons.
Here my code: Where am I going wrong?
const btns = document.getElementById("container");
const textBtn = ["btn 1", "btn 2", "btn 3", "btn 4", "btn 5", "btn 6"]
for (i = 0; i < textBtn.length; i++) {
btns.insertAdjacentHTML('beforeend', `<button class="allbuttons" value=${textBtn[i]}>${textBtn[i]}</button>`);
}
const btn = document.querySelectorAll(".allbuttons")
for (var i = 0; i < btn.length; i++) {
btn[i].addEventListener('click', function(event) {
//console.log( btn[i]);
console.log(event.target.value);
alert(event.target.value)
});
}
<div id="container"></div>
does it help? is it what u need?
const btns = document.getElementById("container");
const textBtn = ["btn 1", "btn 2", "btn 3", "btn 4", "btn 5", "btn 6"]
for (i = 0; i < textBtn.length; i++) {
btns.insertAdjacentHTML('beforeend', `<input type="button" class="allbuttons" value="${textBtn[i]}">`);
}
const btn = document.querySelectorAll(".allbuttons")
for (var i = 0; i < btn.length; i++) {
btn[i].addEventListener('click', function(event) {
console.log(event.target.value);
alert(event.target.value)
});
}
<div id="container"></div>
Your issue may come from this:
<button class="allbuttons" value=${textBtn[i]}>${textBtn[i]}</button>
Your value isn't between quotes <button class="allbuttons" value="${textBtn[i]}">${textBtn[i]}</button>
Related
I want to delete the item from the Firebase real-time database by clicking the button in JavaScript. How can I delete it? I'm getting this error: app.js:61 Uncaught ReferenceError: the key is not defined in console.
I have uploaded my complete code on jsfiddle. Where is my mistake?
https://jsfiddle.net/waqasumer/z7wt6d0e/7/
var main = document.getElementById("main-section");
function saveData() {
var todoItem = document.getElementById("todo-item");
if (todoItem.value === "") {
alert("Please enter task");
} else {
var key = firebase.database().ref('tasks').push().key;
var tasks = {
todoItem: todoItem.value,
key: key
}
firebase.database().ref('tasks/' + key).set(tasks);
document.getElementById("todo-item").value = "";
}
}
function getData() {
firebase.database().ref('tasks').on('child_added', function (data) {
var item = data.val().todoItem;
for (var i = 0; i <= item.length; i++) {
var row = document.createElement("div");
row.setAttribute("class", "row");
var col1 = document.createElement("div");
col1.setAttribute("class", "col text");
var task = document.createTextNode(item);
col1.appendChild(task);
row.appendChild(col1);
var col2 = document.createElement("div");
col2.setAttribute("class", "col");
var editBtn = document.createElement("button");
editBtn.setAttribute("class", "btn btn-success btn-circle btn-sm fa fa-pencil-square-o");
editBtn.setAttribute("onclick", "editTodo(this)");
col2.appendChild(editBtn);
row.appendChild(col2);
var col3 = document.createElement("div");
col3.setAttribute("class", "col");
var deleteBtn = document.createElement("button");
deleteBtn.setAttribute("class", "btn btn-primary btn-circle btn-sm btn-danger fa fa-remove");
deleteBtn.setAttribute("onclick", "deleteTodo(this)");
col3.appendChild(deleteBtn);
row.appendChild(col3);
main.appendChild(row);
break;
}
})
}
getData();
function deleteTodo(e) {
firebase.database().ref('tasks').child(key).remove();
}
First I think you'll want to get your data differently. Try something like this:
function getData() {
tasks = [];
firebase.database.ref('/tasks/').on('child_added', function (snapshot) {
snapshot.forEach(function (childSnapshot) {
var childData = childSnapshot.val();
tasks.push(childData);
});
for (let i = 0; i < tasks.length; i++) {
const task = tasks[i];
}
})
}
Then you can access the items you saved in firebase with dot notation, like task.todoItem for the content of the task and task.key for the key value that firebase pushed.
Then one way to do what you're looking for is to populate your markup with the pushed key that corresponds to the task. You can do it similar to how you pulled the todo item but also get the key:
var item = task.todoItem;
var taskKey = task.key
Then populate a data attribute on the row item with the key:
row.setAttribute("class", "row");
row.setAttribute("data-key", "taskKey");
Then in your delete function, do the following:
function deleteTodo(clickedElement) {
const key = clickedElement.parentElement.getAttribute(data-key);
firebase.database().ref('tasks').child(key).remove();
}
Now "key" in your delete function should have a value.
I've edited the JS code in your snippet to incorporate my changes, see if it works:
var main = document.getElementById("main-section");
function saveData() {
var todoItem = document.getElementById("todo-item");
if (todoItem.value === "") {
alert("Please enter task");
} else {
var key = firebase.database().ref('tasks').push().key;
var tasks = {
todoItem: todoItem.value,
key: key
}
firebase.database().ref('tasks/' + key).set(tasks);
document.getElementById("todo-item").value = "";
}
}
function getData() {
tasks = [];
firebase.database.ref('/tasks/').on('child_added', function (snapshot) {
snapshot.forEach(function (childSnapshot) {
var childData = childSnapshot.val();
tasks.push(childData);
});
for (let i = 0; i < tasks.length; i++) {
const task = tasks[i];
var item = task.todoItem;
var key = task.key;
var row = document.createElement("div");
row.setAttribute("class", "row");
row.setAttribute("data-key", "key");
var col1 = document.createElement("div");
col1.setAttribute("class", "col text");
var newTask = document.createTextNode(item);
col1.appendChild(newTask);
row.appendChild(col1);
var col2 = document.createElement("div");
col2.setAttribute("class", "col");
var editBtn = document.createElement("button");
editBtn.setAttribute("class", "btn btn-success btn-circle btn-sm fa fa-pencil-square-o");
editBtn.setAttribute("onclick", "editTodo(this)");
col2.appendChild(editBtn);
row.appendChild(col2);
var col3 = document.createElement("div");
col3.setAttribute("class", "col");
var deleteBtn = document.createElement("button");
deleteBtn.setAttribute("class", "btn btn-primary btn-circle btn-sm btn-danger fa fa-remove");
deleteBtn.setAttribute("onclick", "deleteTodo(this)");
col3.appendChild(deleteBtn);
row.appendChild(col3);
main.appendChild(row);
break;
}
})
}
getData();
function deleteTodo(clickedElement) {
const key = clickedElement.parentElement.getAttribute('data-key');
firebase.database().ref('tasks').child(key).remove();
}
I have a function that creates a button for each value in an array. I want to get the value of the button that is clicked and store it in a variable.
dates_button = ['8/21/2020','8/28/2020','9/4/2020','9/11/2020','9/18/2020','9/25/2020','10/16/2020','11/19/2020','1/14/2021','3/19/2021','6/18/2021','9/17/2021','1/20/2022']
function printBtn() {
for (var i = 0; i < dates_button.length; i++) {
var btn = document.createElement("button");
var t = document.createTextNode(dates_button[i]);
btn.appendChild(t);
document.body.appendChild(btn);
}
}
printBtn();
You can add an event handler that reads back the textContent from the button; then you can do what you want with it in the event handler. For example:
dates_button = ['8/21/2020', '8/28/2020', '9/4/2020', '9/11/2020', '9/18/2020', '9/25/2020', '10/16/2020', '11/19/2020', '1/14/2021', '3/19/2021', '6/18/2021', '9/17/2021', '1/20/2022']
function btnClick(e) {
let date = e.target.textContent;
// do something with it
console.log(date);
}
function printBtn() {
for (var i = 0; i < dates_button.length; i++) {
var btn = document.createElement("button");
var t = document.createTextNode(dates_button[i]);
btn.appendChild(t);
btn.onclick = btnClick;
document.body.appendChild(btn);
}
}
printBtn();
const dates_button = ['8/21/2020', '8/28/2020', '9/4/2020', '9/11/2020', '9/18/2020', '9/25/2020', '10/16/2020', '11/19/2020', '1/14/2021', '3/19/2021', '6/18/2021', '9/17/2021', '1/20/2022']
function printBtn() {
for (let i = 0; i < dates_button.length; i++) {
let btn = document.createElement("button");
let t = document.createTextNode(dates_button[i]);
btn.appendChild(t);
document.body.appendChild(btn);
btn.addEventListener('click', () => {
alert(dates_button[i]);
});
}
}
printBtn();
You don't even need to read the text out of the DOM if you just add the event listener in your loop there.
Or, if you prefer, this might be a little more efficient because it only requires one event listener.
const dates_button = ['8/21/2020', '8/28/2020', '9/4/2020', '9/11/2020', '9/18/2020', '9/25/2020', '10/16/2020', '11/19/2020', '1/14/2021', '3/19/2021', '6/18/2021', '9/17/2021', '1/20/2022']
function printBtn() {
for (let i = 0; i < dates_button.length; i++) {
let btn = document.createElement("button");
let t = document.createTextNode(dates_button[i]);
btn.appendChild(t);
document.body.appendChild(btn);
}
}
document.addEventListener('click', (ev) => {
if (ev.target.matches('button')) {
console.log(ev.target.innerText);
}
});
printBtn();
Add a value property on your button and attach an event listener. Then onClick's event you can access the value as event.target.value.
dates_button = [
"8/21/2020",
"8/28/2020",
"9/4/2020",
"9/11/2020",
"9/18/2020",
"9/25/2020",
"10/16/2020",
"11/19/2020",
"1/14/2021",
"3/19/2021",
"6/18/2021",
"9/17/2021",
"1/20/2022"
];
function printBtn() {
for (var i = 0; i < dates_button.length; i++) {
var btn = document.createElement("button");
var t = document.createTextNode(dates_button[i]);
btn.appendChild(t);
document.body.appendChild(btn);
btn.addEventListener("click", handleClick);
btn.value = dates_button[i];
}
}
function handleClick(event) {
console.log(event.target.value);
}
printBtn();
You could simply use forEach function and use onClick function to get the value of a clicked date.
Live Demo:
let dates_button = ['8/21/2020', '8/28/2020', '9/4/2020', '9/11/2020', '9/18/2020', '9/25/2020', '10/16/2020', '11/19/2020', '1/14/2021', '3/19/2021', '6/18/2021', '9/17/2021', '1/20/2022']
function printBtn() {
dates_button.forEach(function(date) {
var btn = document.createElement("button");
var text = document.createTextNode(date);
btn.appendChild(text);
btn.value = date;
btn.onclick = function() {
console.log(this.value)
}
document.querySelector('#el').appendChild(btn); //append all buttons
})
}
printBtn();
<div id="el"></div>
I'm getting some json data from the services and bind those values in the table format in the child window. Click on link in the child window, should close child window and redirect the url in parent current window.
<html>
<head>
<title>sample</title>
<script type="text/javascript">
var childWindow;
function GenerateStudentsTable() {
var jsondata = {
"school": {
"students": [{
"studentId": "Test1",
"Name": "Message01"
},
{
"studentId": "Test2",
"Name": "Message2"
}, {
"studentId": "Test3",
"Name": "Message3"
}
],
"redirectURL" : "https://www.google.com/search"
}
}
var query = "students";
var table = document.createElement("TABLE");
table.border = "1";
var headerLabels = ["Id", "Name"]
var headerLabelsCount = headerLabels.length;
var row = table.insertRow(-1);
for (var i = 0; i < headerLabelsCount; i++) {
var headerCell = document.createElement("TH");
headerCell.innerHTML = headerLabels[i];
row.appendChild(headerCell);
}
var jsonLength = Object.keys(jsondata.school.students).length;
for (var i = 0; i < jsonLength; i++) {
row = table.insertRow(-1);
for (var j = 0; j < headerLabelsCount; j++) {
var cell = row.insertCell(-1);
if (j == 0) {
cell.innerHTML = '' + jsondata.school.students[i].studentId + '';
} else {
cell.innerHTML = '' + jsondata.school.students[i].Name + '';
}
}
}
childWindow = window.open("", "Title", "toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=yes,width=780,height=200,top=" + (screen.height - 400) + ",left=" + (screen.width - 840));
childWindow.document.body.innerHTML = table.outerHTML;
}
function redirectToParentWindow()
{
childWindow.close();
window.location.href =jsondata.school.redirectURL;
}
</script>
</head>
<body>
<input type="button" value="Generate Table" onclick="GenerateStudentsTable()" />
<hr />
<div id="dvTable">
</div>
</body>
</html>
I have no issues in the binding data in the child window but i'm not sure how to close the child window and redirect to link in parent window. Thanks in advance
Below code changes are working as expected.
<html>
<head>
<title>sample</title>
<script type="text/javascript">
var childWindow, redirectUrl;
function GenerateStudentsTable() {
var jsondata = {
"school": {
"students": [{
"studentId": "Test1",
"Name": "Message01"
},
{
"studentId": "Test2",
"Name": "Message2"
}, {
"studentId": "Test3",
"Name": "Message3"
}
],
"redirectURL": "https://www.google.com/search"
}
}
var query = "students";
var table = document.createElement("TABLE");
table.border = "1";
var headerLabels = ["Id", "Name"]
var headerLabelsCount = headerLabels.length;
var row = table.insertRow(-1);
for (var i = 0; i < headerLabelsCount; i++) {
var headerCell = document.createElement("TH");
headerCell.innerHTML = headerLabels[i];
row.appendChild(headerCell);
}
var jsonLength = Object.keys(jsondata.school.students).length;
for (var i = 0; i < jsonLength; i++) {
row = table.insertRow(-1);
for (var j = 0; j < headerLabelsCount; j++) {
var cell = row.insertCell(-1);
if (j == 0) {
cell.innerHTML = '' + jsondata.school.students[i].studentId + '';
} else {
cell.innerHTML = '' + jsondata.school.students[i].Name + '';
}
}
}
redirectUrl = jsondata.school.redirectURL.concat("?q=query");
childWindow = window.open("", "Title", "toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=yes,width=780,height=200,top=" + (screen.height - 400) + ",left=" + (screen.width - 840));
childWindow.document.body.innerHTML = table.outerHTML;
}
function redirectToParentWindow() {
childWindow.close();
window.location.href = redirectUrl;
}
</script>
</head>
<body>
<input type="button" value="Generate Table" onclick="GenerateStudentsTable()" />
<hr />
<div id="dvTable">
</div>
</body>
</html>
I am making a gif generator, the goal being to dynamically create clickable buttons that will then dynamically add 10 gifs from the search term to the page. On click is returning the console log, but will not add divs with gif images and rating to the page.
HTML
<form id="killer-form">
<label for="killer-input">Add a serial killer:</label>
<input type="text" id="killer-input"><br>
<input id="killer-add-submit" type="submit" value="Submit">
</form>
<div id="append-img-div"></div>
JS
var killersGifs = {
killerSearches: ["Freddy", "Jason", "Pennywise", "Ghost Face", "American Mary", "Chucky", "Bride of Chucky", "Candyman", "Cujo", "Hannibal", "Leatherface", "Michael Meyers", "Norman Bates", "Pinhead"],
buttonLoop: function() {
for (var b = 0; b < killersGifs.killerSearches.length - 1; b++) {
var buttonM = $("<button class='dynGen'>").text(killersGifs.killerSearches[b]).attr("data-index", killersGifs.killerSearches[b]);
$("#buttons").append(buttonM);
}
},
divLoop: function(event) {
for (var i = 0; i < killersGifs.killerSearches.length - 1; i++) {
//console.log(this.killerSearches[i]);
//var newDiv = $("<div class='gif-div'>");
var killer = killersGifs.killerSearches[i];
var queryURL = "https://api.giphy.com/v1/gifs/search?api_key=B26sstJns2pZuNT5HiJpqS5FV8Su1sDd&q=" + killer + "&limit=10"
//console.log(queryURL);
$.ajax({
url: queryURL,
method: "GET"
}).done(function(response) {
console.log(response);
for (var x = 0; x < response.length - 1; x++) {
var respData = response[x].data;
var image = respData.images.fixed_height_small_still.url;
var rating = respData.rating;
var dynDiv = $("<div class='dyn-div'>");
var killerImg = $("<img>");
killerImg.attr("src", image);
killerImg.attr("alt", "Serial Killer still frame of gif");
dynDiv.append("Rating: " + rating);
dynDiv.append(image);
$("#append-img-div").prepend(dynDiv);
};
});
};
},
userPush: function () {
var userInput = $("input[type='text']").val().trim();
console.log(userInput);
killersGifs.killerSearches.push(userInput);
var buttonU = $("<button class='dynGen'>").text(userInput).attr("data-index", userInput);
$("#buttons").append(buttonU);
console.log(killersGifs.killerSearches);
}
};
killersGifs.buttonLoop();
$("#killer-add-submit").on("click", function(event) {
event.preventDefault();
killersGifs.userPush();
});
$(document).on("click", "button.dynGen", function(event) {
event.preventDefault();
$("#append-img-div").empty();
killersGifs.divLoop(event);
});
Clicking a button should return 10 images (still gifs) related to that word.
The console.log runs on click, but it is console logging an array of 10 for all 13 words as opposed to one array for the word clicked on.
response is an Object.
response.length is an undefined.
response.data is an Array.
If you want image also, Then you should append killerImg also.
var killersGifs = {
killerSearches: ["Freddy", "Jason", "Pennywise", "Ghost Face", "American Mary", "Chucky", "Bride of Chucky", "Candyman", "Cujo", "Hannibal", "Leatherface", "Michael Meyers", "Norman Bates", "Pinhead"],
buttonLoop: function() {
for (var b = 0; b < killersGifs.killerSearches.length - 1; b++) {
var buttonM = $("<button class='dynGen'>").text(killersGifs.killerSearches[b]).attr("data-index", killersGifs.killerSearches[b]);
$("#buttons").append(buttonM);
}
},
divLoop: function(event) {
for (var i = 0; i < killersGifs.killerSearches.length - 1; i++) {
//console.log(this.killerSearches[i]);
//var newDiv = $("<div class='gif-div'>");
var queryURL = "https://api.giphy.com/v1/gifs/search?api_key=B26sstJns2pZuNT5HiJpqS5FV8Su1sDd&q=" + killer + "&limit=10"
var killer = killersGifs.killerSearches[i];
//console.log(queryURL);
$.ajax({
url: queryURL,
method: "GET"
}).done(function(response) {
// console.log(response.data.length);
for (var x = 0; x < response.data.length - 1; x++) {
var respData = response.data[x];
var image = respData.images.fixed_height_small_still.url;
var rating = respData.rating;
var dynDiv = $("<div class='dyn-div'></div>");
var killerImg = $("<img>");
killerImg.attr("src", image);
killerImg.attr("alt", "Serial Killer still frame of gif");
dynDiv.append("Rating: " + rating);
dynDiv.append(image);
$("#append-img-div").prepend($(dynDiv).append($(killerImg)));
};
});
};
},
userPush: function() {
var userInput = $("input[type='text']").val().trim();
console.log(userInput);
killersGifs.killerSearches.push(userInput);
console.log(killersGifs.killerSearches);
}
};
killersGifs.buttonLoop();
$("#killer-add-submit").on("click", function(event) {
event.preventDefault();
killersGifs.userPush();
});
$(document).on("click", "button.dynGen", function(event) {
event.preventDefault();
$("#append-img-div").empty();
killersGifs.divLoop(event);
});
<script src="https://code.jquery.com/jquery-3.2.1.js" integrity="sha256-DZAnKJ/6XZ9si04Hgrsxu/8s717jcIzLy3oi35EouyE=" crossorigin="anonymous"></script>
<div id="buttons"></div>
<form id="killer-form">
<label for="killer-input">Add a serial killer:</label>
<input type="text" id="killer-input"><br>
<input id="killer-add-submit" type="submit" value="Submit">
</form>
<div id="append-img-div"></div>
I am using only JavaScript to create buttons and need to add click handlers to the buttons that will replace the header with the contents of the buttons. I have been trying to figure out how to do this for a while. Any help would be great! Thank you!
Below is my JavaScript code that creates the buttons and header.
var col = document.createElement('div');
col.className = 'col';
document.body.appendChild(col);
var header = document.getElementById('col');
var h = document.createElement("H3");
h.innerHTML = "Nothing clicked yet!";
col.appendChild(h);
var divOne = document.createElement('div');
col.appendChild(divOne);
var btnOne = document.getElementById('col');
var textOne = ["1", "2", "3", "4"];
textOne.forEach(function(post) {
var postDiv = document.createElement("div");
postDiv.className = 'btn btn-default';
postDiv.innerHTML = post;
col.appendChild(postDiv);
});
Add an event to your button elements, but as other answers pointed out, a good practice is to assign IDs to your elements for more accurate lookup :
var btnOne = document.getElementById('col');
var textOne = ["Left", "Middle", "Right"];
textOne.forEach(function(post) {
var btnGroupFour = document.createElement('button');
btnGroupFour.className = 'btn btn-default';
btnGroupFour.innerHTML = post;
btnGroupFour.addEventListener("click", function() {
var header = document.getElementsByTagName('H3')[0];
header.innerHTML = this.innerHTML;
}, false);
divThree.appendChild(btnGroupFour);
});
First of all, you are not creating buttons, you're creating divs, although you're using the button classes from bootstrap (I gues...).
Anyway, the way to proceed would be to add a onclick attribute with a callback function, witch takes one argument: the event itself. Then, with the target attribute of the event object, you're getting access to the event source tag and with value you will get the value.
Just like this:
<input type="button" id="button" value="Test Value!" />
<span id="output"></span>
<script>
document.getElementById("button").addEventListener('click', callback);
function callback(e) { document.getElementById("output").innerHTML = e.target.value; }
</script>
Just assign an ID for your header, and while creating the buttons in the loop. Just assign the onclick callback of the button, to get the id of the header, and replace the text
textOne.forEach(function(post) {
var btnGroupFour = document.createElement('button');
btnGroupFour.className = 'btn btn-default';
btnGroupFour.innerHTML = post;
btnGroupFour.onclick = function(){document.getElementById('headerID').innerHTML = post} ;
h.appendChild(btnGroupFour);
});
Should Work for your situation.
A short Demo
Fairly simple, just add an eventListener onto the element during creation. All I really had to add to your code was: .addEventListener("click", function(){ h.innerHTML = post;});
http://www.w3schools.com/jsref/met_element_addeventlistener.asp
<!DOCTYPE html>
<html>
<body>
<p>Hover over the checkbox to simulate a mouse-click.</p>
<script>
var divContainer = document.createElement('div');
divContainer.className = 'container';
document.body.appendChild(divContainer);
var row = document.createElement('div');
row.className = 'row';
divContainer.appendChild(row);
var col = document.createElement('div');
col.id = 'col-md-12';
row.appendChild(col);
var header = document.getElementById('col');
var h = document.createElement("H3");
h.innerHTML = "Nothing clicked yet!";
col.appendChild(h);
var star = document.createElement('div');
col.appendChild(star);
var btnStar = document.getElementById('col');
var textStar = ["Star"];
textStar.forEach(function(post) {
var postStar = document.createElement("div");
postStar.className = 'btn btn-default';
postStar.innerHTML = post;
postStar.addEventListener("click", function(){
h.innerHTML = post;});
col.appendChild(postStar);
});
var secondLine = document.createElement("HR");
document.body.appendChild(secondLine);
col.appendChild(secondLine);
var divOne = document.createElement('div');
col.appendChild(divOne);
var btnOne = document.getElementById('col');
var textOne = ["1", "2", "3", "4"];
textOne.forEach(function(post) {
var postDiv = document.createElement("div");
postDiv.className = 'btn btn-default';
postDiv.innerHTML = post;
postDiv.addEventListener("click", function(){
h.innerHTML = post;});
col.appendChild(postDiv);
});
var btnTwo = document.getElementById('col');
var textTwo = ["5", "6", "7", "8"];
textTwo.forEach(function(post) {
var btnGroupFour = document.createElement('button');
btnGroupFour.className = 'btn btn-default';
btnGroupFour.innerHTML = post;
btnGroupFour.addEventListener("click", function(){
h.innerHTML = post;});
col.appendChild(btnGroupFour);
});
var secondLine = document.createElement("HR");
document.body.appendChild(secondLine);
col.appendChild(secondLine);
var divThree = document.createElement('div');
col.appendChild(divThree);
var btnOne = document.getElementById('col');
var textOne = ["Left", "Middle", "Right"];
textOne.forEach(function(post) {
var btnGroupFour = document.createElement('button');
btnGroupFour.className = 'btn btn-default';
btnGroupFour.innerHTML = post;
btnGroupFour.addEventListener("click", function(){
h.innerHTML = post;});
divThree.appendChild(btnGroupFour);
});
</script>
</body>
</html>