How to delete HTML column with dynamic header <th> name - javascript

I have a script that able to add new column to a HTML table. When user press add group the header will become Group1, Group2 and so on.. Currently im adding a delete group function that able to delete all the added column. So now the problem is when I delete a column and add again a new column , the name Group(x) will not be reset.
For example:user add group1 and group2 after that he delete group2. The next time he press add group again, it will show group3 instead of group2
Image:
Expected Output: The column name should be reset whenever the column is deleted.
Html:
<table id="persons" border="1">
<thead id="theadID">
<tr>
<th>Name</th>
<th>sex</th>
<th>Message</th>
</tr>
</thead>
<tbody id="tbodyID">
<tr>
<td>Viktor</td>
<td>Male</td>
<td>etc</td>
</tr>
<tr>
<td>Melissa</td>
<td>Female</td>
<td>etc</td>
</tr>
<tr>
<td>Joe</td>
<td>Male</td>
<td>etc</td>
</tr>
</tbody>
</table>
<button onclick="javascript:appendColumn()">Add column</button>
<input type="button" onclick="deleteLastColumn();" value="do it"/>
Jquery& Javascript:
function deleteLastColumn() {
$('#persons tr').find('th:last-child, td:last-child').remove()
}
let groupNum = 1;
const tableEl = document.getElementById('persons');
// append column to the HTML table
function appendColumn() {
// open loop for each row and append cell
for (let i = 0; i < tableEl.rows.length; i++) {
createCell(tableEl.rows[i].insertCell(tableEl.rows[i].cells.length), i, 'col');
}
tableEl.rows[0].querySelector('td:last-child').textContent = 'Group' + groupNum;
groupNum++;
}
// create DIV element and append to the table cell
function createCell(cell, text, style) {
var div = document.createElement('div'), // create DIV element
txt = document.createTextNode(text); // create text node
div.appendChild(txt); // append text node to the DIV
div.setAttribute('class', style); // set DIV class attribute
div.setAttribute('className', style); // set DIV class attribute for IE (?!)
cell.appendChild(div); // append DIV to the table cell
}

maybe I'm missing it but I don't see the code which deletes ALL the cols, I only see one. But still the solution seems simple, just decrement the groupNum variable when you delete a col
function deleteLastColumn() {
$('#persons tr').find('th:last-child, td:last-child').remove()
groupNum--;
}

Related

HTML Table - Buttons for Up, Down and Delete

