In this code, I am trying to push items into the array and then removing them.
If you see below, the create button will give me a blank input and a button that stores it into an array. After it is pushed into the array, the view button goes through the array and displays all the items with the buttons "edit" and "delete" beside it. This is where my problem lies... for each item that is put into the array, it displays it on the Html and has its own buttons. How do I delete that item from the array when I click on a specific delete button?
//variables
var create = document.getElementById("create");
var view = document.getElementById("view");
var display = document.getElementById("display");
var text = document.getElementById("text");
var push = document.getElementById("push");
var arr1 = [];
//create button
create.onclick = function () {
text.style.display = "inline";
push.style.display = "inline";
}
//push button
push.onclick = function () {
arr1.push(text.value);
push.dataset.u_index;
console.log(arr1);
text.value = "";
}
//view button
view.onclick = function () {
for (var i = 0; i < arr1.length; i++) {
var disp = document.createElement("div");
disp.innerHTML = arr1[i];
display.appendChild(disp);
var edit = document.createElement("button");
var edit_t = document.createTextNode("Edit");
disp.appendChild(edit);
edit.appendChild(edit_t);
var del = document.createElement("button");
var del_t = document.createTextNode("Delete");
disp.appendChild(edit);
edit.appendChild(edit_t);
disp.appendChild(del);
del.appendChild(del_t);
}
//del button
del.onclick = function () {
}
}
}
You need some way of identifying the element you want to delete so it can be tied to the delete function. Here's some code that shows one possible way using data attributes.
//variables
var create = document.getElementById("create");
var view = document.getElementById("view");
var display = document.getElementById("display");
var text = document.getElementById("text");
var push = document.getElementById("push");
var results = document.getElementById("results");
var arr1 = [];
//create button
create.onclick = function() {
text.style.display = "inline";
push.style.display = "inline";
}
//push button
push.onclick = function() {
arr1.push(text.value);
push.dataset.u_index;
console.log(arr1);
text.value = "";
}
//view button
view.onclick = function() {
for (var i = 0; i < arr1.length; i++) {
var disp = document.createElement("div");
disp.innerHTML = arr1[i];
results.appendChild(disp);
var edit = document.createElement("button");
var edit_t = document.createTextNode("Edit");
disp.appendChild(edit);
edit.appendChild(edit_t);
var del = document.createElement("button");
var del_t = document.createTextNode("Delete");
disp.appendChild(edit);
edit.appendChild(edit_t);
disp.appendChild(del);
del.appendChild(del_t);
del.setAttribute('data-item-index', i);
//set onclick fn for del button
del.onclick = function() {
var itemIndex = this.getAttribute('data-item-index');
arr1.splice(itemIndex, 1);
console.log(arr1);
results.innerHTML = '';
view.click();
};
}
}
<div id='display'>
<button id="create">Create</button>
<div>
<input type="text" id='text'>
<button id='push'>Push</button>
</div>
<button id='view'>View</button>
<div id='results'></div>
</div>
Related
I have a function that adds badges to a div by selecting items from a dropdown list.
I'm adding badges using this function added to the dropdown list onclick event:
function addBadge(parent, badgeId, value){
var elem = document.getElementById(parent);
var currentTaxiways = elem.children;
var alreadyExists = false;
for(var i = 0; i < currentTaxiways.length; i++){
if(badgeId === currentTaxiways[i].id){
alreadyExists = true;
}
}
if(!alreadyExists) {
var newBadge = document.createElement("span");
newBadge.classList.add("badge");
newBadge.classList.add("badge-primary");
newBadge.classList.add("bg-secondary");
newBadge.id = badgeId;
var node = document.createTextNode(value);
newBadge.appendChild(node);
newBadge.innerHTML += " ";
var deleteButton = document.createElement("a");
deleteButton.href = "#";
deleteButton.classList.add("x-btn");
deleteButton.onclick = function delBadge() {
deleteBadge(newBadge.id);
};
var node2 = document.createTextNode("X");
deleteButton.appendChild(node2);
newBadge.appendChild(deleteButton);
elem.appendChild(newBadge);
}
}
And the function for deleting the badges is this one:
function deleteBadge(badge){
var elem = document.getElementById(badge);
elem.parentNode.removeChild(elem);
}
How do I send the list of ids of all the badges added to the div to my controller using thymeleaf when the form is submitted?
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 trouble with this piece of code. When I click it once, all is good and the behavior is as designed , but when I click it more than once, then there is all bunch of HTML that appears in the div (text area). How should I revise my JS to make it not happen?
HTML :
<div id="transcriptText">Lorem ipsum dolor sit amet </div>
<br>
<div id="divideTranscript" class="button"> Transform the Transcript! </div>
JS :
window.onload = function() {
var transcriptText = document.getElementById("transcriptText");
var newTranscript = document.createElement("div");
var divideTranscript = document.getElementById("divideTranscript");
divideTranscript.onclick = EventHandler;
function EventHandler() {
changeText();
}
function changeText() {
var sArr = transcriptText.innerHTML.split(" ");
transcriptText.innerHTML = "";
console.log(sArr);
var count = 0;
for (var i = 0; i < sArr.length; i++) {
var item = sArr[i];
var newSpan = document.createElement("span");
var newText = document.createTextNode(item);
var dotNode = document.createTextNode(" ");
newSpan.id = "word" + i;
var mouseOverFunction = function () {
this.style.backgroundColor = 'yellow';
};
newSpan.onmouseover = mouseOverFunction;
var mouseOutFunction = function () {
this.style.backgroundColor = '';
};
newSpan.onmouseout = mouseOutFunction;
newSpan.appendChild(newText);
newSpan.appendChild(dotNode);
transcriptText.appendChild(newSpan);
count++;
};
}
};
Here is it live http://jsfiddle.net/b94DG/1/
The main problem is that you use the innerHTML property instead of the .textContent property each time.
Here is an improved version of changeText() that doesn't matter how many times you run it:
function changeText() {
var sArr = transcriptText.textContent.split(/\s+/g); // changed
transcriptText.innerHTML = "";
var count = 0;
for (var i = 0; i < sArr.length; i++) {
var item = sArr[i];
if (!item) continue; // changed: don't add spans for empty strings
var newSpan = document.createElement("span");
var newText = document.createTextNode(item);
var dotNode = document.createTextNode(" ");
newSpan.id = "word" + i;
var mouseOverFunction = function () {
this.style.backgroundColor = 'yellow';
};
newSpan.onmouseover = mouseOverFunction;
var mouseOutFunction = function () {
this.style.backgroundColor = '';
};
newSpan.onmouseout = mouseOutFunction;
newSpan.appendChild(newText);
newSpan.appendChild(dotNode);
transcriptText.appendChild(newSpan);
count++;
};
}
I have made a simple dynamic form to generate input boxes.
<body>
<div id="main1">
<input type="button" onclick="addSelectBox ()" name="clickme" value="+"/>
<input type="button" onclick="removeSelect();" value="-"/>
<input type="button" onclick="xmlData();" value="XML" />
</div>
<div id="main">
</div>
</body>
Here's the javascript code:
(function () {
var selele=0;
var brindex=0;
function addSelectBox() {
selele = selele + 1;
var spantag = document.createElement("span");
spantag.setAttribute("id", selele);
var parentDiv = document.getElementById("main");
var selectElement = document.createElement("select");
var selectElement1 = document.createElement("select");
var selectElement2 = document.createElement("select");
var selectElement3 = document.createElement("select");
var arr = new Array("Stocks", "MutualFunds");
var arr2 = new Array("individual", "401k", "IRA");
var arr3 = new Array("contains", "equals");
var arr4 = new Array("scrapedaccounttype", "scrapedtransactiontype");
var textbox = document.createElement('input');
for (var i = 0; i < arr.length; i++) {
var option = new Option(arr[i]);
selectElement.options[selectElement.options.length] = option;
}
for (var i = 0; i < arr2.length; i++) {
var option = new Option(arr2[i]);
selectElement1.options[selectElement1.options.length] = option;
}
for (var i = 0; i < arr3.length; i++) {
var option = new Option(arr3[i]);
selectElement2.options[selectElement2.options.length] = option;
}
for (var i = 0; i < arr4.length; i++) {
var option = new Option(arr4[i]);
selectElement3.options[selectElement3.options.length] = option;
}
spantag.appendChild(selectElement);
spantag.appendChild(selectElement1);
spantag.appendChild(selectElement2);
spantag.appendChild(selectElement3);
spantag.appendChild(textbox);
parentDiv.appendChild(spantag);
linebreak();
};
function removeSelect() {
var parentDiv = document.getElementById("main");
var removetg = document.getElementById(selele);
if (selele != 1) {
parentDiv.removeChild(removetg);
selele = selele - 1;
} else {
parentDiv.removeChild(removetg);
parentDiv.innerHTML = "";
selele = selele - 1;
}
removeBreak();
};
function linebreak() {
brindex = brindex + 1;
var brtag = document.createElement("br");
brtag.setAttribute("id", brindex);
var parentDiv = document.getElementById("main");
parentDiv.appendChild(brtag);
};
function linespace() {
var myElement = document.createElement("span");
myElement.innerHTML = "           ";
var parentDiv = document.getElementById("main");
parentDiv.appendChild(myElement);
};
function removeBreak() {
var myElement = document.getElementById(brindex);
var parentDiv = document.getElementById("main");
brindex = brindex - 1;
parentDiv.removeChild(myElement);
};
function xmlData() {
xmlDoc = loadXMLDoc("data.xml");
newel = xmlDoc.createElement("edition");
x = xmlDoc.getElementsByTagName("span")[0];
x.appendChild(newel);
};
});
I can't get it to work on jsFiddle, the buttons don't work.
They work fine if I embed it in a tag.
Can anybody help me fix them.
EDIT: I guess i added anonymously because I wanted the var selele and brindex globally for all these functions.
I have made the code changes.
JSFIDDLE
Your functions are within an anonymous function and thus not available from outside.
First remove the code from the anonymous function (see here: http://jsfiddle.net/uH84W/6/), then fix the console errors you get (I assume that's not the whole code).
function addSelectBox() {...
In your fiddle you select onload but you change onload to no warp-in or no warp-in now it's work fine
So I have this piece of code:
window.onload = function () {make_buttons ('calc'); }
function make_buttons (id) {
console.log (id);
var input = document.createElement("INPUT");
document.getElementById(id).appendChild(input);
for (var i = 0;i < 10; i++){
var btn = document.createElement ("BUTTON");
var t = document.createTextNode (i);
btn.appendChild(t);
document.getElementById(id).appendChild(btn).onclick=document.getElementsByTagName("INPUT").value=i;
}
};
Now when I have created the button with the for loop, it should also have the onclick event attached to it which writes the current value of i into my input form.
Code I have written produces no errors but when the button is clicked, it simply does not do anything. Why is that?
New version:
window.onload = function () {make_buttons ('calc'); }
function make_buttons (id) {
var input = document.createElement("input");
input.type = 'text';
input.id = 'inp';
document.getElementById(id).appendChild(input);
for (var i = 0;i < 10; i++){
var btn = document.createElement ("button");
btn.id = i;
var txt = document.createTextNode (i);
btn.appendChild(txt);
var make_btn = document.getElementById(id).appendChild(btn);
make_btn.onclick = button_pressed (i);
}
};
function button_pressed (id) {
document.getElementById("inp").value += id;
};
Method document.getElementsByTagName() returns a NodeList collection that you should iterate through.
You need to go in loop through retrieved elements and assign the value attribute to each of them.
So that you can change
document.getElementById(id).appendChild(btn).onclick=document.getElementsByTagName("INPUT").value=i;
to something like this:
var id = 'my-form',
btn = document.createElement('input');
btn.type = 'button';
btn.value = 'Click me!';
btn.onclick = function() {
var inputs = document.getElementsByTagName('input');
// NodeList to Array if needed:
// var inputsArray = Array.prototype.slice.call(inputs);
for(var i = 0, l = inputs.length; i < l; i++) {
inputs[i].value = i;
}
return false;
};
document.getElementById(id).appendChild(btn);
DEMO #1
Update:
About your second question, yes it won't work in this way since at the time when your onclick event handler is called it's using the last value assigned to i variable. To avoid this you can just use closures.
For example,
HTML:
<form action="" id="my-form">
<input type="text" id="inp" />
</form>
JavaScript:
var btn,
input,
form,
createHandler;
input = document.getElementById('inp');
form = document.getElementById('my-form');
createHandler = function(i) {
return function() {
input.value += i;
};
};
for(var i = 0; i < 5; i++) {
btn = document.createElement('input');
btn.type = 'button';
btn.value = 'Append ' + i;
form.appendChild(btn);
btn.onclick = createHandler(i);
}
DEMO #2
Also you can use just immediately invoked anonymous function to create that closure in the body of your loop:
for(var i = 0; i < 5; i++) {
// ...
btn.onclick = (function(theNumberToAppend) {
return function() {
input.value += theNumberToAppend;
};
})(i);
}
DEMO #3