Dynamically add and remove rows of cascading dropdown lists? - javascript

So I'm trying to make a form where the user can dynamically add and remove rows containing cascading dropdowns as a class picker.
So far I've been able to make everything work except for the remove selected classes function.
I've tried a couple different deleteRow functions but can't seem to make it work.
My most recent attempt is by using the checkbox input but I'm open to any other solutions.
Thanks
<!DOCTYPE html>
<html>
<head>
<title>Semesters Planned</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
$(function() {
$('#selectCategory').change(function() {getSelectedItem(this, null); });
$('#button').click(function()
{addRow('dataTable'); });
var classes = {//can probably use external text files for these later on
"Core": ["UNI101", "ENG101"],
"Major": ["CSC101", "CSC180"],
"Elective": ["ART101", "PSY101"]
};
var keys = Object.keys(classes);
var category_dropdown = document.getElementById("selectCategory");
var getSelectedItem = function(element, row) {
var e = element;
var selectedCategory = e.options[e.selectedIndex].value;
var sub_category_dropdown = (row != null ? row.getElementsByTagName("select")[1] : document.getElementById("selectSubCategory"));
sub_category_dropdown.options.length = 0;
for (var i = 0; i < classes[selectedCategory].length; i++) {
sub_category_dropdown[sub_category_dropdown.length] = new Option(classes[selectedCategory][i], classes[selectedCategory][i]);
}
};
var addRow = function(tableID)
{
var table = document.getElementById(tableID);
var rowCount = table.rows.length;
var row = table.insertRow(rowCount);
var colCount = table.rows[0].cells.length;
for (var i = 0; i < colCount; i++) {
var newcell = row.insertCell(i);
newcell.innerHTML = table.rows[0].cells[i].innerHTML;
newcell.childNodes[0].selectedIndex = 0;
}
var selects = row.getElementsByTagName("select");
selects[0].addEventListener('change', function()
{
getSelectedItem(this, row)
}, false);
};
function deleteRow(tableID)
{
for (var rowi= table.rows.length; rowi==0;) {
var row= table.rows[rowi];
var inputs= row.getElementsByTagName('chk');
for (var inputi= inputs.length; inputi0;) {
var input= inputs[inputi];
if (input.type==='checkbox' && input.checked) {
row.parentNode.remove(tableID);
break;
}
}}}
for (var keys in classes) {
category_dropdown[category_dropdown.length] = new Option(keys, keys);
}
});
</script>
</head>
<body>
<INPUT type="button" value="Add Class" id="button" />
<INPUT type="button" value="Remove Selected Classes"/>
<form id="myForm">
<TABLE id="dataTable">
<TR>
<TD>
<select id="selectCategory">
<option>Choose Class Type</option>
</select>
</TD>
<TD>
<select id="selectSubCategory">
<option>Choose Class Type First</option>
</select>
</TD>
<TD><INPUT type="checkbox" name="chk" id="input"/></TD>
</TR>
</TABLE>
</form>
<input type = "Submit" value = "Submit">
</body>
</html>

My first suggestion would be to make sure that the remove button is doing something when you click it - you've attached an event listener to the Add Class button, but the Remove Selected Classes button doesn't look like it's calling that deleteRows function.
Then, make sure that you have a reference to that table in the deleteRows function. You are passing it a table id, but the table variable reference is defined outside of the scope of that function.
Then, work on the for loop and the logic therein. It looks like you are mistaking getElementsByTagName with getElementsByName. The one you are using is concerned with the tag name (input) not the name attribute (chk).
Hope this helps a little bit!

Related

Created a delete function for a list, but not all checked items are deleting

