Create a select from list and put it in table - javascript

I'm writing a web application using Java and Spring.
From the controller, I send to the view a list called materials
#RequestMapping(value = "/advanced")
public String advancedCalculation(Model model) {
model.addAttribute("materials", materialService.getMaterials());
model.addAttribute("calcForm", new CalculationForm());
return "advanced";
}
materials is a list of objects called MaterialDTO:
public class MaterialDTO extends DTO {
/* Constructors */
public MaterialDTO() { super(); }
public MaterialDTO(Integer id, String name) { super(id, name); }
}
From the client side I have to make tables with buttons to add rows to such tables. Something like:
<table id="1">
<thead>
... 2 columns ...
</thead>
<tbody>
<tr>
<td>HERE I NEED THE SELECTOR</td>
<td>column 2</td>
</tr>
</tbody>
</table>
.
.
.
<table id=N>
<thead>
... M columns ...
</thead>
<tbody>
<tr>
<td>HERE I NEED THE SELECTOR</td>
<td>column 2</td>
...
<td>column M</td>
</tr>
</tbody>
</table>
That selector is the same for all tables, so I wanted to create it from the materials list once and use it where I need it. With this last I'm having problems ...
/* Making select */
var materialsList = new Array();
var sel = $('<select>');
<c:forEach items="${materials}" var="material">
var material = new Object();
material.id = '${material.id}';
material.name = '${material.name}';
materialsList.push(material);
</c:forEach>
$(materialsList).each(function() {
sel.append($('<option>').attr('value', this.id).text(this.name));
});
That's when I try to add it as HTML and it fails
function add_to_table_1() {
$('#1')
.append('<tr><td>' + sel.html() + '</td><td><input type="text" id="e"></input></td><td><input type="text" id="S"></input></td><td><input type="itext" id="r"></input></td><td><button onclick="delete_row(this)">Borrar</button></td></tr>');
}
And instead of the selector appears "[object Object]". How can I fix this?

Try this:
$(sel).wrap('<div></div>').parent().html();
This will fix your select not displaying with your options. Remember .html() only returns innerHTML. The outer html, <select></select>, will not display with it. You have to wrap first.
Alternative:
$(sel)[0].outerHTML

Related

table.removeRow() stops working when 'resetting' table?

Suppose you have a html table of the
<form id="myForm">
<table id="myTable">
<tr>
<th>One</th>
<th>Two</th>
<th>Three</th>
</tr>
<tr>
<td>Alpha</td>
<td>Bravo</td>
<td>X</td>
</tr>
<tr>
<td>Charlie</td>
<td>Delta</td>
<td>X</td>
</tr>
<tr>
<td>Echo</td>
<td>Foxtrot</td>
<td>X</td>
</tr>
</table>
</form>
Reset
I have the following javascript
var table = document.getElementById('myTable');
var form = document.getElementById('myForm');
var formSave = form.innerHTML;
function remove(rowID)
{
table.deleteRow(rowID);
}
function reset()
{
form.innerHTML = formSave;
}
For some reason, the remove() function works fine, but after using the reset() function, it no longer works. Can anyone tell me why this is?
As var table is a live 'Element object' it's properties are updated each time you delete a row. By the time you deploy the reset() function var table references less Children than the restored HTML. Opening the console will show you have an indexing error on subsequent uses of the function bound to "X".
You can remedy this by re-acquiring the element in the reset function, like so...
var table = document.getElementById('myTable');
var form = document.getElementById('myForm');
var formSave = form.innerHTML;
function remove(rowID) {
table.deleteRow(rowID);
}
function reset() {
form.innerHTML = formSave;
/* re-acquire 'new' (inserted) table */
table = document.getElementById('myTable');
}
Hope that helped :)

Simple show/hide gone wrong in Javascript

