I Need some help with adding interactivity to this page.
I'm new to jQuery and this stuff is probably simple but its been driving me nuts!
Its just a footy team with different players details stored in objects in an array called Squad_list
Squad_List.js
var squad = [
{
number: 1,
pic: 'img/HIBBERD_M_t.png',
name: 'Michael',
surname: 'Hibberd',
height: '186 cm',
weight: '86 kg',
debut: 2011,
position: ['defender'],
games: 85,
goals: 11
},
{
number: 2,
pic: 'img/BELLCHAMBERS_T_t.png',
name: 'Tom',
surname: 'Bellchambers',
height: '202 cm',
weight: '106 kg',
debut: 2008,
position: ['ruck'],
games: 79,
goals: 53
},
{
number: 3,
pic: 'img/CHAPMAN_P_t.png',
name: 'Paul',
surname: 'Chapman',
height: '179 cm',
weight: '87 kg',
debut: 2000,
position: ['foward'],
games: 280,
goals: 366,
goals15: 8
},
];
etc etc
I have different functions to create a listQuery from the Squad_List based on different positions, games played etc ie addListDefender creates a list of players whose position = defender
I have a drawtable function to write the info to the page
I've got a select menu to pick the different listQuery options the values named after the relevant listQuery function it should call
App.js
var listQuery = [];
// Draw table from 'listQuery' array of objects
function drawTable(tbody) {
var tr, td;
tbody = document.getElementById(tbody);
// loop through data source
// document.write(tbody);
for (var i = 0; i < listQuery.length; i++) {
tr = tbody.insertRow(tbody.rows.length);
td = tr.insertCell(tr.cells.length);
td.setAttribute("align", "center");
td.innerHTML = "<p>" + listQuery[i].number + "</p>";
td = tr.insertCell(tr.cells.length);
td.innerHTML = '<img src="' + listQuery[i].pic + '">';
td = tr.insertCell(tr.cells.length);
td.innerHTML = listQuery[i].name + " " + listQuery[i].surname;
td = tr.insertCell(tr.cells.length);
td.innerHTML = listQuery[i].height;
td = tr.insertCell(tr.cells.length);
td.innerHTML = listQuery[i].weight;
td = tr.insertCell(tr.cells.length);
td.innerHTML = listQuery[i].debut;
td = tr.insertCell(tr.cells.length);
if (listQuery[i].position.length > 1) {
td.innerHTML += listQuery[i].position[0] + " / " + listQuery[i].position[1];
} else {
td.innerHTML += listQuery[i].position;
}
td = tr.insertCell(tr.cells.length);
td.innerHTML = listQuery[i].games;
td = tr.insertCell(tr.cells.length);
td.innerHTML = listQuery[i].goals;
td = tr.insertCell(tr.cells.length);
}
}
//Display entire list
var displayList = function() {
listQuery = squad;
};
//Take players from list that position = foward
var addListFoward = function() {
for (i = 0; i < squad.length; i++) {
if (squad[i].position.indexOf("foward") >= 0) {
listQuery.push(squad[i]);
console.log(squad[i]);
}
}
}
//Take players from list whose position = defender
var addListDefender = function() {
for (i = 0; i < squad.length; i++) {
if (squad[i].position === "defender") {
listQuery.push(squad[i]);
console.log(squad[i]);
}
}
}
//Take 10 items from player list in order of most games
var addListGames = function () {
squad.sort(function(a, b){
return b.games-a.games
})
listQuery = squad;
listQuery.length = 10;
}
// Site starts with Display Entire List
displayList();
drawTable("output");
//Generate list query on change select button from select options value
$('#select').change(function() {
});
//display selection from select button onclick go button
$('#go').click(function() {
// alert("go has been click!");
drawTable("output");
});
Basically when the select menu is changed I want to call a function equal to the select value and then redraw the table with the go button.....but the various things I've tried on $('#select') and $('#go') don't work.
Any help much appreciated!!!
<!DOCTYPE html>
<html lang="en">
<head>
<meta cahrset="UTF-8">
<title>Bombers Squad</title>
<link rel="stylesheet" href="css/styles.css">
</head>
<body>
<div class="header">
<div class="main-title">
<h1>Bombers Squad</h1>
</div>
<div class="logo">
<img src="img/logo-2x.png" alt="Bombers logo">
</div>
</div>
<div class="main-field">
<form>
<label for="select">View Bombers Squad:</label>
<select id="select" name="bombers_list">
<option value="displayList">Display Entire List</option>
<option value="addListFoward">Display Fowards</option>
<option value="addListMidfield">Display Midfielders</option>
<option value="addListDefender">Display Defenders</option>
<option value="addListRuck">Display Rucks</option>
<option value="addListGames">Display Most Games</option>
<option value="addGoals2015">2015 Goal kickers</option>
<option value="addBF2015">2015 Best & Fairest Votes</option>
</select>
<button id="go" type="submit">Go</button>
</form>
<table id="players">
<caption>Player Information</caption>
<thead>
<tr>
<th scope="col">Number</th>
<th scope="col">Picture</th>
<th scope="col">Name</th>
<th scope="col">Height</th>
<th scope="col">Weight</th>
<th scope="col">Debut</th>
<th scope="col">Position</th>
<th scope="col">Games</th>
<th scope="col">Goals</th>
</tr>
</thead>
<tbody id="output">
</tbody>
</table>
</div>
<script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="js/squad_list.js"></script>
<script src="js/app.js"></script>
</body>
</html>
JsFidder
Seems you just forget to include jquery or not referenced properly
check the below Answer & working demo
or simply add
$(function(){
$('#select').change(function () {
});
//display selection from select button onclick go button
$('#go').click(function () {
alert("go has been click!");
drawTable("output");
});
})
Related
Apologies for any simple mistakes, this is my first Stack Overflow post and I'm relatively new to coding.
I am attempting to create a website that displays a dynamically generated table using DOM elements. This table's rows and columns have been defined using DOM elements, and it should now populate itself on page load when storeItemOutput() is called from initialize(). It should be pulling the data from a loop through the previously defined and populated array storeItems, and displaying their attributes in the table id "storeItemOutput". It should also get one of five values from a dropdown box, and display items that match the selected category whenever it is changed.
However, I can't get the table itself or it's contents to actually display on the page. I'm unsure what is preventing this, and the lack of any output has left me stumped. Am I missing some code in my function? Is the table not created properly?
I've included parts of my code below, as well as expected output and actual output to try and help you understand my issue.
<select class="categoryDropDown" style="margin: 30px;">
<p>
<option selected value="All" onload="storeItemOutput();">All</option>
<option value="Tops" onchange="storeItemOutput();">Tops</option>
<option value="Bottoms" onchange="storeItemOutput();">Bottoms</option>
<option value="Shoes" onchange="storeItemOutput();">Shoes</option>
<option value="Accessories" onchange="storeItemOutput();">Accessories</option>
</p>
</select>
<table id="storeItemOutput">
<span><strong>| ID | Product Name | Price | Qty | Max | Category | Image |</strong></span>
</br>
<tbody>
<tr>
<th>b</th>
<th>b</th>
<th>b</th>
<th>b</th>
<th>b</th>
<th>b</th>
<th>b</th>
</tr>
<tr>
<td>b</td>
<td>b</td>
<td>b</td>
<td>b</td>
<td>b</td>
<td>b</td>
<td>b</td>
</tr>
</tbody>
(Output all store items via DOM table here)
</table>
This is some of my HTML code with an ID'd dummy table, and a dropdown menu class.
var storeItems = [];
function StoreItem(id, name, price, qtyOnHand, maxPerCust, category, shipping, reviews, description, image) {
this.id = id; //String
this.name = name; //String
this.price = price; //Number
this.qtyOnHand = qtyOnHand; //Number
this.maxPerCust = maxPerCust; //Number
this.category = category; //String
this.shipping = shipping; //Number
this.reviews = reviews; //Array
this.description = description; //String
this.image = image; //String
}
storeItems.push(new StoreItem("Y2k111", "Black Hoodie", 119.99, 10, 1, "Tops", 19.99, this.reviews, "100% Cotton Hoodie in Black", "/img/home_img/link"));
Some Javascript code of creating an empty array for store items, creating an object constructor for store items, and pushing a new item to the array (normally there is more than one item being pushed, I used just one here to save space).
function storeItemOutput() {
var itemTableDiv = document.getElementById("cartItemOutput");
var table = document.createElement("table");
itemTableDiv.innerHTML = "";
document.getElementsByTagName("tbody")[0].remove();
var tBody = document.createElement("tbody");
var headerRow = document.createElement("tr");
var hC1 = document.createElement("th");
var hC2 = document.createElement("th");
var hC3 = document.createElement("th");
var hC4 = document.createElement("th");
var hC5 = document.createElement("th");
var hC6 = document.createElement("th");
var hC7 = document.createElement("th");
hC1.innerHTML = "Item ID";
hC2.innerHTML = "Item Name";
hC3.innerHTML = "Item Price";
hC4.innerHTML = "Item Quantity";
hC5.innerHTML = "Max Items Per Customer";
hC6.innerHTML = "Category";
hC7.innerHTML = "Image";
headerRow.appendChild(hC1);
headerRow.appendChild(hC2);
headerRow.appendChild(hC3);
headerRow.appendChild(hC4);
headerRow.appendChild(hC5);
headerRow.appendChild(hC6);
headerRow.appendChild(hC7);
tbody.appendChild(headerRow);
for (var index = 0; index < storeItems.length; index++) {
var products = storeItems[i];
var theRow = document.createElement("tr");
var c1 = document.createElement("td");
var c2 = document.createElement("td");
var c3 = document.createElement("td");
var c4 = document.createElement("td");
var c5 = document.createElement("td");
var c6 = document.createElement("td");
var c7 = document.createElement("td");
c1.innerHTML = products.id;
c2.innerHTML = products.name;
c3.innerHTML = "$" + products.price.toFixed(2);
c4.innerHTML = products.qtyOnHand;
c5.innerHTML = products.maxPerCust;
c6.innerHTML = products.category;
c7.innerHTML = products.image;
theRow.appendChild(c1);
theRow.appendChild(c2);
theRow.appendChild(c3);
theRow.appendChild(c4);
theRow.appendChild(c5);
theRow.appendChild(c6);
theRow.appendChild(c7);
tbody.appendChild(theRow);
}
itemTableDiv.appendChild(tbody);
var selectedCategory = document.getElementByClass("categoryDropDown").value;
var filteredItems = [];
var index = 0;
while (index < storeItems.length) {
if (storeItems[index].category == selectedCategory) {
filteredItems.push(storeItems[index]);
}
index++;
}
storeItemOutput(filteredItems);
And finally, my function that is meant to create and populate the table, before displaying the items that match the selected category.
Here is an image of what the table should look like:
working table
And the lack of output for my table:
my missing table
Any help would be appreciated.
Here's a working example. A few things worthy of mention:
I've used a template element, since it makes repeatedly creating
similar content very much faster.
Floating-point math has rounding errors. For this reason, I've stored the
prices in cents rather than dollars. Perform all math on the number
of cents, then present it as dollars & cents
A NodeList is very similar to, but slightly different than an array. It does not for instance have a forEach member function. For this reason, I used Array.from in the appendRow function. (which is actually shorter by 1 line if you use the commented code instead)
"use strict";
function newEl(tag) {
return document.createElement(tag)
}
function byId(id) {
return document.getElementById(id)
}
function qs(sel, parent = document) {
return parent.querySelector(sel)
}
function qsa(sel, parent = document) {
return parent.querySelectorAll(sel)
}
window.addEventListener('load', onLoaded, false);
function onLoaded(evt) {
var tableData = [
["PID01", "Fluffy Bear", 599, 600, 20, "Toy", "bear.png"],
["PID02", "Rubber Ducky", 1599, 40, 5, "Toy", "duck.png"],
["PID03", "Cool Handbag", 599, 1, 2, "Fashion", "bag.png"],
["PID04", "Fidget Spinner", 999, 120, 10, "Toy", "spinner.png"],
["PID05", "Lame Handbag", 4599, 60, 3, "Fashion", "bag.png"],
["PID06", "UltraMega Genuine Laptop", 170599, 20, 2, "Technology", "laptop.png"],
];
populateTable(tableData);
var categoryNames = ["All", "Fashion", "Toy", "Technology"];
populateSelect(byId('catSelector'), categoryNames);
qs('select').addEventListener('change', updateFilter, false);
}
function populateSelect(selElem, data) {
selElem.innerHTML = '';
data.forEach(txt => selElem.appendChild(new Option(txt, txt)));
}
function populateTable(data) {
data.forEach(appendRow);
function appendRow(itemData, itemIndex, items) {
let newRow = byId('productRowTemplate').content.cloneNode(true);
let cells = Array.from(newRow.firstChild.cells);
cells.forEach((cell, index) => {
if (index == 2)
cell.textContent = '$' + (itemData[index] / 100).toFixed(2);
else
cell.textContent = itemData[index];
});
// cells[0].textContent = itemData[0];
// cells[1].textContent = itemData[1];
// cells[2].textContent = '$'+(itemData[2]/100).toFixed(2);
// cells[3].textContent = itemData[3];
// cells[4].textContent = itemData[4];
// cells[5].textContent = itemData[5];
byId('storeItemOutput').tBodies[0].appendChild(newRow);
}
}
function updateFilter() {
let filter = byId('catSelector').value;
let prodRows = qsa('#storeItemOutput > tbody > tr');
if (filter == 'All') {
prodRows.forEach(row => row.classList.remove('notShown'));
} else {
prodRows.forEach(
row => {
if (row.cells[5].textContent == filter)
row.classList.remove('notShown');
else
row.classList.add('notShown');
}
);
}
}
.notShown {
display: none;
}
.price,
.qty,
.max {
text-align: right;
}
<template id='productRowTemplate'><tr>
<td class='id'></td>
<td class='name'></td>
<td class='price'></td>
<td class='qty'></td>
<td class='max'></td>
<td class='cat'></td>
<td><img class='icon'/></td>
</tr></template>
<body>
Filter:
<select id='catSelector'></select>
<table id='storeItemOutput'>
<thead>
<tr>
<th>ID</th>
<th>Product</th>
<th>Price</th>
<th>Qty</th>
<th>Max</th>
<th>Category</th>
<th>Image</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</body>
I have array and object data i want to call those together.
var data = [
{"number": "PA1234","name": "John"},
{"number": "JM344","name": "jessi"},
{"number": "ML567","name": "Monty"}
];
var costing= {
"cost": 10,
"cost": 20,
"cost": 30,
};
Display Format in table
<pre>
<table>
<tr>
<td>number</td>
<td>name</td>
<td>cost</td>
</tr>
</table>
<pre>
I have done so far but don't know how to called the object costing
var records=$("<table/>").attr("id","tabs");
$("#table").append(records);
for(var j=0;j<data .length;j++)
{
var tr="<tr>";
var td1="<td>"+data [j]["number"]+"</td>";
var td2="<td>"+data [j]["name"]+"</td>";
$("#tabs").append(tr+td1+td2+td3);
}
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<title>
</title>
<style>
#t, tr, th, td{
border: 1px solid black;
}
</style>
</head>
<body>
<table id="t" cellpadding="10">
<tr>
<th>
Number
</th>
<th>
Name
</th>
<th>
Cost
</th>
</tr>
</table>
</body>
<script>
var number = ['PA1234', 'JM344', 'ML567'], name = ['John', 'Jessi', 'Monty'], costing = [30, 30, 30];
for(var i=0;i<3;i++) {
$("#t").append('<tr><td>' + number[i] + '</td><td>' + name[i] + '</td><td>' + costing[i] + '</td></tr>');
}
</script>
</html>
This is what you want
Had to change some things with your second object, costing. I don't think you can have the same key names on different values, you wouldn't be able to iterate over them. Now you can do two approaches:
var data = [
{"number": "PA1234","name": "John"},
{"number": "JM344","name": "jessi"},
{"number": "ML567","name": "Monty"}
];
var costing = {
"cost0": 10,
"cost1": 20,
"cost2": 30,
};
document.addEventListener("DOMContentLoaded", () => {
const place = document.getElementById("place").firstElementChild
const table = document.createElement("table")
for(let i = 0; i < data.length; i++){
let tr = document.createElement("tr")
let tdNumber = document.createElement("td")
let tdName = document.createElement("td")
let tdCost = document.createElement("td")
tdNumber.innerText = data[i].number
tdName.innerText = data[i].name
tdCost.innerText = costing["cost"+i]
tr.appendChild(tdNumber)
tr.appendChild(tdName)
tr.appendChild(tdCost)
table.appendChild(tr)
}
place.appendChild(table)
})
However personally i would change your costing object to this:
var costing2 = [
10,20,30
]
And change the for loop to this:
for(let i = 0; i < data.length; i++){
let tr = document.createElement("tr")
let tdNumber = document.createElement("td")
let tdName = document.createElement("td")
let tdCost = document.createElement("td")
tdNumber.innerText = data[i].number
tdName.innerText = data[i].name
tdCost.innerText = costing2[i]
tr.appendChild(tdNumber)
tr.appendChild(tdName)
tr.appendChild(tdCost)
table.appendChild(tr)
}
Where place is the spot of the div tag in the html. Not the best solution but it works, putting down the html code aswell if you want that:
<html>
<head>
<script src="./file.js"></script>
</head>
<body>
<div id="place">
<pre>
</pre>
</div>
</body>
</html>
I have these codes already working using plain javascript and got it in W3schools which filtering table data using input text. I added a Select dropdown for filtering table. I've found some answers here but its not working to my codes.
I tried using Jquery but its not working. JQUERY CDN is located at the header
<head>
<script
src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
</head>
<table class="table table-bordered" id = "tbl_main_content">
<thead>
<tr>
<th>Title</th>
<th style = "display: none;">Description</th>
<th>Category</th>
<th style = "display: none;">Status</th>
<th width="400px">Action</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
//my input
<input type="text" class="form-control" id="txt_list_search"
placeholder="Enter keyword..." onkeyup="myFunction()">
//my select
<select class="form-control" id = "sort">
<option >Select Sort</option>
<option value = "HTML">Html</option>
<option value = "JAVASCRIPT">Javascript</option>
<option value = "CSS">Css</option>
<option value = "PHP">PHP</option>
<option value = "LARAVEL">Laravel</option>
<option value = "AJAX">Ajax</option>
</select>
<script>
function myFunction()
{
var input, filter, table, tr, td, i, txtValue;
input = document.getElementById("txt_list_search");
filter = input.value.toUpperCase();
table = document.getElementById("tbl_main_content");
tr = table.getElementsByTagName("tr");
for (i = 0; i < tr.length; i++)
{
td = tr[i].getElementsByTagName("td")[0];
if (td)
{
txtValue = td.textContent || td.innerText;
if (txtValue.toUpperCase().indexOf(filter) > -1)
{
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
var options = $("#sort");
$("#tbl_main_content tr:not(.header)").each(function() {
options.append($("<option />").val($(this).find("td:first-
child").text()).text($(this).find("td:first-child").text()));
});
$("#txt_list_search").on('input', function() {
myFunction($(this).val());
});
$("#sort").on('change', function() {
myFunction($(this).val());
});
</script>
// AJAX METHOD TO DISPLAY DATA FROM DB
<script>
getPageData();
function getPageData() {
$.ajax({
dataType: 'json',
url: url,
data: {page:page}
}).done(function(data){
manageRow(data);
});
}
function manageRow(data) {
console.log(data)
var rows = '';
$.each( data, function( key, value ) {
rows = rows + '<tr>';
if(value.status == 0){
rows = rows + '<td style = "color: #FF0000">'+value.title+'</td>';
} else{
rows = rows + '<td style = "color: #000">'+value.title+'</td>';
}
rows = rows + '<td style = "display: none;">'+value.details+'</td>';
rows = rows + '<td>'+value.category+'</td>';
rows = rows + '<td style = "display: none;">'+value.status+' </td>';
rows = rows + '<td data-id="'+value.id+'">';
rows = rows + '<a href = my-posts-sub/'+value.id+'><button class="btn
btn-secondary manage-sub-item"><img src="/media/icon_manage.png"
width = "20">  <i>Manage Sub</i></button> </a>';
rows = rows + '<button data-toggle="modal" data-target="#edit-item"
class="btn btn-secondary edit-item"><img src="/media/icon_edit.png"
width = "20">  <i>Edit</i></button> ';
rows = rows + '<button class="btn btn-secondary remove-item"><img
src="/media/icon_delete.png" width = "20"></button>';
//---------------------class------bootstrap--variable
rows = rows + '</td>';
rows = rows + '</tr>';
});
$("tbody").html(rows);
}
</script>
The onchange event for select is passing value of the select as an argument to myFunction, but myFunction is not accepting any arguments. Change myFunction to
function myFunction(filter)
{
if (filter == undefined)
filter = document.getElementById("txt_list_search").value.toUpperCase();
var table = document.getElementById("tbl_main_content");
var tr = table.getElementsByTagName("tr");
for (var i = 0; i < tr.length; i++)
{
var td = tr[i].getElementsByTagName("td")[0];
if (td)
{
var txtValue = td.textContent || td.innerText;
if (txtValue.toUpperCase().indexOf(filter) > -1)
{
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
Each time I input another football score, the league table is updated and displayed but it's appended to a list of tables. How do I display only the latest table?
Here is an extract of the html:
<div>
<table id="matches" border="1"> </table>
</div>
<div>
<table id="standings" border="1"> </table>
</div>
<input type="button" value="Update" onclick="update()" />
Here is the javascript that displays the fixtures for inputting scores:
// Display fixtures to input the scores
window.onload = function()
{
table = document.getElementById("matches");
var row;
var cell1;
var cell2;
var cell3;
for (i = 1; i < Results.length; i++)
{
row = table.insertRow(i-1); //table starts row 0 but Results row 1 so i-1 used
cell1 = row.insertCell(0);
cell2 = row.insertCell(1);
cell3 = row.insertCell(2);
cell4 = row.insertCell(3);
cell1.innerHTML = Results[i][0];
cell2.innerHTML = '<input type="number" min="0" max="99"/>'
cell3.innerHTML = '<input type="number" min="0" max="99"/>'
cell4.innerHTML = Results[i][3];
}
}
And here is the code that displays the table after the lastest scores have been inputed:
// Display League Table
standings = document.getElementById("standings");
for (i = 0; i < League.length; i++)
{
row = standings.insertRow(i);
cell1 = row.insertCell(0);
cell2 = row.insertCell(1);
cell3 = row.insertCell(2);
cell4 = row.insertCell(3);
cell5 = row.insertCell(4);
cell6 = row.insertCell(5);
cell7 = row.insertCell(6);
cell8 = row.insertCell(7);
cell1.innerHTML = League[i][0];
cell2.innerHTML = League[i][1];
cell3.innerHTML = League[i][2];
cell4.innerHTML = League[i][3];
cell5.innerHTML = League[i][4];
cell6.innerHTML = League[i][5];
cell7.innerHTML = League[i][6];
cell8.innerHTML = League[i][7];
}
After entering three scores this is what is displayed:
I've tried clearing the league array within javascript but still the same outcome. How do I only display top version of the table? Thanks
Thanks again to comments, and some further googling, the following deletes the table ahead of updating it, unless there's a better way?
for(var i = standings.rows.length - 1; i >= 0; i--)
{
standings.deleteRow(i);
}
Cheers everyone! :)
For your table update/question, focus on the updateRow function. This line does the actual update of contents of row rownum column(<td>) i
rows[rownum].getElementsByTagName('td')[i].innerHTML = coldata[i];
There is more here than just updating the table rows, for that you can review the function updateRow in my name-spaced object. updateRow calls createRow if it needs to (the row at that index does not exist), nothing fancy here, then updates the new row.
I use the array of match objects in matches I created (was not one in the question so I made assumptions) also in the namespace:
matches: [{
match: 1,
score: [{
team: "Ap",
score: 3
}, {
team: "Or",
score: 2
}]
}],
Note where I call this code to update the table for standings in the table with standings-table id. I have no idea what those are so I simply inserted some stuff in the array then update the table using
for (let i = 0; i < myLeague.standings.length; i++) {
myLeague.updateRow('standings-table', myLeague.standings[i], i);
}
Other things: I created the form simply to show how to update the table when a new match is inserted, I trigger an event and it does what it needs to update or insert a row - but really that is just to test the update as new matches are created.
Row in a table are either updated or inserted depending totally on the array of matches content
nothing handles deletions from the table or array since this was just about insert and update
if a row index for a match index does not exist, it creates a new row and updates it
var myLeague = myLeague || {
teamSelect1: "team1",
teamSelect2: "team2",
matchesPlayed: 1,
teams: [{
name: "Apples",
abbreviation: "Ap"
},
{
name: "Oranges",
abbreviation: "Or"
},
{
name: "Pears",
abbreviation: "Pe"
}
],
matches: [{
match: 1,
score: [{
team: "Ap",
score: 3
}, {
team: "Or",
score: 2
}]
}],
standings: [
["A", 2, 1, 1, 3, 2, 3, 0],
["B", 3, 1, 1, 3, 2, 3, 6]
],
cloneRow: function(tableid, objectRef) {
// find table to clone/append to
let table = document.getElementById(tableid);
// find row to clone, I use first one
let firstRow = mytable.rows[0];
// let row = document.getElementById("rowToClone");
let clone = firstRow.cloneNode(true); // copy children too
clone.id = ""; // change id or other attributes/contents
table.appendChild(clone); // add new row to end of table
},
createRow: function(tableid, colCount, rowCount = 1, defaultContent = "") {
let row = document.createElement('tr'); // create row node
for (let i = 0; i < colCount; i++) {
let newText = document.createTextNode(defaultContent);
let col = row.insertCell(i);
col.appendChild(newText);
}
let table = document.getElementById(tableid); // find table to append to
let tbody = table.getElementsByTagName('tbody')[0];
for (let r = 1; r <= rowCount; r++) {
tbody.appendChild(row); // append row to table
}
},
updateRow: function(tableid, coldata = ['$nbsp;'], rownum = 0) {
let table = document.getElementById(tableid); // find table to update to
let tbody = table.getElementsByTagName('tbody')[0];
let rows = tbody.rows; // get rows node
let maxRows = 20; //keep it from going crazy adding rows
while (rows.length < maxRows && !rows[rownum]) {
this.createRow(tableid, coldata.length, 1, "x");
}
//myLeague.updateRow(tableid,coldata, rownum);
for (let i = 0; i < coldata.length; i++) {
rows[rownum].getElementsByTagName('td')[i].innerHTML = coldata[i];
}
},
addTeam: function(team, teamid) {
var sel = document.getElementById(teamid);
var optNew = document.createElement("option");
optNew.value = team.abbreviation;
optNew.text = team.name;
sel.add(optNew, null);
},
addTeamsToSelect: function() {
myLeague.teams.forEach(function(team) {
myLeague.addTeam(team, this.teamSelect1);
myLeague.addTeam(team, this.teamSelect2);
}, this);
},
listMatches: function(event) {
// event.target is the div
let src = event.target.dataset.source;
console.log("src:", src);
document.getElementById("matchplayed").textContent = event.matches;
this[src].forEach(function(item, index, array) {
document.getElementById('matchplayed').textContent = array.length;
let rowdata = [item.score[0].team, item.score[0].score, item.score[1].team, item.score[1].score];
this.updateRow(src, rowdata, index);
}, this);
},
clickAddListener: function(event) {
// 'this' is bound to the namespace object
// console.log(event.target); // the button
// console.log(this.matchesPlayed);//namespace
if (!document.getElementById(this.teamSelect1).value || !document.getElementById(this.teamSelect2).value) {
let errorEl = document.getElementById("form1")
.getElementsByClassName("error-text")[0];
errorEl.textContent = "Both teams need to be selected.";
errorEl.style.visibility = 'visible';
errorEl.style.opacity = '1';
setTimeout(function() {
errorEl.style.WebkitTransition = 'visibility .5s, opacity .5s';
errorEl.style.opacity = '0';
errorEl.style.visibility = 'hidden';
errorEl.textContent = "";
}, 5000);
} else {
this.matchesPlayed++;
let r = {
match: this.matchesPlayed,
score: [{
team: document.getElementById(this.teamSelect1).value,
score: document.getElementById("score1").value
}, {
team: document.getElementById(this.teamSelect2).value,
score: document.getElementById("score2").value
}]
};
this.matches.push(r);
}
document.getElementById('matches').dispatchEvent(this.showmatchesevent);
},
addListeners: function() {
let scope = this;
document.getElementById(this.teamSelect1)
.addEventListener('change', function() {
let s = document.getElementById(scope.teamSelect2);
let oval = s.value;
if (this.value == oval) {
s.value = '';
}
}, this);
document.getElementById(this.teamSelect2)
.addEventListener('change', function() {
let s = document.getElementById(scope.teamSelect1);
let oval = s.value;
if (this.value == oval) {
s.value = '';
}
}, this);
document.getElementById('add-match')
// bind this namespace to the event listener function
.addEventListener('click', (this.clickAddListener).bind(this), false);
this.showmatchesevent = new CustomEvent('showmatches');
document.getElementById('matches')
.addEventListener('showmatches', this.listMatches.bind(this), false);
}
};
window.onload = function() {
myLeague.addTeamsToSelect();
myLeague.addListeners();
for (let i = 0; i < myLeague.standings.length; i++) {
myLeague.updateRow('standings-table', myLeague.standings[i], i);
}
// set table from defaults/imported list
document.getElementById('matches').dispatchEvent(myLeague.showmatchesevent);
};
/* typography */
html {
font-family: 'helvetica neue', helvetica, arial, sans-serif;
}
th {
letter-spacing: 2px;
}
td {
letter-spacing: 1px;
}
tbody td {
text-align: center;
}
.match-inputs {
border: solid 2px #DDDDDD;
padding;
1em;
margin: 1em;
}
.error-text {
height: 1em;
color: red;
}
.matches-played {
padding: 13m;
}
/* table layout */
table {
border-collapse: collapse;
border: 1px solid black;
}
.score th,
td {
padding: 0.2em;
border: solid #DDDDDD 1px;
}
.container {
padding: 1em;
}
<div class="container match-inputs">
<form id="form1">
<div>Add Matches</div>
<div class="input-group"><label>Choose L Team:</label>
<select id="team1">
<option value="">Choose</option>
</select>
</div>
<div class="input-group"><label>Choose L2 Team:</label>
<select id="team2">
<option value="">Choose</option>
</select>
</div>
<div class="input-group score-group"><label>Team1 score:</label>
<input id="score1" type="number" class="score-input" value="0" min="0" max="99" value="0" />
</div>
<div class="input-group score-group"><label>Team2 score:</label>
<input id="score2" type="number" class="score-input" value="0" min="0" max="99" value="0" />
</div>
<div class="input-group"><label>Add this match to the list.</label>
<button type="button" id="add-match">Add Match</button>
</div>
<div class="error-text"> </div>
</form>
</div>
<div class="container">
<div class="matches-played">Matches Played:<span id="matchplayed"></span></div>
<table id="matches" data-source="matches">
<thead>
<tr>
<th colspan="4">Matches</th>
</tr>
<tr>
<th>L</th>
<th>S</th>
<th>S2</th>
<th>L1</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
</div>
<div class="container">
<table id="standings-table">
<thead>
<tr>
<th colspan="8">Standings</th>
</tr>
<tr>
<th>Team</th>
<th>P</th>
<th>W</th>
<th>D</th>
<th>L</th>
<th>F</th>
<th>A</th>
<th>Pts</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
</div>
I am trying to insert multiple rows and columns to create a table in html dynamically by selecting the number of rows and columns in dropdown list using javascript code like in MS Word.
For example if I select number of rows as 5 and number of columns as 5 from the dropdown list of numbers. 5 rows and 5 columns should get displayed.
My question is how can I add multiple rows and columns dynamically to create a table by selecting the number of rows and columns from the drop down list.
Since, <table> element is the one of the most complex structures in HTML, HTML DOM provide new interface HTMLTableElement with special properties and methods for manipulating the layout and presentation of tables in an HTML document.
So, if you want to accomplish expected result using DOM standards you can use something like this:
Demo old
Demo new
HTML:
<ul>
<li>
<label for="column">Add a Column</label>
<input type="number" id="column" />
</li>
<li>
<label for="row">Add a Row</label>
<input type="number" id="row" />
</li>
<li>
<input type="button" value="Generate" id="btnGen" />
<input type="button" value="Copy to Clipboard" id="copy" />
</li>
</ul>
<div id="wrap"></div>
JS new:
JavaScript was improved.
(function (window, document, undefined) {
"use strict";
var wrap = document.getElementById("wrap"),
setColumn = document.getElementById("column"),
setRow = document.getElementById("row"),
btnGen = document.getElementById("btnGen"),
btnCopy = document.getElementById("btnCopy");
btnGen.addEventListener("click", generateTable);
btnCopy.addEventListener("click", copyTo);
function generateTable(e) {
var newTable = document.createElement("table"),
tBody = newTable.createTBody(),
nOfColumns = parseInt(setColumn.value, 10),
nOfRows = parseInt(setRow.value, 10),
row = generateRow(nOfColumns);
newTable.createCaption().appendChild(document.createTextNode("Generated Table"));
for (var i = 0; i < nOfRows; i++) {
tBody.appendChild(row.cloneNode(true));
}
(wrap.hasChildNodes() ? wrap.replaceChild : wrap.appendChild).call(wrap, newTable, wrap.children[0]);
}
function generateRow(n) {
var row = document.createElement("tr"),
text = document.createTextNode("cell");
for (var i = 0; i < n; i++) {
row.insertCell().appendChild(text.cloneNode(true));
}
return row.cloneNode(true);
}
function copyTo(e) {
prompt("Copy to clipboard: Ctrl+C, Enter", wrap.innerHTML);
}
}(window, window.document));
JS old:
(function () {
"use strict";
var wrap = document.getElementById("wrap"),
setColumn = document.getElementById("column"),
setRow = document.getElementById("row"),
btnGen = document.getElementById("btnGen"),
copy = document.getElementById("copy"),
nOfColumns = -1,
nOfRows = -1;
btnGen.addEventListener("click", generateTable);
copy.addEventListener("click", copyTo);
function generateTable(e) {
var newTable = document.createElement("table"),
caption = newTable.createCaption(),
//tHead = newTable.createTHead(),
//tFoot = newTable.createTFoot(),
tBody = newTable.createTBody();
nOfColumns = parseInt(setColumn.value, 10);
nOfRows = parseInt(setRow.value, 10);
caption.appendChild(document.createTextNode("Generated Table"));
// appendRows(tHead, 1);
// appendRows(tFoot, 1);
appendRows(tBody);
(wrap.hasChildNodes() ? wrap.replaceChild : wrap.appendChild).call(wrap, newTable, wrap.firstElementChild);
}
function appendColumns(tElement, count) {
var cell = null,
indexOfRow = [].indexOf.call(tElement.parentNode.rows, tElement) + 1,
indexOfColumn = -1;
count = count || nOfColumns;
for (var i = 0; i < count; i++) {
cell = tElement.insertCell(i);
indexOfColumn = [].indexOf.call(tElement.cells, cell) + 1;
cell.appendChild(document.createTextNode("Cell " + indexOfColumn + "," + indexOfRow));
}
}
function appendRows(tElement, count) {
var row = null;
count = count || nOfRows;
for (var i = 0; i < count; i++) {
row = tElement.insertRow(i);
appendColumns(row);
}
}
function copyTo(e) {
prompt("Copy to clipboard: Ctrl+C, Enter", wrap.innerHTML);
}
}());
If you want to copy generated result to clipboard you can look at answer of Jarek Milewski - How to copy to the clipboard in JavaScript?
You can use this function to generate dynamic table with no of rows and cols you want:
function createTable() {
var a, b, tableEle, rowEle, colEle;
var myTableDiv = document.getElementById("DynamicTable");
a = document.getElementById('txtRows').value; //No of rows you want
b = document.getElementById('txtColumns').value; //No of column you want
if (a == "" || b == "") {
alert("Please enter some numeric value");
} else {
tableEle = document.createElement('table');
for (var i = 0; i < a; i++) {
rowEle = document.createElement('tr');
for (var j = 0; j < b; j++) {
colEle = document.createElement('td');
rowEle.appendChild(colEle);
}
tableEle.appendChild(rowEle);
}
$(myTableDiv).html(tableEle);
}
}
Try something like this:
var
tds = '<td>Data'.repeat(col_cnt),
trs = ('<tr>'+tds).repeat(row_cnt),
table = '<table>' + trs + '</table>;
Then place the table in your container:
document.getElementById('tablePreviewArea').innerHTML = table;
Or with JQuery:
$('#tablePreviewArea').html(table);
Here is the JSFiddle using native js.
Here is the JSFiddle using jQuery.
About the string repeat function
I got the repeat function from here:
String.prototype.repeat = function( num )
{
return new Array( num + 1 ).join( this );
}
I had one sample code...try this and modify it according to your requirement. May it helps you out.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Untitled Document</title>
<style type="text/css">
#mytab td{
width:100px;
height:20px;
background:#cccccc;
}
</style>
<script type="text/javascript">
function addRow(){
var root=document.getElementById('mytab').getElementsByTagName('tbody')[0];
var rows=root.getElementsByTagName('tr');
var clone=cloneEl(rows[rows.length-1]);
root.appendChild(clone);
}
function addColumn(){
var rows=document.getElementById('mytab').getElementsByTagName('tr'), i=0, r, c, clone;
while(r=rows[i++]){
c=r.getElementsByTagName('td');
clone=cloneEl(c[c.length-1]);
c[0].parentNode.appendChild(clone);
}
}
function cloneEl(el){
var clo=el.cloneNode(true);
return clo;
}
</script>
</head>
<body>
<form action="">
<input type="button" value="Add a Row" onclick="addRow()">
<input type="button" value="Add a Column" onclick="addColumn()">
</form>
<br>
<table id="mytab" border="1" cellspacing="0" cellpadding="0">
<tr>
<td> </td>
<td> </td>
</tr>
<tr>
<td> </td>
<td> </td>
</tr>
<tr>
<td> </td>
<td> </td>
</tr>
<tr>
<td> </td>
<td> </td>
</tr>
</table>
</body>
</html>
Instead of button , you can use select menu and pass the value to variable. It will create row ,column as per the value.