I am working on a project using HTML5, CSS3, Javascript and Bootstrap.
The current page I'm having issues with has an HTML Table that requires four main functionalities: add new row, move row up, move row down, delete row.
To be more specific, I need it to be able to:
Provide the user the option to add an IP range to a new row at the bottom of the table.
Provide the new IP Range with an order number that follows the previously defined order. (Example: if there are 10 IP Ranges listed, the new IP Range should have an order number of 11)
Provide user buttons in each row to move an IP Range up or down in order.
Provide the user the option to delete an IP Range.
Right now I can add IP Ranges to a new row at the bottom of the table. I can move rows up and down. I can also delete a row.
Currently my code requires me to select the row I plan to move before I move it, which is a feature I would like to remove.
What I need help with:
1. How can I remove the need to SELECT the row before doing these functionalities? Example: if the user presses the UP arrow in row 2, just move the IP Range from row 2 to row 1?
2. How can I automatically reorder the rows based on if a row is deleted? Example: if there exists an IP Range in the table, it should start with a value Order=1. Any subsequent IP Range rows 'n' should have a value of 1+n. If there are three IP Ranges in the table and the second IP Range is deleted, how can I ensure that the order will not be (1, 3) and instead (1, 2)?
Note: the information in the table in the example provided is static but I will be filling dynamically from database. I will not know beforehand how many IP Ranges there are.
code:
function SomeDeleteRowFunction() {
// event.target will be the input element.
var td = event.target.parentNode;
var tr = td.parentNode; // the row to be removed
tr.parentNode.removeChild(tr);
}
//This function adds a user-input IP Range to the end of table body
function addEndIPRanges() {
//Accessing table body
var table = document.getElementById("myTableBody");
//Insert row at end of table body (-1 appends)
var row = table.insertRow(-1);
//Insert 3 new cells into new row
var cell1 = row.insertCell(0);
var cell2 = row.insertCell(1);
var rowCount = table.rows.length;
cell1.innerHTML = rowCount;
cell2.innerHTML = document.getElementById('addIPRange').value;
}
"use strict";
const tbody = document.querySelector("#table tbody");
let selected = null;
tbody.addEventListener("click", function(e) {
let row = e.target.closest("tr");
if (row === selected) {
row.classList.toggle("selected")
selected = null;
} else {
if (selected) {
selected.classList.toggle("selected");
}
selected = row;
row.classList.toggle("selected");
}
});
function upNdown(direction) {
let up, down;
if (selected) {
up = direction == "up" ? selected : selected.nextElementSibling;
down = direction == "up" ? selected.previousElementSibling : selected;
if (up && down) {
tbody.insertBefore(up, down); // put up before down
var temp = up.firstElementChild.textContent; // swap first cells' text content
up.firstElementChild.textContent = down.firstElementChild.textContent;
down.firstElementChild.textContent = temp;
}
}
}
tr {
cursor: pointer
}
.selected {
background-color: red;
color: #fff;
font-weight: bold
}
<figure class="text-center mb-3">
<h1 class="display-5">IP Range Management</h1>
</figure>
<hr>
<input type='text' id='addIPRange' />
<button style="text-align: center;" onclick="addEndIPRanges()">Add IP Range</button>
<hr>
<h4 class="iprangetableheader" style="text-align: center;">IP Ranges</h4>
<table id="table" style="margin: auto; width: 75%;">
<thead>
<tr style="text-align: center;">
<th scope="col">Order</th>
<th scope="col">IP Range</th>
<th scope="col">Actions</th>
</tr>
</thead>
<tbody id="myTableBody">
<tr>
<td>1</td>
<td>255.255.255.255</td>
<td><button onclick="upNdown('up');">&ShortUpArrow;</button>
<button onclick="upNdown('down');">&ShortDownArrow;</button>
<input type="button" value="Delete Row" onclick="SomeDeleteRowFunction()">
</td>
</tr>
<tr>
<td>2</td>
<td>234.132.1.642</td>
<td><button onclick="upNdown('up');">&ShortUpArrow;</button>
<button onclick="upNdown('down');">&ShortDownArrow;</button>
<input type="button" value="Delete Row" onclick="SomeDeleteRowFunction()">
</td>
</tr>
<tr>
<td>3</td>
<td>24.32.2.25</td>
<td><button onclick="upNdown('up');">&ShortUpArrow;</button>
<button onclick="upNdown('down');">&ShortDownArrow;</button>
<input type="button" value="Delete Row" onclick="SomeDeleteRowFunction()">
</td>
</tr>
</tbody>
</table>
<hr>
Link to JS Fiddle: What I've got so far
It might look weird but it works:
You can send the clicked button as a parameter to the function and derive the row which it belongs to. That row is your required element.
const tbody = document.querySelector("#table tbody");
function upNdown(direction,button) {
// Here button parameter is getting the button which is clicked
// Its parent element is a td whose parent element is a tr which is to be moved and voila
let selected = button.parentElement.parentElement;
let up, down;
if (selected) {
up = direction == "up" ? selected : selected.nextElementSibling;
down = direction == "up" ? selected.previousElementSibling : selected;
if (up && down) {
tbody.insertBefore(up, down); // put up before down
var temp = up.firstElementChild.textContent; // swap first cells' text content
up.firstElementChild.textContent = down.firstElementChild.textContent;
down.firstElementChild.textContent = temp;
}
}
}
<table id="table" style="margin: auto; width: 75%;">
<thead>
<tr style="text-align: center;">
<th scope="col">Order</th>
<th scope="col">IP Range</th>
<th scope="col">Actions</th>
</tr>
</thead>
<tbody id="myTableBody">
<tr>
<td>1</td>
<td>255.255.255.255</td>
<td><button onclick="upNdown('up',this);">&ShortUpArrow;</button>
<button onclick="upNdown('down',this);">&ShortDownArrow;</button>
<input type="button" value="Delete Row" onclick="SomeDeleteRowFunction()">
</td>
</tr>
<tr>
<td>2</td>
<td>234.132.1.642</td>
<td><button onclick="upNdown('up',this);">&ShortUpArrow;</button>
<button onclick="upNdown('down',this);">&ShortDownArrow;</button>
<input type="button" value="Delete Row" onclick="SomeDeleteRowFunction()">
</td>
</tr>
<tr>
<td>3</td>
<td>24.32.2.25</td>
<td><button onclick="upNdown('up',this);">&ShortUpArrow;</button>
<button onclick="upNdown('down',this);">&ShortDownArrow;</button>
<input type="button" value="Delete Row" onclick="SomeDeleteRowFunction()">
</td>
</tr>
</tbody>
</table>
This is how you can maintain the index:
Add a class ip-row or whatever you want to all the tr elements which hold the ip.
Remember to give that class to only the elements which hold the ip otherwise it will index all the rows.
Take that class and insert the following code in the delete function and put it after you have removed the element like this-
function SomeDeleteRowFunction() {
// event.target will be the input element.
var td = event.target.parentNode;
var tr = td.parentNode; // the row to be removed
tr.parentNode.removeChild(tr);
// Select all trs
let trs = Array.from(tbody.querySelectorAll('.ip-row'))
// Start index
let index = 1;
trs.forEach((tr) => {
// For all trs give a value to its first td which holds the index
tr.querySelectorAll('td')[0].innerHTML = index;
// increment the index
index++
})
}

