I want to create a webpage that loads a selected CSV file (from hard drive) and displays its contents using table HTML.
The project incorporates two components and so far, I've been researching the latter; generating a table out of a nested array in javascript.
For some reason, the columns do not appear the way they should.
My code
<!DOCTYPE html>
<html>
<body>
<table id="1"> </table>
<button onclick="createTable()">Create</button>
<script>
function createTable() {
var array = [[1,2,3],[4,5,6],[7,8,9]];
document.getElementById("1").innerHTML = ""; //Clear.
for (i = 0; i < array.length; i++) {
document.getElementById("1").innerHTML += "<tr>";
for (k = 0; k < array[0].length; k++) {
document.getElementById("1").innerHTML += "<td>" + array[i][k] + "</td>" ;
}
document.getElementById("1").innerHTML += "</tr>";
}
}
</script>
</body>
</html>
Save the table contents to a variable first and set it to the innerHTML afterwards. Everytime you add a <tr> (or any not singleton tag for that matter), the browser immediately renders the closing tag.
Try this:
function createTable() {
var array = [[1,2,3],[4,5,6],[7,8,9]];
var content = "";
array.forEach(function(row) {
content += "<tr>";
row.forEach(function(cell) {
content += "<td>" + cell + "</td>" ;
});
content += "</tr>";
});
document.getElementById("1").innerHTML = content;
}
Because you are planning on using the FileReader API, IE9 support is off the table anyways. Updated the above function to use the 'newer' forEach array function
ADDENDUM
To load a file with javascript you have to use the FileReader HTML5 API. I can give you some pointers as to how you should go about doing this. This is all untested code, but it gives you a little idea what to do
1.Create a input field
<input type="file" id="file" name="file">
2.Trigger a response on change of this input
var file = document.getElementById('file');
file.addEventListener('change', function() {
var reader = new FileReader();
var f = file.files[0];
reader.onload = function(e) {
var CSVARRAY = parseResult(e.target.result); //this is where the csv array will be
};
reader.readAsText(f);
});
3.Parse the result to an array by using split/push. This uses \n as row delimiter and , as cell delimiter.
function parseResult(result) {
var resultArray = [];
result.split("\n").forEach(function(row) {
var rowArray = [];
row.split(",").forEach(function(cell) {
rowArray.push(cell);
});
resultArray.push(rowArray);
});
return resultArray;
}
(or you can use a third party plugin which will parse the CSV for you: papa parse, for instance)
After some long searching, this is probably the most simple and functional script that I could ever come across, also available for free. Although it doesn't deal with the array modification directly, it's easy to edit and elicit your desired results.
Related
This is my entrance into programming, I have been working with JS for
two weeks for school. The project is to build a website for a rug
shop.
This week's assignment is writing a table and populating the fields
using arrays accessed by for loop. The arrays have to be stored in
separate JS page, and functions are in the actual HTML page.
Here are my arrays on its own js page:
function getID()
{
var url = window.location.toString();
var i = 0;
if(url.indexOf("?id=")>0)
{
var start = url.lastIndexOf("?id=")+ 4;
i = url.substring(start);
}
return i;
}
//array containing names of individual rugs in inventory
var aName = new Array();
aName[0] = "Red/Blue3x5";
aName[1] = "Blue/Yellow5x8";
aName[2] = "VintagePersian7x10";
aName[3] = "Oversize.20x20";
//array containing prices on rug inventory
var aPrice = new Array();
aPrice[0] = "$299.00";
aPrice[1] = "$700.00";
aPrice[2] = "$2,999.00";
aPrice[3] = "$25,000.00";
//array containing images individual rugs in inventory
var aImage = Array();
aImage[0] = src="red.blue.3x5.jpg";
aImage[1] = src="blue.yellow.5x8.jpg";
aImage[2] = src="vintage.persian.7x10.jpg";
aImage[3] = src="oversize.20x20.jpg";
Here's the segment of HTML page table where the images should appear
in the first column :
<tbody>
<script type="text/javascript">
//tabel header
document.write("<table border='1' rules='rows' cellspacing='0'>");
document.write("<tr>");
document.write("<th> </th><th>Name</th><th>Price</th><th>Order</th>");
document.write("</tr>");
//loop through aName aray & write results
for (var i =0; i < aName.length ; i++) {
document.write("<tr>");
//initialize empty array
var pictures = [];
//insert place holder
var image = new Image;
//set src attribute
image.src = 'images/' + aImage[i];
pictures.push(image);
document.write("<td>");
document.write("<image src='aImage[i]' width='50' height='20'" + " />");
document.write("</td>");
document.write("<td>" + aName[i] + "</td>");
document.write("<td>" + aPrice[i] + "</td>");
//to create hyperlinks for products
document.write("<td><span class='link'><a href='#' title='price'>price</a></span>");
}
</script>
</tbody>
The table appears with the proper columns, but the place where the
image should appear displays a blank spot, and debugging shows:
"Failed
to load resource: net::ERR_FILE_NOT_FOUND" message.
i cleaned this up a bit and fixed the <img> for you.
i added comments to the code to help you. let me know if you need anything else. please see the notes below for more information about my suggested changes. good luck!
i don't think you need to instantiate new Image objects when
you're writing the <img> tags to the DOM.
i named the external script data.js and i included it with a
<script> tag within the <html> tag.
you need to make sure that the images are saved in a directory
called images on the same level and in the same directory as the
html file. others have mentioned this above. let us know if you need more clarification.
// this is "data.js"
function getID () {
var url = window.location.toString();
var i = 0;
if (url.indexOf("?=") > 0) {
var start = url.lastIndexOf("?id=") + 4;
i = url.substring(start);
}
return i;
}
var aName = [];
aName[0] = "Red/Blue3x5";
aName[1] = "Blue/Yellow5x8";
aName[2] = "VintagePersian7x10";
aName[3] = "Oversize.20x20";
aPrice[0] = "$299.00";
aPrice[1] = "$700.00";
aPrice[2] = "$2,999.00";
aPrice[3] = "$25,000.00";
// new - i fixed the declarations below
var aImage = [];
aImage[0] = "red.blue.3x5.jpg";
aImage[1] = "blue.yellow.5x8.jpg";
aImage[2] = "vintage.persian.7x10.jpg";
<html>
<!-- includes the othe script you created -->
<script type="text/javascript" src="data.js"></script>
<!-- we'll assume there are other tags such as <head> and <body> -->
<tbody>
<!-- your inline js -->
<script type="text/javascript">
// table header
document.write("<table border='1' rules='rows' cellspacing='0'>");
document.write("<tr>");
document.write("<th> </th><th>Name</th><th>Price</th><th>Order</th>");
document.write("</tr>");
// loop through aName aray & write results
for (var i = 0; i < aName.length; i++) {
document.write("<tr>");
document.write("<td>");
// new - i fixed the tag below
var imgSrc = "images/" + aImage[i];
document.write("<img src=" + imgSrc + " width='50' height='20'/>");
document.write("</td>");
document.write("<td>" + aName[i] + "</td>");
document.write("<td>" + aPrice[i] + "</td>");
// new -- not sure where you're getting the hyperlink url's from but i can help with this as well when you figure it out
// to create hyperlinks for products
document.write("<td><span class='link'><a href='#' title='price'>price</a></span>");
}
</script>
</tbody>
<!-- closing other tags -->
</html>
This code still would not display images and returned "Failed to load resource: net::ERR_FILE_NOT_FOUND" error in debugger. I fooled around with your updates and made it work by modifying one line:
document.write("");
changed to:
document.write("");
Now it works perfectly, thank you!!
It cannot find your image files. Check the paths you have set:
src="picture.jpg" = picture.jpg is located in the same folder as the current page
src="images/picture.jpg" = picture.jpg is located in the images folder in the current folder
src="/images/picture.jpg" = picture.jpg is located in the images folder at the root of the current web
src="../picture.jpg" = picture.jpg is located in the folder one level up from the current folder
I am making a program, and I'm wondering why all I see on my html page is the form, but only a single . where the bulleted list for an unordered list should be. I input the user input in the fields, but it doesn't show me the data in the fields, like it's supposed to, when I click submit. Here's the code.
function getFormElements() {
var gather_form_elements = new Array(
$("#first_name").val(),
$("#last_name").val(),
$("email").val(),
$("#phone_number").val()
);
displayValues(gather_form_elements);
}
function displayValues(gather_form_elements) {
for(i=0; i<gather_form_elements.length; i++)
{
document.getElementById("contact_info").innerHTML = "<li>" + gather_form_elements[i] + "</li>";
}
}
Because you are overiding it on every iteration. Try to accumulate the html before using innerHTML like this:
var html = "";
for(var i = 0; i < gather_form_elements.length; i++) {
html += "<li>" + gather_form_elements[i] + "</li>";
// ^^ the += is crucial. If you don't use it, it will just replace the content of html (the innerHTML in your code), we need to use += to append to html instead of overriding it.
}
document.getElementById("contact_info").innerHTML = html;
You can acheive the same result using only one line of code:
document.getElementById("contact_info").innerHTML =
'<li>' + gather_form_elements.join('</li><li>') + '</li>';
I'm have a table with buttons in each row. On every button click I want to pass that row's data to a method. I've done the following
HTML
<body>
<div>
<button onclick="load()" >Click</button>
<table id="roleTable">
<thead>
<tr>
<td>EnterpriseId</td>
<td>Role</td>
<td>UserId</td>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</body>
Javascript
function load() {
var data = JSON.parse(sessionStorage.getItem("loginInfo"));
var html = "";
for (var i = 0; i < data.length; i++) {
html += "<tr><td>" + data[i].ENTERPRISE_ID + "</td>";
html += "<td><button type='button' onclick='loadSegment(data[" + i + "])'>...</button></td>";
html += "<td>" + data[i].USER_ID + "</td></tr>";
}
document.getElementById('roleTable').getElementsByTagName("TBODY")[0].innerHTML = html;
}
function loadSegment(o) {
alert('reading obj');
alert(JSON.stringify(o));
}
The problem is when I click on the button with given code, nothing happens.
But if I move the code of load() function out, the loadSegment method gets called and I'm able to use the object as I want.
Working JS
//function load() { // Commented the function call
var data = JSON.parse(sessionStorage.getItem("loginInfo"));
var html = "";
for (var i = 0; i < data.length; i++) {
html += "<tr><td>" + data[i].ENTERPRISE_ID + "</td>";
html += "<td><button type='button' onclick='loadSegment(data[" + i + "])'>...</button></td>";
html += "<td>" + data[i].USER_ID + "</td></tr>";
}
document.getElementById('roleTable').getElementsByTagName("TBODY")[0].innerHTML = html;
//}
function loadSegment(o) {
alert('reading obj');
alert(JSON.stringify(o));
}
I don't understand why through the second code the method is reachable but not from the first code. If I don't pass object as parameter in the first code then it is able to reach to the loadSegment() function.
Can anybody please help me understand what is the exact issue her. And how can I achieve the function call from the first JS code.
Update
JSON string
[{"USER_ID":"UID00007","ENTERPRISE_ID":"admin1","ROLE":"ADMIN"},
{"USER_ID":"UID00008","ENTERPRISE_ID":"admin2","ROLE":"TESTER"},
{"USER_ID":"UID00009","ENTERPRISE_ID":"admin3","ROLE":"REVIEWER"},
{"USER_ID":"UID00010","ENTERPRISE_ID":"admin4","ROLE":"PMO"},
{"USER_ID":"UID00011","ENTERPRISE_ID":"admin5","ROLE":"MANAGER"},
{"USER_ID":"UID00012","ENTERPRISE_ID":"admin6","ROLE":"DEVELOPER"},
{"USER_ID":"UID00013","ENTERPRISE_ID":"admin7","ROLE":"DBA"}]
In the first example, the data variable exists only within the scope of the load function:
function load() {
var data = JSON.parse(sessionStorage.getItem("loginInfo"));
//...
}
And then you try to reference it outside of that function:
onclick='loadSegment(data[0])'
It doesn't exist at this point, so you can't reference it. By contrast, in the second example you create the data variable in global scope, so it exists on the window object and can be referenced anywhere.
To encapsulate the data variable within that function, you'll need to supply the HTML you're creating with all of the information it needs to call the loadSegment function, not just an index reference. Maybe serialize the whole value into the function call? Maybe put values on data-* attributes? Maybe move all the code into the function except the data variable and keep that on window scope? You have options, depending on what you're trying to achieve overall.
Side note: You might not want to create something called load on the window object (or any other DOM object). If not actual problems, that could cause confusion with other code.
Changing the functionName will help
function loadfun()
{
var data = JSON.parse(sessionStorage.getItem("loginInfo"));
var html = "";
for (var i = 0; i < data.length; i++) {
html += "<tr><td>" + data[i].ENTERPRISE_ID + "</td>";
html += "<td><button type='button' onclick='loadSegment(data[" + i + "])'>...</button></td>";
html += "<td>" + data[i].USER_ID + "</td></tr>";
}
document.getElementById('roleTable').getElementsByTagName("TBODY")[0].innerHTML = html;
}
function loadSegment(o) {
alert('reading obj');
alert(JSON.stringify(o));
}
What I'm trying to do is pretty simple: Add a 1x20 table of input cells inside a div.
I created a JavaScript function
var tableHTML = function(attributes, rows, columns)
{
var retHTML = "<table " + attributes + ">";
for (var i = 0; i < rows; ++i)
{
retHTML += "<tr>";
for (var j = 0; j < columns; ++j)
retHTML += "<td> </td>";
retHTML += "</tr>";
}
return (retHTML + "</table>retHTML");
}
to give me the HTML for a table with a specified dimensions and attributes. Then, in the body of my HTML, I put
<div class="inner_div" id="input_table">
<!-- div to house the table -->
</div>
<script type="text/javascript">
document.getElementById("input_table").innerHTML += tableHTML("id=\"input_table\" type=\"input\"", 1, 20);
</script>
which I thought would accomplish the task, but hasn't. I think this is because I'm trying to assign a string object to an HTML object. I kinda assumed that an implicit cast would be made. Anyways, I'm wondering if anyone has a "quick fix" to my problem. I would prefer not to redo my entire approach to the problem, but I also wouldn't mind someone informing me of the proper way to do the type of thing I'm trying to do -- using JavaScript to fill in page HTML on load.
Here's my take on this. I'm learning functional programming, so I do a bunch things here that might seem like their a waste of coding, but here's the concept:
Get the dimensions
Create a single row
Copy that row to make the table
After that return the table.
If you want to add id's, class's, etc... work with the DOM element returned by makeTable.
// Makes a single row
var makeRow = function(_columns) {
var row = document.createElement('tr');
var cell = document.createElement('td');
var cols = _columns;
while (cols) {
row.appendChild(cell.cloneNode(true));
cols--;
}
return row;
}
// Makes a table
var makeTable = function(_rows, _columns) {
var table = document.createElement('table');
var row = makeRow(_columns);
var rows = _rows;
while (rows) {
table.appendChild(row.cloneNode(true));
rows--;
}
return table;
}
I tried your code and it works: the table is generated and obviously empty
But be carrefull: if you do this, you will have two elements with the same ID (input_table)
I have this JSON which generates a table :
function show(json)
{
var content = '<table id = "myTable" border = 1>';
var counter;
for(counter = 0; counter < json.length ; counter++)
{
content += '<tr><td class = "topics">' + json[counter]['topic_name'] + '</td>''</tr>';
}
content += '</table>';
$('#table_here').append(content);
}
I call it two times :
1st. here :
$(document).ready(function(){
$.getJSON("admin.php", show);
Second when I add something on the table:
When I add something, the new table appears below the old one, I want to lose the old one and see only the new one. How can I do it?
try to change
$('#table_here').append(content);
into
$('#table_here').html(content);
this will replace the entire content of #table_here element