I'm trying to create a show/hide function for data within a table populated with data from a mssql database. The function should look for rows with the same value in the "capability" column and onclick, hide all rows with the same value. After this, a row is inserted into the table with the same capability value, but summarizes the data in the hidden rows. This should work in the way that grouping cells together works in excel.
I've managed to get this to work, but it only works for the first click and I receive a "cannot read innerHTML property of NULL" for any of the function's calls after that.
function compactRows(thisrow) {
var totalRows = document.getElementById("DataTable").getElementsByTagName("tr").length;
var summaryVal1= [];
var summaryVal2= [];
for(var i = 1; i < totalRows;i++) {
var trID = "capability" + i;
if(thisrow.innerHTML == document.getElementById(trID).innerHTML) { //The error gets returned on this line
summaryVal1.push(document.getElementById(trID).parentNode.children[5].innerHTML);
summaryVal2.push(document.getElementById(trID).parentNode.children[14].innerHTML);
document.getElementById(trID).parentNode.style.display = 'none';
}
}
createNewRow(thisrow, summaryVal1, summaryVal2);
}
//I took out the logic for the data summarizing in the createNewRow function because I don't think its relevant to the issue I'm having. Also, I didn't want to crowd the area with unrelated code
function createNewRow(row, ibxMobile, overallStatus) {
var table = document.getElementById("DataTable");
var localRow = table.insertRow(row.parentNode.rowIndex);
var cell1 = localRow.insertCell(0);
cell1.setAttribute("id", "entry1");
var cell2 = localRow.insertCell(0);
cell2.setAttribute("id", "Capability");
cell2.innerHTML = row.innerHTML;
var cell3 = localRow.insertCell(0);
cell3.setAttribute("id", "entry3");
}
The function called at the bottom, createNewRow, handles making the row to be entered after all the rows are hidden. It also, handles the logic for summarizing the hidden rows.
All help is greatly appreciated! Thank you
Edit 1: example table set up
<table>
<tr>
<th>Entry1 </th>
<th>Capability</th>
<th>Entry3 </th>
</tr>
<tr>
<td>1.1</td>
<td id="Capability1" onclick="compactRows(this)">Lasers</td>
<td>stuff</td>
</tr>
<tr>
<td>1.2</td>
<td id="Capability2" onclick="compactRows(this)">Lasers</td>
<td>things</td>
</tr>
<tr>
<td>2.1</td>
<td id="Capability3" onclick="compactRows(this)">Beams</td>
<td>more things</td>
</tr>
</table>
//The Below table is what it looks like after clicking either of the first two entries
<table>
<tr>
<th>Entry1 </th>
<th>Capability</th>
<th>Entry3 </th>
</tr>
<tr>
<td>1</td>
<td id="Capability">Lasers</td>
<td></td>
</tr>
<tr>
<td>2.1</td>
<td id="Capability3" onclick="compactRows(this)">Beams</td>
<td>more things</td>
</tr>
</table>
There is no "Capability1" id for any rows after the "CreateNewRow" is called. Therefore, the second time "CompactRows()" is called a null reference is thrown when accessing "document.getElementById("Capability1").innerHTML". Rework the CreateNewRow to inlcude the increment for the Capability id value or test that "getElementById" actually returns an object before attempting to access the innerHTML method.

how to convert/transform an HTML table tbody (with rowspans) TO json?