Populate a form text area on table row selection - Python Flask HTML

Need help with populating a text area based on html table row selection.
In the table below, I want to extract the content of the column 'Comments' for the selected row and write into the text area 'Comment' on the same page. I have only managed to create the table but nothing else.
Below is the code I have now created from this link. What is happening now is that only the currently selected cell gets put in the text box instead of just the 'Comment' column. I want to input only in the 'Comment' column into the box regardless of the cell clicked upon in the row.
<table id="table">
<tr>
<th>Name</th>
<th>Age</th>
<th>Comments</th>
</tr>
<tbody>
<tr>
<td>John</td>
<td>42</td>
<td>avery long comment</td>
</tr>
<tr>
<td>Peter</td>
<td>35</td>
<td>another very long comment</td>
</tr>
<tr>
<td>Mary</td>
<td>54</td>
<td>some comment</td>
</tr>
</tbody>
</table>
<script>
var table = document.getElementById('table');
var selected = table.getElementsByClassName('selected');
table.onclick = highlight;
function highlight(e) {
if (selected[0]) selected[0].className = '';
e.target.parentNode.className = 'selected';
var element = document.querySelectorAll('.selected');
if (element[0] !== undefined) { //it must be selected
document.getElementById("myTextbox").value = element[0].children[0].firstChild.data
}
}
</script>
<div >
<textarea class="form-control" id="myTextbox"></textarea>
</div>
Thanks for your help.
You're getting the first column but you can get the third column with the comment by changing the index of the child to 2 instead of 0.
document.getElementById("myTextbox").value = element[0].children[2].firstChild.data

Change button text of a cloned element

