So, I'm currently working on a HTML page that displays a table with an editable text box and a delete button for the row for every quote in a list. The list is fetched from a stored file, so I need to dynamically generate this table and its rows every time I fetch it. However, when this code runs, the table generated is empty, because when the listener is added, the delete row function executes and just removes the row right after it's added.
for (var i = 0; i < quotesArray.length; i++) {
//Insert a new row into the table.
var newQuoteRow = quoteList.insertRow(-1);
var cellOne = newQuoteRow.insertCell(0);
var cellTwo = newQuoteRow.insertCell(1);
//Insert editable text boxes for a quote into the row.
var quoteInput = document.createElement('input');
quoteInput.value = quotesArray[i];
quoteInput.className = "quote";
cellOne.appendChild(quoteInput);
//Put a delete button at the end of the row.
var deleteQuoteButton = document.createElement('button');
deleteQuoteButton.innerHTML = "x";
cellTwo.appendChild(deleteQuoteButton);
deleteQuoteButton.addEventListener('click', deleteCurrentQuoteRow(deleteQuoteButton));
}
});
}
function deleteCurrentQuoteRow(buttonToDelete) {
var currentRow = buttonToDelete.parentNode.parentNode; //get the grandparent node, which is the row containing the cell containing the button.
currentRow.parentNode.removeChild(currentRow); //delete the row in the table
}
From what I understand, this problem occurs because the function linked to in the addEventListener method has a parameter, which causes it to execute immediately instead of waiting for a click. However, I can't think of a way to implement this without passing the button being clicked as the parameter, because then I won't know which row to delete. How can I fix this so that the table will actually populate, and the delete button will actually delete a row?
Currently you are invoking the function deleteCurrentQuoteRow and assigning its return value which is undefined as event listener.
Use
deleteQuoteButton.addEventListener('click', function(){
deleteCurrentQuoteRow(this); //Here this refers to element which invoke the event
});
OR, You can modify the function deleteCurrentQuoteRow as
function deleteCurrentQuoteRow() {
var currentRow = this.parentNode.parentNode; //get the grandparent node, which is the row containing the cell containing the button.
currentRow.parentNode.removeChild(currentRow); //delete the row in the table
}
Then you can just pass the function reference as
deleteQuoteButton.addEventListener('click', deleteCurrentQuoteRow);
Related
I'm trying to loop through an array until it matches the value of the object that is clicked.
When the object is created the text input box shares it's value with the object and the array. I would like to be able to loop through the array until there is a match, then find the index, after that pass the index value to a variable to be used. From there remove the object that is clicked from the webpage and the array.
Additional details are that there is an input box with a button. The user enters a line of information into the input box and selects a button to appendChild it to the list. The object created is a div with the input value as the paragraph with a span element with an X which is supposed to remove the object when clicked.
Here is the HTML Code being used
<div id="outerDiv">
<div id="taskList">
</div>
</div>
Here is the code to create the object.
var magicArray = [];
function makeOutline() {
var textValue = document.getElementById("inputBox").value;
if (textValue == "" || textValue == null){
alert("Please enter a item you want to add to the to-do list");
} else {
var inputField = document.getElementById("taskList");
var inputText = document.createTextNode(textValue);
var mainHeading = document.createElement("p");
mainHeading.setAttribute("class", "outlineBorder");
var spanText = document.createTextNode("x");
var spanBox = document.createElement("span");
spanBox.setAttribute("class", "close");
spanBox.setAttribute("onclick", "removeMe()");
var outlineList = document.createElement("div");
outlineList.setAttribute("value", textValue);
spanBox.appendChild(spanText);
mainHeading.appendChild(inputText);
mainHeading.appendChild(spanBox);
outlineList.appendChild(mainHeading);
inputField.appendChild(outlineList);
magicArray[magicArray.length] = textValue;
document.getElementById("inputBox").value = "";
}
}
Here is the code to remove the item.
I am able to have it set to a static number and work every time; however,
struggling to find a dynamic solution since there can be multiple objects.
function removeMe() {
var removeList = document.getElementById("taskList");
removeList.removeChild(removeList.childNodes[1];
}
Here is a screenshot of the family tree structure
First, you can use this to get the element. docs:
When the event handler is invoked, the this keyword inside the handler is set to the DOM element on which the handler is registered.
function removeMe()
{
// this refers to the item that invoked removeMe()
var removeList = document.getElementById("taskList");
removeList.removeChild(this.parentNode.parentNode);
}
Also, this is how you properly add event listeners
spanBox.addEventListener("click", removeMe);
Here is a working jsfiddle for you
I currently have a jQuery Datatable, which upon a row being clicked on, the data from that row is outputted to textboxes and select boxes. I'm trying to make it so whatever is entered into the textboxes, will be saved/entered into the selected row upon pressing the saverow button.
Here's my JSFiddle: JSFiddle
Javascript:
var table = $('#example').DataTable();
(function () {
var table = document.querySelector('#example');
var name = document.querySelector('#nameinput');
var format = document.querySelector('#formatinput');
var address = document.querySelector('#addressinput');
var report = document.querySelector('#reportinput');
var alarm = document.querySelector('#alarminput');
table.addEventListener('click', onTableClick);
function onTableClick (e) {
var tr = e.target.parentElement;
var data = [];
for (var td of tr.children) {
data.push(td.innerHTML);
}
name.value = data[0];
address.value = data[1];
format.value = data[2];
report.value = data[3];
alarm.value = data[4];
console.log(alarm.value);
}
$("#saverow").click(function() {
var table1 = $('#data-table').DataTable();
var data = [];
data[0] = name.value;
data[4] = alarm.value;
console.log(name.value);
console.log(alarm.value);
table1.draw(true);
});
})();`
With the saverow code, I thought by trying to make the columns equal to the value of the textbox, then redrawing the table would work. The console does have the correct output when you type something new into the textbox then pressing Save. I just cant figure out how to put that back into the selected row.
I'm not wanting to do the inline editing if possible. Trying to keep it in this format.
I don't know if this counts as an answer, but you're not actually doing anything with that data variable in the save row click. You take the datatable, do nothing to change it, and then redraw it. So it's not surprising nothing is happening.
See this change to your fiddle to get the rows adding:
https://jsfiddle.net/o92g9goL/14/
Primarily, you need to set the table and datatable into different arrays. Also do it inside the main function. Also you need to actually add this code:
datatable.row.add(data).draw(false);
As for the editing, you'll need to make sure that you don't just prepopulate it, but make an actual reference to that row, otherwise how will it know to update it?
I am trying to delete an array record based on what table row is clicked.
This function adds a button to a row and appends it to the end of the table
function addButtons(table, tr){
var delBtn = document.createElement("button");
delBtn.innerHTML = "×"
delBtn.onclick = deleteBu(tr)
tr.appendChild(delBtn);
table.children[1].appendChild(tr)
}
The function below is meant to delete an array record based on the row clicked. For example, in row 1, the first cell is "45". Based on this, the record is deleted if it is found in the array storageProblem.
Here is what I have so far. The issue is because I am using tr as the action listener, so simply clicking on the row will delete the row, it is not localized to the button. But using tr is the only way I have found to get the first td of a row.
function deleteBu(tr){
$(tr).click(function(){
var value=$(this).find('td:first').html();
for(i = 0; i < storageProblem.length; i++){
if(value == storageProblem[i][0]){
storageProblem.splice(i, 14)
loadCallProblemTable()
}
}
})
}
I'm not sure if I've understood your question right but maybe try this solution:
function deleteBu(x) {
var Index = $(x).closest('tr').index();
console.log("Row index: " + Index);
}
i have dynamic simple table like:
I try to get previous value cell when i click edit button.
Example: when i click first edit button that will alert('a1')
when i click second edit button that will alert('a2')
i try with
$('.edit').click(function(){
alert($(this).parents('tr').prev().children().eq(1).text());
});
it's working well with first edit button because previous row that has one row.
And it't not working with second edit button.
How can i do it (by dynamic previous row) http://jsfiddle.net/bWjbj/
ps: i'm working with next row with
alert($(this).parents('tr').nextAll(':eq(' + ($(this).parent().siblings().eq(0).attr("rowspan")-1) + ')').children().eq(1).text());
http://jsfiddle.net/mblase75/XGdkD/
The problem is that for the second Edit button, the previous table row isn't the row you want -- you want the row two more before that, because that's where the rowspans begin.
Or, to be general: you want the table row belonging to the previous Edit button. In the case of the first edit button, though, you just want the previous row.
So, in code:
$('.edit').click(function () {
var idx = $('.edit').index(this); // which Edit button is this?
if (idx > 0) { // first button
var $tr = $('.edit').eq(idx-1).closest('tr'); // previous row
} else { // not first button
var $tr = $(this).closest('tr').prev('tr'); // previous Edit button's row
}
var $td = $tr.find('td:nth-child(2)'); // second <td> of the row
alert($td.text());
});
Compact version of the same code:
$('.edit').click(function () {
var idx = $('.edit').index(this),
$tr = (idx) ? $('.edit').eq(idx-1).closest('tr') : $(this).closest('tr').prev('tr'),
$td = $tr.find('td:nth-child(2)');
alert($td.text());
});
I have a table that is built dynamically from a user specified query to a database and I want to give the user the option to edit the data from the generated HTML table. When the user double clicks on the row containing the data they want to edit, I have a new row appear underneath it with textboxes for them to submit new values. Right now, when the user clicks double clicks two rows, both rows of textboxes remain in the table and I want to delete the first row before the second shows up. My question is, what is a good was to find table rows containing textboxes so that I can perhaps use JavaScript's deleteRow() function?
I'm generating rows like so:
function editRow(row) {
var table = document.getElementById("data");
var newRow = table.insertRow(row.rowIndex + 1);
var cell;
for (var i = 0; i < row.childNodes.length; i++) {
cell = newRow.insertCell(i);
textBox = document.createElement("input");
textBox.type = "text";
textBox.placeholder = row.childNodes[i].innerHTML;
textBox.style.textAlign = "center";
textBox.style.width = "90%";
cell.appendChild(textBox);
}
}
and the only way I can I can think of doing it is something like (pseudo code):
for all table rows
if row.childNodes.innerHTML contains 'input'
deleteRow(index)
Thanks for the help
You could use jQuery. Assuming row is a DOM element, this should work:
var textBoxes = $("input:text", row);
i guess the easiest option would be to add the created rows to an array. This way you simply have to delete the rows inside the array and not iterate through the whole table.
I ended up doing the following:
function editRow(row) {
var table = document.getElementById("data");
clearExistingTextBoxes(table);
...
}
function clearExistingTextBoxes(table) {
var tBoxRow = table.getElementsByTagName("input");
if (tBoxRow.length > 0) {
tBoxRow = tBoxRow[0].parentNode.parentNode;
table.deleteRow(tBoxRow.rowIndex);
}
}
Assuming I'm only going to be clearing one row at a time.