I am currently taking Wes Boros JS 30 challenge and for this particular class, we created a list where we add foods we like. As an extra assignment, we are to create a select all function, an unselect all function, and a delete function. I was able to successfully create a select all function where once you click that button, it selects all the items on the current list. My issue is that the delete function I created deletes everything, except for one or two items. Those undeleted items still remain checked, but I have to click on the delete button again in order for it to delete. FYI: I local storage was incorporated in this exercise.
Can somebody help me out and also explain what I was doing wrong?
Here is a jsfiddle of it as well
Here is how I have my HTML set up:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>LocalStorage</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="wrapper">
<h2>LOCAL TAPAS</h2>
<p></p>
<ul class="plates">
<li>Loading Tapas...</li>
</ul>
<form class="add-items">
<input type="text" name="item" placeholder="Item Name" required>
<input type="submit" value="+ Add Item">
</form>
<input type="button" onclick="selectAll()" value="Select All"/>
<input type="button" onclick="UnSelectAll()" value="Unselect All"/>
<input type="button" onclick="deleteItem()" value="delete Item"/>
</div>
</body>
</html>
Here is my Javascript:
const addItems = document.querySelector('.add-items');
const itemsList = document.querySelector('.plates');
const items = JSON.parse(localStorage.getItem('items')) || [];
//DELETE FUNCTION
function deleteItem(){
var boxes = document.getElementsByClassName('chk');
var texts = document.getElementsByClassName('txt');
for(var i = 0; i < boxes.length; i++){
box = boxes[i];
txt = texts[i];
if(box.checked){
box.parentNode.removeChild(box);
txt.parentNode.removeChild(txt);
}
}
}
//SELECT ALL FUNCTION
function selectAll(){
var checkedItem = document.getElementsByName('item');
for (var i = 0; i < checkedItem.length; i++) {
if (checkedItem[i].type == 'checkbox')
checkedItem[i].checked = true;
}
}
//UNSELECT ALL FUNCTION
function UnSelectAll(){
var checkedItem = document.getElementsByName('item');
for (var i = 0; i < checkedItem.length; i++) {
if (checkedItem[i].type == 'checkbox')
checkedItem[i].checked = false;
}
}
//ADD ITEM FUNCTIO
function addItem(e){
e.preventDefault()
const text = (this.querySelector('[name=item]')).value;
const item = {
text,
done: false
};
items.push(item);
populateList(items, itemsList);
localStorage.setItem('items', JSON.stringify(items));
this.reset();
}
//DISPLAY THE HTML FUNCTION
function populateList(plates =[], platesList) {
platesList.innerHTML = plates.map((plate, i) => {
return `
<li>
<input class="chk" type="checkbox" name="item" data-index=${i} id="item${i}" ${plate.done ? 'checked' : ''} />
<label class="txt" name="item" for="item${i}">${plate.text}</label>
</li>
`
}).join('');
}
function toggleDone(e){
if(!e.target.matches('input')) return;
const el = e.target;
const index = el.dataset.index;
items[index].done = !items[index].done;
localStorage.setItem('items', JSON.stringify(items));
populateList(items, itemsList);
}
addItems.addEventListener('submit', addItem)
itemsList.addEventListener('click', toggleDone)
populateList(items, itemsList);
//DELETE ITEM EVENT HANDLER
itemsList.addEventListener('click', deleteItem);
The reason why your delete function wasn't working properly it's because Node.childNodes returns a live NodeList which means when you use removeChild on each element in the collection the other elements gets rearranged and the length of list get's smaller causing you to skip some of them so you should convert your html collection to an array using Array.from
function deleteItem(){
var boxes = document.getElementsByClassName('chk');
var texts = document.getElementsByClassName('txt');
arrbox = Array.from(boxes)
arrtext = Array.from(texts)
for(var i = 0; i < arrbox.length; i++){
var box = arrbox[i];
var txt = arrtext[i];
if(box.checked){
box.parentNode.removeChild(box);
txt.parentNode.removeChild(txt);
}
}
}
Here is working jsfiddle

how to create dynamic grid using javascript