Making an food ordering app. There is a first table with all items you can choose. Each item have a button. On this button click it clones the line and put it in a second table containing your chosen items. I would like to change the text content of the button when the element go to the second table. Like "+" in the first table become "-" in the second table (to next delete the item of the second table on "-" click)
HTML
<h1>CHOOSE</h1>
<table id="starters">
<tr>
<th>PRODUCT</th>
<th>PRICE</th>
<th>ADD TO CART</th>
</tr>
<tr>
<td>Cherry</td>
<td>6</td>
<td><button class="item_button">+</button></td>
</tr>
<tr>
<td>Peach</td>
<td>8</td>
<td><button class="item_button">+</button></td>
</tr>
<tr>
<td>Strawberry</td>
<td>12</td>
<td><button class="item_button">+</button></td>
</tr>
</table>
<h1>YOUR CHOICE</h1>
<table id="products_cart">
</table>
JS
let basket = document.getElementById("products_cart")
let buttons = document.querySelectorAll('.item_button');
for (button of buttons) {
button.addEventListener('click', cloneLine);
}
function cloneLine(e) {
let td = e.target.parentNode;
let tr = td.parentNode;
let clone = tr.cloneNode(true);
basket.appendChild(clone);
}
I tried different things like to get (querySelectorAll) the buttons and change their innerHTML (or textContent or innerText) with no success. I also tried to create another button and to replace the former by the newer.

Jquery - Add Column left or right to previous Column

