Renaming ID of all child elements after dynamically deleting line in table - javascript

I created a form in Google Apps Script, to send data to a sheet, but I wanted a way to dynamically add rows by clicking a button. I found this article (https://www.geeksforgeeks.org/how-to-dynamically-add-remove-table-rows-using-jquery/) that uses jquery that works well great, even shows how to delete a line, whilst also renaming the <tr> tag id to the correct number as well as the text content of the first <td> tag.
However, I added an autocomplete input using materialize, and thought I could use the same method to change the <input> ID when deleting a row, but, seem to be failing miserably.
To see what I'm talking about, I'd invite you to run the code snippit, and add a few rows. If you delete any of the rows (apart from the last one), then all the Row numbers go down by one, the <tr> tag ids go down by one, but the <input> tag ids don't.
I apologize if my query isn't clear, and would be happy to try and explain more, if needed.
Here is all the code to recreate the project in a "normal" code editor :
JS in first snippit, html in second
let rowIdx = 1;
//This list would be generated from a google sheet on page load for the autocomplete input
let listRecettes = {
"Banana": null,
"Orange": null,
"Mango": null,
}
//ON LOAD
document.addEventListener('DOMContentLoaded', function() {
var elems = document.querySelectorAll('.autocomplete');
var instances = M.Autocomplete.init(elems);
// Load words into autocomplete
populateWordsRecettes();
});
//Autocomplete initialize
function populateWordsRecettes() {
var autocomplete = document.getElementById("recettes1");
var instances = M.Autocomplete.init(autocomplete, {
data: listRecettes
});
}
//autocomplete initialize for added rows
function newLineAutocomplete() {
var autocomplete = document.getElementById(`recettes${rowIdx}`);
var instances = M.Autocomplete.init(autocomplete, {
data: listRecettes
});
console.log(`Row ${rowIdx} initialized`);
}
document.getElementById('btnAjouterLigne').addEventListener('click', addLine);
function addLine() {
// jQuery button click event to add a row.
// Adding a row inside the tbody.
$('#tableBodyCasse').append(`<tr id="R${++rowIdx}">
<td class = "row-index">Row ${rowIdx}</td>
<td><div class = "input-field"><input type="text" id="recettes${rowIdx}" class="autocomplete"></div></td>
<td>Lorum Ipsum</td>
<td>Lorum Ipsum</td>
<td>Lorum Ipsum</td>
<td><button class="btn waves-effect red darken-4 waves-light btnSupprimerLigne">Delete</button></td>
</tr>`);
//Initialize the autocomplete for new row
newLineAutocomplete();
}
//delete line
$('#tableBodyCasse').on('click', '.btnSupprimerLigne', function() {
// Getting all the rows next to the
// row containing the clicked button
let child = $(this).closest('tr').nextAll();
// Iterating across all the rows
// obtained to change the index
child.each(function() {
// Getting <tr> id.
let id = $(this).attr('id');
// Getting the <p> inside the .row-index class.
let idx = $(this).children('.row-index');
// Gets the row number from <tr> id.
let dig = parseInt(id.substring(1));
// Modifying row index.
idx.html(`Row ${dig - 1}`);
// Modifying row id.
$(this).attr('id', `R${dig - 1}`);
});
//MY PROBLEM STARTS HERE
let childInput = $(this).find('input').nextAll();
childInput.each(function() {
let idInput = $(this).attr('id');
let digInput = parseInt(idInput.substring(9));
console.log(digInput);
$(this).attr('id', `recettes${digInput - 1}`);
});
// Removing the current row.
$(this).closest('tr').remove();
// Decreasing the total number of rows by 1.
rowIdx--;
});
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js">
</script>
</head>
<body>
<div class="container">
<!-- CONTAINER START -->
<table class="striped">
<thead>
<tr>
<th>Row num</th>
<th>Product</th>
<th>Type</th>
<th>Qty</th>
<th>Total</th>
<th>Delete line</th>
</tr>
</thead>
<tbody id="tableBodyCasse">
<tr id="R1">
<td class="row-index">Row 1</td>
<td>
<div class="input-field"><input type="text" id="recettes1" class="autocomplete"></div>
</td>
<td>unknown</td>
<td>2</td>
<td>5,4</td>
<td><button class="btn waves-effect red darken-4 waves-light btnSupprimerLigne">Delete</button>
</td>
</tr>
</tbody>
</table>
<button class="btn waves-effect waves-light" id="btnAjouterLigne">Add line
<i class="material-icons left">add_circle_outline</i>
</button>
</div>
<!--CONTAINER END -->
<?!= include("page-casse-js"); ?>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
</body>
</html>

Related

Dynamically add rows and run the script

I have a table that's creating rows dynamically upon button click. This input box contains an auto suggest script. When , I am trying to perform an input on the the first box(the one that is default created) , the auto complete works fine. But, on performing the dynamic adding of the row, the script for that row doesn't work. How to invoke the auto complete script on the new ?
<html>
<body>
<div id="addButtonDiv">
<button id="add" >Add New</button>
</div>
<table id="tableAdd">
<head>
<tr>
<th >enter</th>
</tr>
</head>
<body>
<tr>
<td>
{!! Form::text('nameId', null,['class'=>'form-control auto', 'placeholder' => 'name']) !!}
</td>
</tr>
</body>
</table>
<script type="text/javascript">
$(document).ready(function ()
{
$("#add").click(function()
{
$('#tableAdd tr:last').after('<tr><td>{!! Form::text('project_manager_name', null,['class'=>'form-control pmID', 'placeholder' => 'Project Manager']) !!}</td></tr>')
});
});
$(".auto")
.on("keydown", keyDownEventForProjectAndCompetencyLead)
.autocomplete(
{
//function that autocompletes the input
});
</script>
</body>
</html>
Jquery sometimes has a little trouble identifying elements that have been programatically added to the DOM just by the original class / id. Try using a different selector method to check against the modified page:
$(document)
.on("keydown", ".auto", keyDownEventForProjectAndCompetencyLead)
.autocomplete( // etc )
Your selector isn't applying to DOM elements added after the page is loaded.
Modify as above to listen on all element in document that match, or attach listener on each new element created:
<html>
<body>
<button id="add">add</button>
<table id="cooltable">
<tr>
<td>cool table cell</td>
</tr>
</table>
<script type="text/javascript">
function autoPopulate(event){
// some code
event.currentTarget.value = "auto populated content";
}
let add_button = document.getElementById('add');
add_button.addEventListener('click',(event)=>{
let new_row = document.createElement('tr'); // create row
let new_cell = document.createElement('td'); // create cell
let new_input = document.createElement('input'); // create input
new_input.type = 'text';
new_input.value = "default content";
new_input.addEventListener('keydown', (event)=>{ // attach listener
autoPopulate(event);
});
new_cell.appendChild(new_input) // add input to cell
new_row.appendChild(new_cell) // add cell to row
document.getElementById('cooltable').appendChild(new_row); // add row to table
})
</script>
</body>
</html>
Problem here is you are adding callback on "keyDown" event which is not happening hence your script is not running
To fix this you should add eventlistener on jquery load()
Or you should using .bind('DOMNodeInserted DOMNodeRemoved') to call function when new node are added or deleted.
<div id='myParentDiv'> </div>
<button>Click </button>
$("button").click(function(){
$("#myParentDiv").append("<div class='test'></div>");
});
$("#myParentDiv").bind("DOMNodeInserted",function(){
alert("child is appended");
});
Here is working demo
https://jsfiddle.net/vickykumarui/28edcsmb/
Code for Table Example
<div id="addButtonDiv">
<button id="add" >Add New</button>
</div>
<table id="tableAdd">
<head>
<tr id = "test1">
<th >enter</th>
</tr>
</head>
<body>
<tr>
<td>
Test 1
</td>
</tr>
</body>
</table>
var numberOFRow = 1;
$("#add").click(function(){
numberOFRow++
$('#tableAdd tr:last').after('<tr id = test'+numberOFRow +'><td> Test' + numberOFRow + '</td></tr>')
});
$("#tableAdd").bind("DOMNodeInserted",function(){
alert("Row number"+ numberOFRow+ "created");
});
Working Demo for your table examplehttps://jsfiddle.net/vickykumarui/qpxL8k4c/

delete function delets the last record from table. js jquery.updated

I have a dynamic table which gets values from db. I have a button which onclcik runs the query to delete the record from database. Currently instead of deleteing record(which was clicked ) its deleting the last record available. I am updating from here I figure out the issue when I provide ID to the post somehow the LAST ID is being sent to the query, is there anyway I can delete the ID which was selected.please look at the code for more info
//this is how im creating dynamic table
//just for the test
function() {
});
});
<table>
<thead>
<tr>
<td>
</td>
</tr>
</thead>
<tbody id="table"></tbody>
</table>
<button type="button" id="chochk" style="display:none" class="sukuti">delete</button>
.
Perhaps you may be better listening directly on the change event of the checkbox and then get the value of the event.target afterwards? There is something wrong with the way you are getting the variable ad in your code i suspect, but without seeing how that is derived it's hard to see why.
The example below shows a simple way to get the value of a checkbox, hopefully this might lead you to the correct answer.
$('.test').on('change', function(e) {
alert(e.target.value);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Value of 1: <input type="checkbox" class="test" value="1" /><br />
Value of 2: <input type="checkbox" class="test" value="2" />
Instead of a checkbox, use a radio button, so the user can only select one at a time. Then in the handler for the delete button, get the value of the checked button and send that to the server.
//this is how im creating dynamic table
//just for the test
function() {
var table = document.getElementById('tablebody');
for (var i = 0; i < (test.length); i = i + 2) { //test is an array of values from db
var row = table.insertRow(-1);
var cell3 = row.insertCell(-1);
var cell1 = row.insertCell(-1);
var cell2 = row.insertCell(-1);
cell1.innerHTML = //some html span
cell2.innerHTML = //some html span
//this is the checkbox which onclick shows the button
cell3.innerHTML = '<input type="radio" name="checkbox" class="your" value="ID of current row">';
}
///this is how i am displaying a button on click and also delete function
$(document).on('click', ".your", function() {
$('#chochk').show();
});
$(".sukuti").click(function() {
var ad = $(".your:checked").val();
$.post("test.jsp", {
id: ad //ad is the ID which will delete the specifIC ID being clicked
}, function(data) { //sending a query to delete from db working good
});
});
<table>
<thead>
<tr>
<td>
</td>
</tr>
</thead>
<tbody id="table"></tbody>
</table>
<button type="button" id="chochk" style="display:none" class="sukuti">delete</button>

Referencing with Javascript/jQuery the rows of a table that has no id while holding an instance of one of its rows

I have several tables in my page and none of them has an id attribute.
I retrieve with Javascript or jQuery a row of one of these tables. Then I want to do things to all the rows of that table but not to any row of any other table. Selecting such rows through jQuery would do, and also doing that with Javascript would be ok.
So I need to identify a table and the only thing I know about it is that this row belongs to it. Is it possible ?
Runnable example:
<html>
<head>
<script src="jquery-1.11.3.js"></script>
<style>
.myYellow
{
background-color: yellow;
}
</style>
<script type="text/javascript">
function doStuff() {
var jqRow = jQuery("#r1t1"); if (jqRow.length !== 1) throw "ERROR";
var htmlRow = jqRow.get(0); // How do I restrict the jqSelectedRows below to only the table this row belongs to ?
var jqSelectedRows = jQuery("tr.myYellow"); // But I only want the yellow rows of the table containing htmlRow .
jqSelectedRows.each(function(index) {
this.setAttribute("style", "background-color: blue");
});
}
</script>
</head>
<body>
<table border="1">
<tr id="r1t1" ><td>r1 t1</td></tr>
<tr id="r2t1" class="myYellow"><td>r2 t1</td></tr>
<tr id="r3t1" class="myYellow"><td>r3 t1</td></tr>
<tr id="r4t1" ><td>r4 t1</td></tr>
</table>
<br><br>
<table border="2">
<tr id="r1t2" class="myYellow"><td>r1 t2</td></tr>
<tr id="r2t2" class="myYellow"><td>r2 t2</td></tr>
<tr id="r3t2" ><td>r3 t2</td></tr>
</table>
<br><br>
<input type="button" value="Do" onclick="doStuff()">
<br>The button selects the first row of the first table ("r1 t1") and then it
<br>must turn blue all the <strong>yellow</strong> rows of <strong>that table only</strong>;
no other table must be affected.
</body>
</html>
Use .siblings(). See comment in snippet.
Note: Changed button slightly which of course can easily be converted back to the original way by deleting the code around the doStuff() function and adding the onclick="doStuff();" back to the <input> button.
$(function() {
$('#do').on('click', doStuff);
function doStuff() {
var jqRow = $("#r1t1");
if (jqRow.length !== 1) throw "ERROR";
var jqSelectedRows = jqRow.siblings(); // How do I restrict the jqSelectedRows below to only the table this row belongs to? | Use .siblings() to collect all <tr>s within the table (excluding the referenced tr#r1t1).
jqSelectedRows.each(function(index) {
this.setAttribute("style", "background-color: blue");
});
}
});
.myYellow {
background-color: yellow;
}
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>32721615</title>
</head>
<body>
<table border="1">
<tr id="r1t1">
<td>r1 t1</td>
</tr>
<tr id="r2t1" class="myYellow">
<td>r2 t1</td>
</tr>
<tr id="r3t1" class="myYellow">
<td>r3 t1</td>
</tr>
</table>
<br>
<br>
<table border="2">
<tr id="r1t2" class="myYellow">
<td>r1 t2</td>
</tr>
<tr id="r2t2" class="myYellow">
<td>r2 t2</td>
</tr>
<tr id="r3t2">
<td>r3 t2</td>
</tr>
</table>
<br>
<br>
<input id="do" type="button" value="Do">
<br>The button selects the first row of the first table ("r1 t1") and then it
<br>must turn blue all the <strong>yellow</strong> rows of <strong>that table only</strong>; no other table must be affected.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
</body>
</html>

BIRT how to get table name?

In my report design's layout I have a label, table and HTML button.
How do I get values from tables, labels, etc. using the HTML button's OnClick event?
The table and label can't be accessed easily using "elementname".getValue(); Am I missing something?
Thanks.
Alright, this solution can be modified to how your actual table structure looks like, and what actual information you need. You can do this many different ways, but this solution utilizes jQuery to get the label element and also the 'td' cells from a Table and Twitter Bootstrap for styling. You can see a jsFiddle here that I made to visualize this. If it doesn't fit your needs, I would suggest looking at the jQuery API to modify how exactly you should get the data you need.
This is the HTML:
<!DOCTYPE html>
<html>
<head>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
</head>
<body>
<label id="label">This is my Table</label>
<table class="table table-striped">
<thead>
<tr>
<th>Row</th>
<th>First Name</th>
<th>Last Name</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>John</td>
<td>Carter</td>
<td>johncarter#mail.com</td>
</tr>
<tr>
<td>2</td>
<td>Peter</td>
<td>Parker</td>
<td>peterparker#mail.com</td>
</tr>
<tr>
<td>3</td>
<td>John</td>
<td>Rambo</td>
<td>johnrambo#mail.com</td>
</tr>
</tbody>
</table>
<button type="button" id="getInfo" class="btn btn-primary">Get Info</button>
<br/>
<p>Your Results Object once you hit Get Info button</p>
<div id="results"></div>
<!-- Get jQuery -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</body>
</html>
This is the Javascript:
// This solution uses jQuery
// A $( document ).ready() block.
$( document ).ready(function() {
// declares an object literal named 'results' to save future results
// declares an array literal named 'tableData' to save table data
var results = {},
tableData = [];
// this executes once you click
// the HTML button with ID '#getInfo'
$('#getInfo').click(function() {
//loop through each 'td' cell which has information
$('td').each(function() {
var value = $(this).text();
tableData.push(value);
});
// assign the label to object 'results' with property label
results.label = $('#label').text();
results.tableData = tableData;
document.getElementById("results").innerHTML =
JSON.stringify(results);
});
});

HTML - JavaScript - Spring Change row color depending upon the value

I have variable being initialized by Spring Model and depending upon the value of a column, I need to display the relevant color of background.
I tried following JavaScript code but is not working:
<head>
<script type="text/javascript">
<!--
var table = document.getElementById("dataStatusVar");
var tbody = table.getElementsByTagName("tbody")[0];
var rows = tbody.getElementsByTagName("tr");
// add event handlers so rows light up and are clickable
for (i=0; i < rows.length; i++) {
var value = rows[i].getElementsByTagName("td")[0].firstChild.nodeValue;
if (value == 'mraible') {
rows[i].style.backgroundColor = "red";
}
}
-->
</head>
<body>
<div>
<table id="dataStatusVar">
<tr>
<th>TYPE</th>
<th>START</th>
<th>END</th>
</tr>
<tr>
<td>mraible</td>
<td>startvalue</td>
<td>endvalue</td>
</tr>
</table>
</div>
</body>
I expect the row to be RED. But it is not.
Can you please suggest what I am doing wrong?
cant comment so asking in answers, have you tried writing the js code below html?
The JS needs to be executed after the html is loaded and using a separate file when dealing with JSTL can be weird to say the lease so the best option is to execute js code after the HTML and JSTL is done.
If you have an option to choose the jstl here is the following code
<c:forEach items="${rows}" var="usr" varStatus="st">
<c:choose>
<c:when test="${st.index%2 eq 0}">
<c:set var="tr" value="red"></c:set>
</c:when>
<c:otherwise>
<c:set var="tr" value="blue"></c:set>
</c:otherwise>
</c:choose>
<div>
<table id="dataStatusVar">
<tr>
<th>TYPE</th>
<th>START</th>
<th>END</th>
</tr>
<tr bgcolor="{tr}">
<td>mraible</td>
<td>startvalue</td>
<td>endvalue</td>
</tr>
</table>
</div>
</c:forEach>
you may try this:
<body>
<div>
<table id="dataStatusVar">
<tr>
<th>TYPE</th>
<th>START</th>
<th>END</th>
</tr>
<tr>
<td>mraible</td>
<td>startvalue</td>
<td>endvalue</td>
</tr>
</table>
</div>
</body>
<script>
var table = document.getElementById("dataStatusVar");
var tbody = table.getElementsByTagName("tbody")[0];
var rows = tbody.getElementsByTagName("tr");
// add event handlers so rows light up and are clickable
for (i=0; i < rows.length; i++) {
var tds = rows[i].getElementsByTagName("td");
if (tds.length) {
var value = tds[0].innerHTML;
if (value == 'mraible') {
rows[i].style.background = "red"; // for entire row
//tds[0].style.background = "red"; // for a cell
}
}
}
</script>
If a function/statements depend on DOM element(s), then measures has to be taken that during the execution of that function/statement element(s) should be available (loaded) for processing. So, i have called setColour() function once the elements are loaded (in body)
<html>
<head>
<script type="text/javascript">
function setColour()
{
var table = document.getElementById("dataStatusVar"); //Gets the required table
var tbody = table.getElementsByTagName("tbody")[0];
var rows = tbody.getElementsByTagName("tr"); //Gets the trs from the table
for (i=0; i < rows.length; i++) {//For each row in the table
var tdelements = rows[i].getElementsByTagName("td")[0]; //First cell in the selected row
if (tdelements != null) { //If first cell exists
var value = tdelements.innerHTML; //Fetch the content of the first cell in the selected row
if (value === 'mraible') { //Checks if the cell has expected value
rows[i].style.background = "red"; // Sets red color for the entire row
}
}
}
}
</script>
</head>
<body onload="setColour()">
<div>
<table id="dataStatusVar">
<tr>
<th>TYPE</th>
<th>START</th>
<th>END</th>
</tr>
<tr>
<td>mraible</td>
<td>startvalue</td>
<td>endvalue</td>
</tr>
<tr>
</tr>
</table>
</div>
</body>
</html>
From your sample, i have assumed that color has to be set for the entire row if the content of the the first column in the row matches a particular value.

Categories

Resources