s.no. | description
abcd1
abcd2
abcd3
i want to add more rows through input. now what i want is when i will add another row. let say {describtion="abcd4"}
then the above grid will become
s.no. | description
abcd4
abcd1
abcd2
abcd3
meaning s.no. field got updated and new row will be added at top. adding a new row on top is no issue but how could i update s.no. at same time, here i want to ask is there any specific way to do this.
Here is a solution that adds rows at the top of a table and keeps the numbers updated:
document.querySelector('#btnadd').addEventListener('click', function () {
var inp = document.querySelector('#inpadd');
var descr = inp.value;
if (descr === '') return; // do not add empty values
var grid = document.querySelector('#grid');
// first increment all row numbers
for (var i = 1, row; row = grid.rows[i]; i++) {
row.cells[0].textContent = i+1;
}
// add new row
var row = grid.insertRow(1);
var cell1 = row.insertCell(0);
var cell2 = row.insertCell(1);
cell1.textContent = 1;
cell2.textContent = descr;
// clear input
inp.value = "";
});
New description: <input type="text" id="inpadd"><button id="btnadd">Add</button>
<table id="grid">
<tr><th>s.no.</th><th>description</th></tr>
<table>
If you want to insert new text description in the beginning of the ordered list, you can use 'insertBefore' javascript code:
list.insertBefore(entry, list.firstChild);
It should add the new text in the beginning of the list. Refer below code if it helps your problem.
<!DOCTYPE html>
<html>
<body>
<p>Input the text description and click 'Add Description' button to insert in list:</p>
<form>
Description Text:<br>
<input type="text" name="description" id="description">
<br>
<input type="button" value="Add Description" onclick='appendDescription()'>
</form>
<ol id="desclist">
<li>abcd1</li>
<li>abcd2</li>
<li>abcd3</li>
</ol>
<script>
function appendDescription(){
var description= document.getElementById('description').value;
var entry = document.createElement('li');
entry.appendChild(document.createTextNode(description));
var list = document.getElementById('desclist');
list.insertBefore(entry, list.firstChild);
}
</script>
</body>
</html>
function pushAtStarting(array, element){
array.unshift(element); // new element has s.no = 0
for (index in array){
array[index].sno++
}
}
var array = [];
pushAtStarting(array, {sno: 0, description: "abc"});
it works if your grid is java script arrays and elements are json elements.

How to pass an array created in javascript to another jsp and then use that array in a java function on that jsp?

Here is a script i have and I want to be able to pass the array "playernames" into a java function on another .jsp. I'm wonder how to pass that array to another page and then retrieve it for my java function.
<script>
function getPlayerNames() {
var selected = document.querySelectorAll("#selected-players > tr > td");
var playernames = [];
for(var i=0; i<selected.length; ++i){
var id = selected[i].getAttribute('id');
if (id.indexOf('Player')>-1) {
playernames.push(selected[i].textContent);
}
}
}
</script>
Edit:
<td style="vertical-align: top;"><button onclick="getPlayerNames()"id="generate">Generate</button><br></td>
<input type="hidden" id="players" />
<script>
function getPlayerNames(){
var selected = document.querySelectorAll("#selected-players > tr > td");
var playernames = [];
for(var i=0; i<selected.length; ++i){
var id = selected[i].getAttribute('id');
if (id.indexOf('Player')>-1) {
playernames.push(selected[i].textContent);
}
}
document.getElementById("players").values=playernames;
document.getElementById("players").submit();
window.location.replace("lineups.jsp");
}</script>
Other jsp
<%String[] players = request.getParameterValues("players");%>
You'll need to have the hidden field inside the form tags with the id and action attributes set as below.
<td style="vertical-align: top;"><button onclick="getPlayerNames()"id="generate">Generate</button><br></td>
<form id="playerNames" action="Url"> // In action give the Url of the jsp page you want to send the values to lineups.jsp in your case I guess.
<input type="hidden" id="players" name="players" />
</form>
<script>
function getPlayerNames(){
var selected = document.querySelectorAll("#selected-players > tr > td");
var playernames = [];
for(var i=0; i<selected.length; ++i){
var id = selected[i].getAttribute('id');
if (id.indexOf('Player')>-1) {
playernames.push(selected[i].textContent);
}
}
document.getElementById("players").value=playernames;
document.getElementById("playerNames").submit();
}</script>
1) Stringify the array and then assign to hidden field.
Refer: Javascript Hidden Input Array
2) Submit the hidden field in a form to server.
<input type="hidden" id="hiddenArrayField"/>
document.getElementById("hiddenArrayField").value=yourStringifyArrayValue;
3) On server you would get this as a part of request i.e. on next jsp you can retrieve this value as a request parameter.
<%= request.getParameter("hiddenArrayField")%>