I have an HTML table with combined row td's, or how to say, I don't know how to express myself (I am not so good at English), so I show it! This is my table:
<table border="1">
<thead>
<tr>
<th>line</th>
<th>value1</th>
<th>value2</th>
</tr>
</thead>
<tbody>
<tr>
<td rowspan="2">1</td>
<td>1.1</td>
<td>1.2</td>
</tr>
<tr>
<td>1.3</td>
<td>1.4</td>
</tr>
<tr>
<td rowspan="2">2</td>
<td>2.1</td>
<td>2.2</td>
</tr>
<tr>
<td>2.3</td>
<td>2.4</td>
</tr>
</tbody>
</table>
(you can check it here)
I want to convert this table to a JSON variable by jquery or javascript.
How should it look like, and how should I do it? Thank you, if you can help me!
if you want to convert only text use this one :
var array = [];
$('table').find('thead tr').each(function(){
$(this).children('th').each(function(){
array.push($(this).text());
})
}).end().find('tbody tr').each(function(){
$(this).children('td').each(function(){
array.push($(this).text());
})
})
var json = JSON.stringify(array);
To make a somehow representation of your table made no problem to me, but the problem is how to parse it back to HTML! Here a JSON with the first 6 tags:
{"table":{"border":1,"thead":{"th":{"textContent":"line","tr":"textContent":"value1",...}}}}}...
OR for better understanding:
{"tag":"table","border":1,"child":{"tag":"thead","child":{"tag":"th","textContent":"line",
"child":{"tag":"tr","textContent":"value1","child":...}}}}...
Closing tags are included.
For further explanations I need to know whether your table is a string or part of the DOM.
I belive this is what you want:
var jsonTable = {};
// add a new array property named: "columns"
$('table').find('thead tr').each(function() {
jsonTable.columns = $(this).find('th').text();
};
// now add a new array property which contains your rows: "rows"
$('table').find('tbody tr').each(function() {
var row = {};
// add data by colum names derived from "tbody"
for(var i = 0; i < jsonTable.columnsl.length; i++) {
row[ col ] = $(this).find('td').eq( i ).text();
}
// push it all to the results..
jsonTable.rows.push( row );
};
alert(JSON.stringify(jsonTable));
I think there should be some corrections, but this is it I think.

how to sum columns of html table generated from database in jsp using javascript?

I am working on my site and i want to sum the values in one column of html table using javascript over a jsp. I have found various codes which can add static data which has been put in already but when i use same thing in my code it doesnt work.
The javascript is as follows:-
<script type="text/javascript">
var debugScript = true;
function computeTableColumnTotal(tableId, colNumber)
{
var result = 0;
try
{
var tableElem = window.document.getElementById(tableId);
var tableBody = tableElem.getElementsByTagName("tbody").item(0);
var i;
var howManyRows = tableBody.rows.length;
for (i=1; i<(howManyRows-1); i++) // skip first and last row (hence i=1, and howManyRows-1)
{
var thisTrElem = tableBody.rows[i];
var thisTdElem = thisTrElem.cells[colNumber];
var thisTextNode = thisTdElem.childNodes.item(0);
if (debugScript)
{
window.alert("text is " + thisTextNode.data);
} // end if
// try to convert text to numeric
var thisNumber = parseFloat(thisTextNode.data);
// if you didn't get back the value NaN (i.e. not a number), add into result
if (!isNaN(thisNumber))
result += thisNumber;
} // end for
} // end try
catch (ex)
{
window.alert("Exception in function computeTableColumnTotal()\n" + ex);
result = 0;
}
finally
{
return result;
}
}
function finishTable()
{
if (debugScript)
window.alert("Beginning of function finishTable");
var tableElemName = "hikeTable";
//idhar column define kar raha hai wo
var totalMilesPlanned = computeTableColumnTotal("hikeTable",2);
var totalMilesHiked = computeTableColumnTotal("hikeTable",3);
try
{
var totalMilesPlannedElem = window.document.getElementById("totalMilesPlanned");
document.getElementById("total_1").innerHTML = totalMilesPlanned;
var totalMilesHikedElem = window.document.getElementById("totalMilesHiked");
document.getElementById("total_2").innerHTML = totalMilesHiked ;
}
catch (ex)
{
window.alert("Exception in function finishTable()\n" + ex);
}
return;
}
</script>
This works when html table is like
<html>
<body onload="finishTable();">
<tbody>
<table id="hikeTable" align="center" border="1" bordercolor="lightslategray">
<tr>
<th scope="col">Locations</th>
<th scope="col"> Date </th>
<th >Miles (planned)</th>
<th>Miles (actual)</th>
</tr>
<tr>
<td>Alapocas Woods </td>
<td>02/18/06</td>
<td>1324</td>
<td>1</td>
</tr>
<tr>
<td>Alapocas </td>
<td>02/18/06</td>
<td>1176576523</td>
<td>23</td>
</tr>
<tr>
<td>Alapocas </td>
<td>02/18/06</td>
<td>67</td>
<td>98</td>
</tr>
<tr>
<td colspan="2">Total </td>
<td id="total_1"></td>
<td id="total_2"></td>
</tr>
</tbody>
<table>
</html>
But my table is something like this :-
<html>
<body onload="finishTable();">
<tbody>
<table id="hikeTable" align="center" border="1" bordercolor="lightslategray">
<tr>
<th scope="col">Locations</th>
<th scope="col"> Date </th>
<th >Miles (planned)</th>
<th>Miles (actual)</th>
</tr>
<%Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:#localhost:1521:dir","hr","hr");
java.sql.Statement statement = conn.createStatement();
java.sql.ResultSet rs = statement.executeQuery(searchquery);
while(rs.next()){
int buildarea = rs.getInt("build_area");
int numberoflevels = rs.getInt("no_of_levels");
%>
<tr>
<td>Alapocas Woods </td>
<td>02/18/06</td>
<td><%=buildarea%></td> //here a value comes from database
<td>1</td>
</tr>
<tr>
<td>Alapocas </td>
<td>02/18/06</td>
<td>bumberoflevels</td>
<td>23</td>
</tr>
<td colspan="2">Total </td>
<td id="total_1"></td>
<td id="total_2"></td>
</tr>
</tbody>
<%}%>
<table>
</html>
Please help!!
Just some them over:
int totalBuildArea = 0;
int totalNoOfLevels = 0;
while(rs.next()){
int buildarea = rs.getInt("build_area");
int numberoflevels = rs.getInt("no_of_levels");
%>
...
...
The total row should be out of the loop.
...
...
totalBuildArea += buildarea ;
totalnumberOfLevels += numberoflevels ;
<%}%>
<td colspan="2">Total </td>
<td id="total_1"><%=totalBuildArea %></td>
<td id="total_2"><%=totalnumberOfLevels %></td>
That said,
What you are doing does not sound right at all.
For one, accessing the database from JSP is not a good idea. What you need is a good three tire architecture. You can use frameworks like struts. Or at least have your own Business Logic classes, and call them from your servlet.
Even if this is the only way for whatever reason, your JSP itself does not look correct.
Consider this:
<tr>
<td>Alapocas Woods </td>
<td>02/18/06</td>
<td><%=buildarea%></td> //here a value comes from database
<td>1</td>
</tr>
<tr>
<td>Alapocas </td>
<td>02/18/06</td>
<td>bumberoflevels</td>
<td>23</td>
Part of the data is hardcoded. Part of the data is from the database. The columns are not right. <tr>s don't end. For me this does not look like the actual code. Or it is and you have not put complete effort in giving all the details.
Try working on the JSP. Come up with a structure you want. There can be pieces that you don't know how to do. That is fine. Ask them as questions. We are here to help.
But we can help only when you ask a proper question. One simple rule: Imagine You're Trying To Answer The Question.
I leave it to you on whether you want to do the database calls using a servlet or in the JSP itself. The flow is almost the same.
First you create a class for representing the data on the UI. You have a set of (Location, Date, Planned Miles and Actual miles) and then a total of them.
You may want to create a class to represent this (I have made up the name from the id of the HTML, you may want to give a better name):
class Hike
{
private String location;
private Date date;
private Integer builtArea;
private Integer numberOfLevels;
//And their getters and setters
}
And a HikeData class
class HikeData
{
private List<Hike>;
private Integer totalBuiltArea;
private Integer totalNumberOfLevels;
//And their getters and setters
}
//The database call part is fine:
<%Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn = DriverManager
.getConnection("jdbc:oracle:thin:#localhost:1521:dir","hr","hr");
java.sql.Statement statement = conn.createStatement();
java.sql.ResultSet rs = statement.executeQuery(searchquery);
//Fetch the data and populate the above classes
int totalBuiltArea = 0;
int totalNumberOfLevels = 0;
List<Hike> hikeList = new ArrayList<Hike>();
while(rs.next()){
Hike hike = new Hike();
hike.setLocation(rs.getString("location"));
hike.setDate(rs.getDate("date")));
int builtArea = rs.getInt("build_area");
hike.setBuiltArea(builtArea);
int numberOfLevels = rs.getInt("no_of_levels");
hike.setNumberOfLevels(numberOfLevels);
totalBuiltArea+= builtArea;
totalNumberOfLevels += numberOfLevels;
hikeList.add(hike);
}
HikeData hikeData = new HikeData();
hikeData.setHikeList(hikeList);
hikeData.setTotalNumberOfLevels(totalNumberOfLevels);
hikeData.setTTotalBuiltArea(totalBuiltArea);
//Add the class to request
request.setAttribute("hikeData", hikeData);
The HTML table part is now simpler:
<table id="hikeTable" align="center" border="1" bordercolor="lightslategray">
<tr>
<th scope="col">Locations</th>
<th scope="col"> Date </th>
<th >Miles (planned)</th>
<th>Miles (actual)</th>
</tr>
<%HikeData hikeData = request.getAttribute("hikeData");
for(Hike hike : hikeData.getHikeList())
{%>
<tr>
<td><%=hike.getLocation()%></td>
<td><%=hike.getDate()%></td>
<td><%=hike.getBuiltArea()%></td> //here a value comes from database
<td><%=hike.getnumberOfLevels()%></td>
</tr>
<%}>%>
<tr>
<td colspan="2">Total </td>
<td id="total_1"><%=hikeData.getTotalNumberOfLevels()%></td>
<td id="total_2"><%=hikeData.getTotalBuiltArea()%></td>
</tr>
If you are using a servlet, you move the database part to the servlet or to a service class that is called from the servlet.
If you are continuing with the JSP, you have all these in the JSP itself.
I know adding to request and then retrieving is kind of redundant but I have done so so that if you decide to move this out of the JSP, it is easier.
On a closing Note: This is definitely not the best way to write web apps. There are frameworks to make your job easier and the application maintainable and scalable. For the controller(servlet) part you can use the well known struts framework, [Spring Web flow][2], or the very simple Apache Wicket.
For the business logic part, you can use EJB3 or spring.
For database access you can use hibernate.
None of this is mandatory, but it always good to have at least a MVC framework i not the database and business logic stuff. Struts makes your life very easy.

Rearranging table in JavaScript

I want reorder table rows using JavaScript .
for example take the following dummy table:
<table>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>A</td>
<td>B</td>
<td>C</td>
<td>D</td>
</tr>
<tr>
<td>A1</td>
<td>B1</td>
<td>C1</td>
<td>D1</td>
</tr>
</table>
I want to do this in JavaScript without using jQuery. I want to show the A1,B1,C1,D1.. row as the first row and then 1,2,3,4 row and then A,B,C,D row.
I know that there will be some wait time on the client side but I need to do it in the client side. Is there some generic solution to do this, for any number of rows?
If I understand correctly, you are asking how to take the last row and make it the first row, pushing down the rest. This should do it:
<table id="mytable">
...
</table>
<script type="text/javascript">
var tbl = document.getElementById('mytable');
var rows = tbl.getElementsByTagName('tr');
var firstRow = rows[0];
var lastRow = rows[rows.length];
firstRow.parentNode.insertBefore(lastRow.parentNode.removeChild(lastRow), firstRow);
</script>
Assuming your table does not have nested tables. At which point this would need to be a little smarter. This also assumes you're not using TBODY and THEAD nodes. But I'm sure you can get the idea and enhance it from there.
Do:
var table = ...; // Get reference to table (by ID or other means)
var lastRow = table.rows[table.rows.length - 1];
lastRow.parent.insertBefore(table.rows[0], lastRow);
The best way to solve this in Javascript is:
Give the Tr.. a unique name. for eg: X_Y,X_Z,A_Y,A_Z
Now add a hidden lable or text Box which gives the sorting order from the server i.e When the page renders I want to sort it All the Tr's that have a ID starting with A should come first and All the Z's should come second.
<asp:label id="lblFirstSortOrder" runat="server" style="display:none;">A,X</label>
<asp:label id="lblSecondSortOrder" runat="server" style="display:none;">Z,Y</label>
When the page renders..the order should be A_Z,A_Y,X_Z,X_Y
Before Rendering this is table that comes from the aspx file:
<table>
<tr id='Tr_Heading'>
<td>A</td>
<td>B</td>
</tr>
<tr id="Tr_X_Y">
<td>GH</td>
<td>GH1</td>
</tr>
<tr id="tr_X_Z">
<td>HU</td>
<td>HU1</td>
</tr>
<tr id="tr_A_Z">
<td>JI</td>
<td>JI1</td>
</tr>
<tr id="tr_A_Y">
<td>JI</td>
<td>JI1</td>
</tr>
Script:
function SortAndArrange()
{
var firstList = document.getElementById('lblFirstSortOrder').value;
var secondList = document.getElementById('lblSecondSortOrder').value;
var firstTypes = new Array();
firstTypes = firstList.split(',');
var secondLists = new Array();
secondLists = secondList.split(',');
var refNode = document.getElementById('Tbl_' + firstTypes[0] + "_" + secondTypes[0]);
for (var i = 0; i<firstTypes.length; i++)
{
for (var j = 0; j< secondTypes.length;j++)
{
var TrName = 'Tbl_'+firstTypes[i]+'_'+secondTypes[j];
var FirstSecondTrs = document.getElementById(TrName);
if (FirstSecondTrs)
{
FirstSecondTrs.parentNode.removeChild(FirstSecondTrs);
insertAfter(refNode,FirstSecondTrs);
refNode = FirstSecondTrs;
}
}
}
}
function insertAfter( referenceNode, newNode )
{
referenceNode.parentNode.insertBefore( newNode, referenceNode.nextSibling );
}
I hope you guys get the idea.. for me the sorting order will always come from the server and not from the user of the page...
Thanks a Lot for all the answers.. Apprecite it. Helped me get to this solution.
Thanks,
Ben

Categories