HTML Table Not Updating With CSS - javascript

I am attempting to make a table that has the equivalent of the Bootstrap table-hover feature along with the table-striped feature. However, the CSS does not seem to be applying properly. The th styling is applying however none of the rows are. Additionally, I know the toAppend lines should probably be more clear but that is not my current concern.
This is what the table currently looks like:
JavaScript:
function fortniteSearch(data) {
// data to retrieve data / construct table
const tableCells = [
{category: "lifeTimeStats", stats: [8, 9, 10, 11, 7, 2, 4, 5]},
{category: "stats", subcategory: "p2", stats: ["top1", "winRatio", "kills", "kd", "kpg", "matches", "top10", "top25"]},
{category: "stats", subcategory: "p10", stats: ["top1", "winRatio", "kills", "kd", "kpg", "matches", "top5", "top12"]},
{category: "stats", subcategory: "p9", stats: ["top1", "winRatio", "kills", "kd", "kpg", "matches", "top3", "top6"]}];
// cell labels and flag
const gameModes = ["OVERALL:", "SOLO:", "DUO:", "SQUADS:"];
// check for errors
if(data.error !== undefined)
alert("Player not found!");
else {
// set player name and image
$("#playerName").val(data.IGN);
$("#playerIcon").attr("src", "/images/avatar_fortnite.png");
// show stats
$("#statDisplay").fadeIn(500);
// clear pre-existing table
$("#statTable").empty();
// iterate through the table
for(let i = 0; i < tableCells.length; i++) {
// set header row
$("#statTable").append('<thead> <tr> <th align = "center" colspan = 8> <b> <u>' + gameModes[i] + "</u> </b> </th> </tr> </thead> <tbody> <tr>");
// intialize stats
let toAppend;
// iterate through stats
for(let j = 0; j < tableCells[i].stats.length; j++) {
// if there is no sub-category (use different html)
if(tableCells[i].subcategory === undefined)
toAppend = ("<td> <b>" + data[tableCells[i].category][tableCells[i].stats[j]].key + ":</b>" + "<br>" + data[tableCells[i].category][tableCells[i].stats[j]].value + "</td>");
else
toAppend = ("<td> <b>" + data[tableCells[i].category][tableCells[i].subcategory][tableCells[i].stats[j]].label + ":</b>" + "<br>" + data[tableCells[i].category][tableCells[i].subcategory][tableCells[i].stats[j]].value + "</td>");
// add html
$(".statTable").append(toAppend);
}
// close table row
$(".statTable").append("</tr> </tbody>");
}
// hide game window
$("#gameSelect").css("display", "none");
}
}
CSS:
#statTable {
width: 95%;
height: 10%;
margin-left: auto;
margin-right: auto;
margin-top: 10px;
text-align: center;
border: 1px solid black;
background-color: white;
}
#statTable th {
background-color: green;
color: white;
text-align: center;
}
#statTable tr:nth-child(even) {
background: grey;
}
#statTable tr:hover td {
background-color: red;
}
HTML:
<body>
<div class = "standardImage" id = "statDisplay">
<div name = "statBanner" id = "statBanner" class = "statBanner">
<img src = "/images/icon_xbox.png" name = "playerIcon" class = "playerIcon" id = "playerIcon" alt = "Player Icon">
<input name = "playerName" class = "playerName" id = "playerName" readonly>
<span name = "statButtons" id = "statButtons" class = "statButtons">
<button name = "backButton" class = "backButton" id = "backButton"> BACK </button>
<button name = "refreshButton" class = "refreshButton" id = "refreshButton"> REFRESH </button>
</span>
</div>
<table class = "statTable" id = "statTable"> <thead> </thead> <tbody> </tbody> </table>
</div>
</body>

Related

Javascript set value of specific table cell