Getting HTML table data (td) (i.e. text or val) using table header (th) into Textarea

I have SQLite3 (i.e. Spatialite query) that outputs the results into HTML table. I want to get the AsText(Geometry) data to output in <textarea>
Here is the table and some assumptions.
<table>
<tr>
<th>name</th>
<th>AsText(Geometry))</th>
</tr>
<tr>
<td>Andres Street</td>
<td>LINESTRING(7.120068 43.583917,7.120154 43.583652,7.120385
43.582716,7.12039 43.582568,7.120712 43.581511,7.120873 43.580718)</td>
</tr>
</table>
$('#wktInput').click(function(){
???
???
var asTextGeometryText =
$("#wktResult").text(asTextGeometryText);
});
<textarea name='wktResult' value ='wktResult' ROWS="10" COLS="50" >'Should Display AsText(Geometry Column here!'</textarea>
This is the DOM
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
var fieldNames = aResult.fieldNames;
var records = aResult.data;
var numFields = fieldNames.length;
var numRecords = records.length;
var container = document.getElementById('queryResults');
container.innerHTML = '';
var table = document.createElement('table');
container.appendChild(table);
var headerRow = document.createElement('tr');
table.appendChild(headerRow);
for(var i = 0; i < numFields; i++){
var header = document.createElement('th');
header.innerText = fieldNames[i];
headerRow.appendChild(header);
}
for(var i = 0; i < numRecords; i++){
var tableRow = document.createElement('tr');
table.appendChild(tableRow);
for(var j = 0; j < numFields; j++){
var tableData = document.createElement('td');
tableRow.appendChild(tableData);
tableData.innerText = records[i][j];
}
}
}
<input id='SQLinput' size="90" rows="3" value = 'SELECT name, AsText(Geometry) FROM Roads Where MbrContains(Geometry, MakePoint(7.120872,43.580722,4326))'></input>
<input type='button' class='button' value='Display AsText' ontouchend='wktAsTextInput'/>
Thanks in advance
It seems that texarea uses id for value.
<textarea id="field1">example text</textarea>
[This problem is related to textarea in jQuery as well][1]
This example below demonstrate that jquery is not working in textarea using id.
<script type="text/javascript">
$(function() {
$('button').click(function() {
var row = $('input:first').val();
var column = $('input:eq(1)').val();
var cell = $('table tr:eq('+row+') td:eq('+column+')');
if (cell.length == 0) {
$('#value').text('Undefined');
}
else {
$('#value').text(cell.text());
}
});
});
</script>
</head>
<body>
<h1>Table Cell Value</h1>
<table>
<tr><td>Cell 1-1</td><td>Cell 1-2</td><td>Cell 1-3</td></tr>
<tr><td>Cell 2-1</td><td>Cell 2-2</td><td>Cell 2-3</td></tr>
<tr><td>Cell 3-1</td><td>Cell 3-2</td><td>Cell 3-3</td></tr>
</table>
Row: <input type="text" value="0">
Column: <input type="text" value="0">
Value: <span id="value">?</span><br>
Textarea: <textarea id="value" >Try this! this is not working</textarea>
<button>Get Value</button>
All is working in this example. Then added a textarea to see if I can make it work. Textarea is not working in this example. Something wrong with jquery and textarea using id as well as name.
Textarea: <textarea name="value" >Try this! this is not work as well</textarea>
How this does not work.
New info about this textarea value.
$('#id_of_textarea').attr('value'); //to get and...
$('#id_of_textarea').attr('value','updated value of textarea'); //to set it...
<textarea id="editor_desc" onkeyup="update_textarea(this)"></textarea>
function update_textarea(obj)
{
$('#mydiv').text($(obj).attr('value')); //whatever you type in the textarea would be reflected in #mydiv
}
http://blog.ekini.net/2009/02/24/jquery-getting-the-latest-textvalue-inside-a-textarea/
It seems that my problem is not rendering a regular html tablet but a direct render to the screen.
The author of QuickConnect say told me,
If you want one of those values so that you can use it you need to pull it
out of the 2D array.
Do you mean displaying the content in AsText(Geometry) column at the textarea?
var text = []
$('table').find('tr:has(td)').each(function(){
text.push($.trim($(this).find('td:eq(1)').html()));
})
// and you set it to your textarea
$('textarea[name="wktResult"]').val(text.join('\n'));
1- assign an id attribute to your textarea to use it in jquery or if your page contain just one textarea you can use tag name insteasd.
2- to get text of textarea you need just call text function without any parameters
$('#wktInput').click(function(){
var asTextGeometryText =$('table').find('th').eq(2).text();
$('#id_of_textarea').attr('value',asTextGeometryText);
});