I have two buttons called "Add Column Left" and "Add Column Right". I need to get the Index of the clicked cell, so that I can get the column index and add the new column to the previous one.
My current code:
function AddColumn(addLeft){ // Which button is clicked? Add Left || Add Right
var header = $('#tableHeader'); // Get the table header element
var headerContentToAppend = "<th>Header</th>"; // The default text of the new header
var table = $('#tableBody'); // Get the table body element
var rowContentToAppend = "<td>Content</td>"; // The default text of the new cells
// issue 1: missing index of the clicked/focussed column
if (addLeft) { // Button "Add Column Left" clicked
header.prepend(headerContentToAppend); // Add the Column to the left of the previous column
}
else { // Button "Add Column Right" clicked
header.append(headerContentToAppend); // Add the Column to the right of the previous column
}
$('table th').last().attr("contenteditable", true).focus(); // set all cells editable and focus the last one
table.find("tr").each(function() { // Get all existing rows ....
// issue 2: maybe the cells don't match to the right column, I have to test this after finishing the first issue
$(this).append(rowContentToAppend); // ... and add cells to the new column
});
}
So my problem is to get the right index of the clicked column. After adding a new column i have to fill it up with new cells below.
I placed two comments called "issue" in the code, that should make things clear.
My HTML Code:
<table id="dataTable">
<thead id="tableHeader">
</thead>
<tbody id="tableBody">
</tbody>
</table>
I want to control the table by Javascript to keep it dynamic.
Since you're using jQuery you could use the method index() to get the element index :
var index = $(this).closest('tr').find('td').index($(this));
Hope this helps.
var index = 0;
function AddColumn(addLeft){
var header = $('#tableHeader');
var headerContentToAppend = "<th>Header</th>";
var table = $('#tableBody');
var rowContentToAppend = "<td>Content</td>";
if (addLeft)
header.find('th').eq(index).before(headerContentToAppend);
else
header.find('th').eq(index).after(headerContentToAppend);
$('table th').attr("contenteditable", true).last().focus();
table.find("tr").each(function() {
if (addLeft)
$(this).find('td').eq(index).before(rowContentToAppend);
else
$(this).find('td').eq(index).after(rowContentToAppend);
});
$('td').removeClass('selected');
}
$('body').on('click','td',function(){
$('td').removeClass('selected');
$(this).addClass('selected');
index = $(this).closest('tr').find('td').index($(this));
});
.selected{
background-color: grey;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table border="1">
<thead id='tableHeader'>
<th>Header 1</th>
<th>Header 2</th>
<th>Header 3</th>
</thead>
<tbody id='tableBody'>
<tr>
<td>column 1</td>
<td>column 2</td>
<td>column 3</td>
</tr>
<tr>
<td>column 11</td>
<td>column 22</td>
<td>column 33</td>
</tr>
<tr>
<td>column 111</td>
<td>column 222</td>
<td>column 333</td>
</tr>
</tbody>
</table>
<br>
<button onClick='AddColumn(true)'>< Add to the Left</button>
<button onClick='AddColumn(false)'>Add to the Right ></button>

javascript get external table row on click

I have a button:
<button id="external-list-row">Test</button>
in which I would like to change with a row from an external table on click. The external table is structured like this;
<table id="table_id">
<thead>
<tr>
<th>X</th>
<th>Y</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>Row 1</p>
</td>
</tr>
<tr>
<td>
<p>Row 2</p>
</td>
</tr>
<tr>
<td>
<p>Row 3</p>
</td>
</tr>
</tbody>
</table>
So my question is this; how can I replace "Test" in the button with the content of Row 1 with javascript?
As for the javascript, I'm not sure how I can get the content from row 1, and replace the button with it.
<script>
var rows = document.getElementById('table_id').getElementsByTagName("tr");
for (var i=0; i<rows.length; i++) {
$('#external-list-row').onclick = function() {
}};
</script>
Post comments:
I can access table data from other tables within the same html file, but I still don't know how to access data from tables in other html files. For example, if I try to access a videos liquid file from another liquid file, like photos, nothing happens when I press the button.
Fiddle of current code. It can replace the content of a list with the content of another, but the lists need to be on the same html file.
https://jsfiddle.net/hgnymydL/
Well, the first thing you should understand, is that a table element has a rows property, so getting the first row is trivial.
var table = document.getElementById("table_id");
var firstRow = table.rows[0];
From there, you can use textContent to get the text content of the row. I believe that's what you were looking for.
You can also select the first row of a table with a CSS selector like so:
var firstRow = document.querySelector("#table_id tbody tr");
$('#external-list-row').on('click', function() {
$(this).text($('#table_id tbody tr:first').text());
});
If you want to replace the button text with contents of the First Row ONLY then:
$('#external-list-row').html($('tr:first-child').html);
Of course you could wrap this in any event, so for example, on clicking the button:
$('#external-list-row').on('click', function() {
$(this).html($('tr:first-child').text());
});
BUT, based on the code you have given, I'm assuming you want to change the text after each click in which case you could do this:
var clickNumber = -1;
$('#external-list-row').on('click', function(event) {
clickNumber = clickNumber + 1;
//console.log('\n\nclickNUmber' + clickNumber);
$('tbody tr').each(function(index, el) {
//console.log('index: ' + index);
var block = $(el).find('td p');
if(index == clickNumber) {
//console.log('entered if')
//console.log(block.text());
//console.log('----clickNUmber' + clickNumber);
//console.log('index: ' + index);
//console.log(el);
$('#external-list-row').html(block.text());
}
});
});
jsFiddle: https://jsfiddle.net/zmb2b37t/
Hope that helps!
If you are wanting to replace the visible text "Test" in the button with the content of the cell clicked:
var tbl = document.getElementById('table_id');
var btn = document.getElementById('external-list-row');
tbl.onclick = function(ev){
var trgt = ev.target;
if(trgt.tagName === 'P' ||trgt.tagName === 'TD'){
btn.textContent = trgt.textContent;
}
};
Only one event handler is attached in this scenario.
Via event delegation we determine if it was a TD or P element that was clicked. If the rows are modified the function will still work.
Here is jquery code of do this
$('#table_id tr td').on('click', function(){
$('#external-list-row').html($(this).html());
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="external-list-row">Test</button>
<table id="table_id">
<thead>
<tr>
<th>X</th>
<th>Y</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<p>Row 1</p>
</td>
</tr>
<tr>
<td>
<p>Row 2</p>
</td>
</tr>
<tr>
<td>
<p>Row 3</p>
</td>
</tr>
</tbody>
</table>

Categories