I am having an issue with populating an HTML table with the correct data dynamically via javascript and jQuery.
The table shows some numbers based on gender, and every time the user makes a selection, they get back new data from the server, which populates the table. There are two rows and 4 cells. I dynamically insert the cells and update the text via javascript every time the API returns new data. The problem is that the data is being populated in the wrong table cells -- the number for "female / cell 2" ends up in the "female / cell 3" and so forth. I can't figure out how to target the correct cells based on the data. Here is a minimal reproduction via codepen, or see below for code as well:
Also I did look at the following threads but didn't see anything that seemed like it addressed my issue:
s/o thread 1 -----
s/o thread 2
The data is very simple and looks like this -- there are positive, neutral, and negative percentages for female and male:
let genderData = [
{ gender: "female", percent: 36, score: "neutral" },
{ gender: "female", percent: 1, score: "negative" },
{ gender: "female", percent: 18, score: "positive" },
{ gender: "male", percent: 27, score: "neutral" },
{ gender: "male", percent: 14, score: "positive" },
{ gender: "male", percent: 1, score: "negative" }
];
The HTML table looks like this, with the header row hard-coded in HTML:
<!-- Gender Table -->
<table id="sentiment-table__gender" class="table">
<thead class="sticky">
<tr id="sentiment-gender-tr">
<!-- gender -->
<th class="sticky left-align table-th">Gender</th>
<!-- percent positive posts -->
<th class="sticky right-align table-th">Positive Posts</th>
<!-- percent neutral posts -->
<th class="sticky right-align table-th">Neutral Posts</th>
<!-- percent Negative posts -->
<th class="sticky right-align table-th">Negative Posts</th>
</tr>
</thead>
<tbody id="sentiment-page-table__body"></tbody>
</table>
What I need to do is populate the table with the percentages for each sentiment, categorized by gender. The "female" item with a "neutral" score of "36%" should appear in the female row / cell 2 (neutral), but instead appears in a different cell. I suspect this is because the data is not in a specific order, so I can't just populate the cells one by one. I can't change anything about the backend or how the data is returned.
I loop through the data, and then write conditionals to separate the female and male data. Then I write a switch statement based on the sentiment and insert cells for each item. I know what I'm missing is some way to specify which cell the data point should be inserted into. I tried specifying it by saying newFemaleRow.insertCell(2) (or whichever cell I wanted to target), but that threw an error:
sentiment.js:280 Uncaught DOMException:
Failed to execute 'insertCell' on 'HTMLTableRowElement':
The value provided (2) is outside the range [-1, 1].
See below for a full snippet including my JS, and here's that codepen link one more time too.
$(function () {
populateTable();
});
let genderData = [
{ gender: "female", percent: 36, score: "neutral" },
{ gender: "female", percent: 1, score: "negative" },
{ gender: "female", percent: 18, score: "positive" },
{ gender: "male", percent: 27, score: "neutral" },
{ gender: "male", percent: 14, score: "positive" },
{ gender: "male", percent: 1, score: "negative" }
];
const populateTable = () => {
// Local variables
let genderTable = $("#sentiment-table__gender");
// Store table id in variable
let tableRef = document.getElementById("sentiment-table__gender");
// Clear out table data before loading new results
$(tableRef).find("tr:gt(0)").remove();
let newMaleRow = tableRef.insertRow(-1);
let newFemaleRow = tableRef.insertRow(-1);
let maleGenderCell = newMaleRow.insertCell(0);
let maleGenderText = document.createTextNode("Male");
maleGenderCell.className = "left-align";
maleGenderCell.appendChild(maleGenderText);
let femaleGenderCell = newFemaleRow.insertCell(0);
let femaleGenderText = document.createTextNode("Female");
femaleGenderCell.className = "left-align";
femaleGenderCell.appendChild(femaleGenderText);
// Loop through the data to populate the table
for (let item of genderData) {
// MALE
if (item.gender === "male") {
switch (item.score) {
case "negative":
let negativeMalePostsCell = newMaleRow.insertCell();
let negativeMalePostsText = document.createTextNode(
item.percent.toLocaleString("en-US") + "%"
);
negativeMalePostsCell.className = "right-align";
negativeMalePostsCell.appendChild(negativeMalePostsText);
break;
case "neutral":
let neutralMalePostsCell = newMaleRow.insertCell();
let neutralMalePostsText = document.createTextNode(
item.percent.toLocaleString("en-US") + "%"
);
neutralMalePostsCell.className = "right-align";
neutralMalePostsCell.appendChild(neutralMalePostsText);
break;
case "positive":
let positiveMalePostsCell = newMaleRow.insertCell();
let positiveMalePostsText = document.createTextNode(
item.percent.toLocaleString("en-US") + "%"
);
positiveMalePostsCell.className = "right-align";
positiveMalePostsCell.appendChild(positiveMalePostsText);
break;
}
}
// FEMALE
if (item.gender === "female") {
switch (item.score) {
case "negative":
let negativeFemalePostsCell = newFemaleRow.insertCell();
let negativeFemalePostsText = document.createTextNode(
item.percent.toLocaleString("en-US") + "%"
);
negativeFemalePostsCell.className = "right-align";
negativeFemalePostsCell.appendChild(negativeFemalePostsText);
break;
case "neutral":
let neutralFemalePostsCell = newFemaleRow.insertCell();
let neutralFemalePostsText = document.createTextNode(
item.percent.toLocaleString("en-US") + "%"
);
neutralFemalePostsCell.className = "right-align";
neutralFemalePostsCell.appendChild(neutralFemalePostsText);
break;
case "positive":
let positiveFemalePostsCell = newFemaleRow.insertCell();
let positiveFemalePostsText = document.createTextNode(
item.percent.toLocaleString("en-US") + "%"
);
positiveFemalePostsCell.className = "right-align";
positiveFemalePostsCell.appendChild(positiveFemalePostsText);
break;
}
}
}
};
/* ==================================================
Table styling
================================================== */
.table {
text-overflow: wrap;
border-collapse: collapse;
border-spacing: 0;
width: 80%;
border: 1px solid #ddd;
position: relative;
}
/* GENERAL TABLE STYLING */
.sticky {
position: sticky;
position: -webkit-sticky;
top: -1px;
background: white;
}
.table-th,
.table td {
padding: 8px;
height: 40px;
}
.right-align {
text-align: right;
}
.center-align {
text-align: center;
}
.left-align {
text-align: left;
}
.table tr:nth-child(even) {
background-color: orange;
}
.border {
border-bottom: 1px inset black;
}
<!-- jQuery -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<!-- jQuery UI -->
<script src="https://code.jquery.com/ui/1.13.1/jquery-ui.js"></script>
<!-- Gender Table -->
<table id="sentiment-table__gender" class="table">
<colgroup>
<col span="1" />
<col span="1" />
<col span="1" />
<col span="1" />
</colgroup>
<thead class="sticky">
<tr id="sentiment-gender-tr">
<!-- gender -->
<th class="sticky left-align table-th">Gender</th>
<!-- percent positive posts -->
<th class="sticky right-align table-th">Positive Posts</th>
<!-- percent neutral posts -->
<th class="sticky right-align table-th">Neutral Posts</th>
<!-- percent Negative posts -->
<th class="sticky right-align table-th">Negative Posts</th>
</tr>
</thead>
<tbody id="sentiment-page-table__body"></tbody>
</table>
Shoot, this should have been easy. I simply need to insert the JS dynamically in the same order as the HTML! All I did was switch around the order of the cases in the switch statement to match the order of the cells in the table header, and boom, all the data populated in the correct cell.
Here is an updated codepen
$(function () {
populateTable();
});
let genderData = [
{ gender: "female", percent: 36, score: "neutral" },
{ gender: "female", percent: 1, score: "negative" },
{ gender: "female", percent: 18, score: "positive" },
{ gender: "male", percent: 27, score: "neutral" },
{ gender: "male", percent: 14, score: "positive" },
{ gender: "male", percent: 1, score: "negative" }
];
const populateTable = () => {
// Local variables
let genderTable = $("#sentiment-table__gender");
// Store table id in variable
let tableRef = document.getElementById("sentiment-table__gender");
// Clear out table data before loading new results
$(tableRef).find("tr:gt(0)").remove();
let newMaleRow = tableRef.insertRow(-1);
let newFemaleRow = tableRef.insertRow(-1);
let maleGenderCell = newMaleRow.insertCell(0);
let maleGenderText = document.createTextNode("Male");
maleGenderCell.className = "left-align";
maleGenderCell.appendChild(maleGenderText);
let femaleGenderCell = newFemaleRow.insertCell(0);
let femaleGenderText = document.createTextNode("Female");
femaleGenderCell.className = "left-align";
femaleGenderCell.appendChild(femaleGenderText);
// Loop through the data to populate the table
for (let item of genderData) {
// MALE
if (item.gender === "male") {
switch (item.score) {
case "neutral":
let neutralMalePostsCell = newMaleRow.insertCell();
let neutralMalePostsText = document.createTextNode(
item.percent.toLocaleString("en-US") + "%"
);
neutralMalePostsCell.className = "right-align";
neutralMalePostsCell.appendChild(neutralMalePostsText);
break;
case "negative":
let negativeMalePostsCell = newMaleRow.insertCell();
let negativeMalePostsText = document.createTextNode(
item.percent.toLocaleString("en-US") + "%"
);
negativeMalePostsCell.className = "right-align";
negativeMalePostsCell.appendChild(negativeMalePostsText);
break;
case "positive":
let positiveMalePostsCell = newMaleRow.insertCell();
let positiveMalePostsText = document.createTextNode(
item.percent.toLocaleString("en-US") + "%"
);
positiveMalePostsCell.className = "right-align";
positiveMalePostsCell.appendChild(positiveMalePostsText);
break;
}
}
// FEMALE
if (item.gender === "female") {
switch (item.score) {
case "neutral":
let neutralFemalePostsCell = newFemaleRow.insertCell();
let neutralFemalePostsText = document.createTextNode(
item.percent.toLocaleString("en-US") + "%"
);
neutralFemalePostsCell.className = "right-align";
neutralFemalePostsCell.appendChild(neutralFemalePostsText);
break;
case "negative":
let negativeFemalePostsCell = newFemaleRow.insertCell();
let negativeFemalePostsText = document.createTextNode(
item.percent.toLocaleString("en-US") + "%"
);
negativeFemalePostsCell.className = "right-align";
negativeFemalePostsCell.appendChild(negativeFemalePostsText);
break;
case "positive":
let positiveFemalePostsCell = newFemaleRow.insertCell();
let positiveFemalePostsText = document.createTextNode(
item.percent.toLocaleString("en-US") + "%"
);
positiveFemalePostsCell.className = "right-align";
positiveFemalePostsCell.appendChild(positiveFemalePostsText);
break;
}
}
}
};
/* ==================================================
Table styling
================================================== */
.table {
text-overflow: wrap;
border-collapse: collapse;
border-spacing: 0;
width: 80%;
border: 1px solid #ddd;
position: relative;
}
/* GENERAL TABLE STYLING */
.sticky {
position: sticky;
position: -webkit-sticky;
top: -1px;
background: white;
}
.table-th,
.table td {
padding: 8px;
height: 40px;
}
.right-align {
text-align: right;
}
.center-align {
text-align: center;
}
.left-align {
text-align: left;
}
.table tr:nth-child(even) {
background-color: orange;
}
.border {
border-bottom: 1px inset black;
}
<!-- jQuery -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<!-- jQuery UI -->
<script src="https://code.jquery.com/ui/1.13.1/jquery-ui.js"></script>
<!-- Gender Table -->
<table id="sentiment-table__gender" class="table">
<colgroup>
<col span="1" />
<col span="1" />
<col span="1" />
<col span="1" />
</colgroup>
<thead class="sticky">
<tr id="sentiment-gender-tr">
<!-- gender -->
<th class="sticky left-align table-th">Gender</th>
<!-- percent neutral posts -->
<th class="sticky right-align table-th" id='neutral-posts-th'>Neutral Posts</th>
<!-- percent Negative posts -->
<th class="sticky right-align table-th" id='negative-posts-th'>Negative Posts</th>
<!-- percent positive posts -->
<th class="sticky right-align table-th" id='positive-posts-th'>Positive Posts</th>
</tr>
</thead>
</table>