Dynamicaly delet the table row using check box and javascript

How can we Dynamically delete the html table rows using javascript.
We have a check box on each row. While clicking the remove button with the check box selected the row would be deleted. Such as
document.getElementById(j).innerHTML = '';
Removing an element is best done with DOM node functions like removeChild, rather than innerHTML-hacking. eg.:
function removeAllRowsContainingCheckedCheckbox(table) {
for (var rowi= table.rows.length; rowi-->0;) {
var row= table.rows[rowi];
var inputs= row.getElementsByTagName('input');
for (var inputi= inputs.length; inputi-->0;) {
var input= inputs[inputi];
if (input.type==='checkbox' && input.checked) {
row.parentNode.removeChild(row);
break;
}
}
}
}
Here's a small mockup on how this could be done:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Mockup</title>
<script type="text/javascript">
function killRow(src) {
var dRow = src.parentElement.parentElement;
document.all("table").deleteRow(dRow.rowIndex);
}
</script>
</head>
<body>
<form action="something.html">
<table id="table">
<tr>
<td><input type='checkbox' onclick='killRow(this);'>Click me!</td>
<td>Demodata 1</td>
</tr>
<tr>
<td><input type='checkbox' onclick='killRow(this);'>Click me!</td>
<td>Demodata 2</td>
</tr>
</table>
</form>
</body>
</html>
Key in this is a JScript-function which then can be used from any row in there. It might even be more generalized. When clicking on the checkboxes the function is called.
I'd rather not use innerHTML on this, I'd prefer DOM nodes (here parentElement).
Here is a function that performs the required action of deleting rows by checking the value of checkbox. Call this function in the onclick event of the delete button(Comments included). Hope this helps :)
function removeSampleRow(id) {
/***We get the table object based on given id ***/
var objTable = document.getElementById(id);
/*** Get the current row length ***/
var iRow = objTable.rows.length;
/*** Initial row counter ***/
var counter = 0;
/*** Performing a loop inside the table ***/
if (objTable.rows.length > 1) {
for (var i = 0; i < objTable.rows.length; i++) {
/*** Get checkbox object ***/
var chk = objTable.rows[i].cells[0].childNodes[0];
if (chk.checked) {
/*** if checked we del ***/
objTable.deleteRow(i);
iRow--;
i--;
counter = counter + 1;
}
}
/*** Alert user if there is now row is selected to be deleted ***/
if (counter == 0) {
alert("Please select the row that you want to delete.");
}
}else{
/*** Alert user if there are no rows being added ***/
alert("There are no rows being added");
}
}

Categories