How do I display a dynamically created html table only once?

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>

Getting a bootstrap table row to change colors based off of json data

I have a Bootstrap table with hover functionality, that populates with data retrieved from Twitch's JSON API.
It works fairly well, but I want, based off of a certain JSON variable (whether or not the user is offline) for the table row to change colors.
The full code is here, and the most relevant JS snippets is below:
if (gameContent == null) {
statusText = "Offline...";
gameText = "Nothin'";
row.addClass("offline");
$("td", row).each(function() {
$(td).addClass("offline");
});
}
The offline class has a different background color.
The thing is, with row.addClass down being commented out, everything else works, but if those things aren't commented out, then those rows disappear completely, including text. And it seems like (through the Inspector) the class isn't being added to the tr or td elements at all, but for some reason, the text is getting wiped instead. I just feel like I'm looking at the wrong portion of the code. Any ideas?
You don't need ot add class to the row instead add it to all the td inside row using
$("td", row).each(function() {
$(this).addClass("offline");
});
updated codepen
//jquery
$(document).ready(function() {
//streamers
var streamers = [
"ESL_SC2",
"OgamingSC2",
"cretetion",
"freecodecamp",
"storbeck",
"habathcx",
"RobotCaleb",
"noobs2ninjas",
"no_account_friend"
];
var num_streamers = streamers.length;
//fcc info/call
var url = "https://wind-bow.gomix.me/twitch-api/channels/";
var gameUrl = "https://go.twitch.tv/directory/game/";
var tbody = document.getElementById("streamers");
//stream parser
function add_row(url_parsed) {
$.getJSON(
url_parsed,
function(data) {
if (data.status === 404) {
return;
}
//set logo, status, game
var logoImg = data.logo;
var statusContent = data.status;
var gameContent = data.game;
if (logoImg == null) {
logoImg =
"https://static-cdn.jtvnw.net/jtv_user_pictures/xarth/404_user_600x600.png";
}
//insert rows/cells
var row = tbody.insertRow(tbody.rows.length);
var logo = row.insertCell(0);
var name = row.insertCell(1);
var status = row.insertCell(2);
var game = row.insertCell(3);
//set text/html for cells
var logoText =
"<img src='" +
logoImg +
"' alt='" +
data.display_name +
" logo' height=50 width=50>";
var nameText =
"<a href='" + data.url + "'>" + data.display_name + "</a>";
var statusText, gameText;
//check if game is null
if (gameContent == null) {
statusText = "Offline...";
gameText = "Nothin'";
/* --problem code here*/
// row.addClass("offline");
// row.className ="offline";
$("td", row).each(function() {
$(this).addClass("offline");
});
} else {
statusText = statusContent;
gameText =
"<a href='" + gameUrl + gameContent + "'>" + gameContent + "</a>";
}
$(logo).append(logoText);
$(name).append(nameText);
$(status).append(statusText);
$(game).append(gameText);
}
);
} //end add_row
//for each streamer in list
for (i = 0; i < num_streamers; i++) {
add_row(url + streamers[i] + "?callback=?");
}
});
#import url('https://fonts.googleapis.com/css?family=Play|Bungee+Shade');
header {
font-family: "Bungee Shade", Arial, sans-serif;
}
body {
background-color: #a895cc;
}
table {
font-family: "Play", Arial, sans-serif;
text-align: left;
}
.offline {
background-color: #aeb2b2;
}
th {
background-color: #cc949d;
}
td {
background-color: #94ccc3;
}
tr:hover td {
background-color: #b9d38d;
}
img {
border-radius: 10px;
}
thead {
background-color: #8e9cb2;
}
tbody {
background-color: #afc0db;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container text-center">
<header>
<h1>Twitch Streamers via Twitch API</h1>
<h2>Coming to you from Free Code Camp</h2>
</header>
<table class="table table-hover">
<thead>
<tr>
<th>
Logo:
</th>
<th>
Display Name:
</th>
<th>
Streaming:
</th>
<th>
Game/Activity:
</th>
</tr>
</thead>
<tbody id="streamers">
</tbody>
</table>
</div>
P.S row.className = 'offline'; will work instead of row.addClass("offline"); but that won't change any colour of row. You are getting complete row like this <tr><td></td><td></td>... using javascript function and not jquery that's why row.addClass("offline"); is throwing error and thus further js don't run for that thus no data in row
You looking at the correct code. please do like this.
Just add this in your code
row.className = 'offline';
Please see the updated code
if (gameContent == null) {
statusText = "Offline...";
gameText = "Nothin'";
row.className = 'offline';
this will change the color of the columns inside the row
tr.offline td{
background-color: red;
}

Moving an image from one <td> to another <td> on the same table

So I'm doing this school project. And I'm stuck with the main logic. I'm doing a Checkers game. I got all checker board and checker pieces, the problem is its movement.
Basically, I just want it so that when I click the image from one //td// and click to another //td//, the image moves or transfers to the new //td//. I used ID attributes for //td// as a friend suggested maybe I could start from there.
Thanks so much :)
<html>
<head>
<style>
body { background-color: #D1CDDF; }
p { font-family: Verdana, Geneva, sans-serif;
font-size: 30; }
img { width: 35px;
height: 35px; }
label { font-family: "Lucida Console", Monaco, monospace;
font-size: 15; }
.focused{ border: 2px solid yellow; }
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script>
<script>
function saveScore() {
// syntax: $.post(URL,data,callback);
$.post("scores.php",
{
TheFile: $("#filename").val(),
TheMessage: $("#winner").val() + "\r\n"
}
,function(dataFromtheServer) {
$("#result").html(dataFromtheServer);
});
}
function openBoard()
{
$(document).ready(function()
{
var p1Name = document.getElementById("p1name").value;
var p2Name = document.getElementById("p2name").value;
var heading = "<center><p><font color=\"#cc33ff\">" + p1Name + " vs " + p2Name + "</font></p></center>";
var table = $('<table width=500px cellspacing=0px cellpadding=0px border=1px ></table>');
var rc;
var picName;
var picName2;
for( y = 1; y <= 8; y++ )
{
var row = $('<tr></tr>');
for ( var x = 1; x <= 8; x++)
{
rc = y + x;
// creating the images
picName = "p" + 1 + ".png" ;
var pic1 = $('<img>').attr('src',picName);
picName2 = "p" + 2 + ".png";
var pic2 = $('<img>').attr('src',picName2);
if(rc % 2 === 0)
{
if(y === 1 || y === 2 || y === 3)
{
var col1 = $('<td align=center height=50px width=50px bgcolor=#4E9660 ></td>').attr('id',y + '-' + x);
col1.html(pic1);
row.append(col1);
}
else if(y === 6 || y === 7 || y === 8)
{
var col2 = $('<td align=center height=50px width=50px bgcolor=#4E9660 ></td>').attr('id',y + '-' + x);
col2.html(pic2);
row.append(col2);
}
else
{
var col3 = $('<td align=center height=50px width=50px bgcolor=#4E9660 ></td>').attr('id',y + '-' + x);
row.append(col3);
}
}
else
{
var col4 = $('<td align=center height=50px width=50px bgcolor=#C4C160 ></td>').attr('id',y + '-' + x);
row.append(col4);
}
}
table.append(row);
}
document.getElementById("bBoard").style.visibility = "hidden";
$('#board').append(heading);
$('#board').append(table);
$(function()
{
$('img').click(function()
{
$('img').removeClass('focused');
$(this).addClass('focused');
$(this).setPosition()
});
});
});
}
</script>
</head>
<body>
<center>
<p>~Checkers~</p>
<table border=1 cellpadding=25px>
<tr><td><label>Player 1: <input type=text id=p1name /></label><br/><br/>
<label>Player 2: <input type=text id=p2name /></label><br/><br/>
<button id="bBoard" onclick="openBoard();">Start Game</button><br/><br/></td>
<td><div class="b" id="board"></div></td>
<td>
<input type=hidden id=filename value="players.txt" />
<label>Register Winner: <input type=text id=winner /></label><br/><br/>
<button id="bReg" onclick="saveScore();">Submit</button><br/><br/>
<div id="result"></div>
</td>
</td></tr>
</table>
</center>
</body>
All you need to do is get a DOM reference to the img element in quesiton and then call .appendChild(thatImgElement) on the td that it should be moved to.
Here's a simple example:
// Get reference to image to be moved
var img = document.getElementById("checkmark");
img.addEventListener("click", function(){
// Get reference to target container
var rightCell = document.getElementById("right");
// Move image into target
rightCell.appendChild(this);
});
table { width:300px; height:50px; }
table,td { border: 1px solid black; }
td { width: 50%; }
img { width:30px; }
<table>
<tr>
<td id="left"><img id="checkmark" src="https://i.stack.imgur.com/hyKmt.jpg"></td>
<td id="right"></td>
</tr>
</table>

Javascript / Jquery Help - Calling functions from select menu

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");
});
})

Categories

Resources