Ternary operator in Template Literal HTML TABLE - javascript

I am trying to set my table data to have a background color of red if it has a "Failed" status. I am having a hard time setting this inline style. At first I tried to use the ternary operator in the second td of the createTableData function but could not get it to work. Right now I am attempting to break it out into its own function but not working either.
Looking for help on setting the background color of my table data.
HTML
<body>
<div class="container-fluid">
<div class="jumbotron">
<h1 class="text-center mb-3">
Active Directory Replication Health
</h1>
</div>
<div id="table"></div>
</div>
<script src="js/jquery-3.3.1.min.js"></script>
<script src="js/bootstrap.bundle.min.js"></script>
<script src="js/script.js"></script>
Script
var data = [
{
"DC": "SV07CTDC1",
"Connectivity": "Passed",
"Advertising": "Failed"
},
{
"DC": "SVGCCTDC1",
"Connectivity": "Passed",
"Advertising": "Failed"
}
];
function checkStatus(status) {
status === "Failed" ? "background-color: red" : "background-color: blue"
}
function createTableData(dc ){
var html = ''
for( key in dc )
html += `
<tr>
<td> ${key} </td>
<td style=${checkStatus(dc[key])} > ${dc[key]} </td>
</tr>
`
return html
}
function createTable(dc) {
return `
<div class="col-md-3 col-sm-6 ">
<table class="table table-dark table-striped table-bordered table-hover">
${createTableData(dc)}
</table>
</div>
`
}
document.getElementById("table").innerHTML = `
<div class="row">
${data.map(createTable).join("")}
</div>
`

The only thing you're missing in your checkStatus method is to return the condition result;
function checkStatus(status) {
return status === "Failed" ? "background-color: red" : "background-color: blue"
}
updated codepen

Related

Filter JavaScript Array Based on Multiple Values

I am trying to filter a Javascript dictionary based on multiple conditions.
I tried doing these steps:
I created an empty dictionary variable
Selected the input element and get the raw HTML node
Saved the value of the element that was changed as a variable
Saved the id of the element that was changed as another variable
conditionally add values to the filters object
// 1. Create a variable to keep track of all the filters as an object.
var filters = {};
// 3. Use this function to update the filters.
function updateFilters() {
// 4a. Save the element that was changed as a variable.
let changedElement = d3.select(this);
// 4b. Save the value that was changed as a variable.
let elementValue = changedElement.property("value")
console.log(elementValue);
// 4c. Save the id of the filter that was changed as a variable.
let filterId = changedElement.attr("id");
console.log(filterId);
// 5. If a filter value was entered then add that filterId and value
// to the filters list. Otherwise, clear that filter from the filters object.
if (elementValue != "") {
filters[filterId] = elementValue;
}
else {
delete filters[filterId];
}
// 6. Call function to apply all filters and rebuild the table
filterTable();
In the next function I need to loop through the filters list and keep data that matches the filter values.
// 7. Use this function to filter the table when data is entered.
function filterTable() {
// 8. Set the filtered data to the tableData.
let filteredData = tableData;
// 9. Loop through all of the filters and keep any data that
// matches the filter values
Object.entries(filters).forEach(([filterId, elementValue]) => {
if (filters[filterId] != "") {
filteredData = filteredData.filter(entry => entry.datetime === elementValue);
}
if (filters[filterId] != "") {
filteredData = filteredData.filter(entry => entry.city === elementValue);
}
if (filters[filterId] != "") {
filteredData = filteredData.filter(entry => entry.state === elementValue);
}
if (filters[filterId] != "") {
filteredData = filteredData.filter(entry => entry.country === elementValue);
}
if (filters[filterId] != "") {
filteredData = filteredData.filter(entry => entry.shape === elementValue);
}
};
// 10. Finally, rebuild the table using the filtered data
buildTable(filteredData);
}
// 2. Attach an event to listen for changes to each filter
d3.selectAll("input").on("change", updateFilters);
// Build the table when the page loads
buildTable(tableData);
The interface looks like this:
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!-- <meta http-equiv="X-UA-Compatible" content="IE=edge"> -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootswatch/3.3.7/superhero/bootstrap.min.css"> -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.16/css/jquery.dataTables.min.css">
<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js"></script>
<title>UFO Finder</title>
<link
rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
crossorigin="anonymous"
/>
<link href="https://fonts.googleapis.com/css?family=Ubuntu" rel="stylesheet">
<link rel="stylesheet" href="static/css/style.css">
</head>
<body class="bg-dark">
<div class="wrapper">
<nav class="navbar navbar-dark bg-dark navbar-expand-lg">
<a class="navbar-brand" href="index.html">UFO Sightings</a>
</nav>
<div class="jumbotron">
<h1 class="display-4">The Truth Is Out There</h1>
</div>
<div class="container-fluid">
<div class="row">
<div class="col-md-4">
<h3>UFO Sightings: Fact or Fancy? <small>Ufologists Weigh In</small></h3>
</div>
<div class="col-md-8">
<p>Some Text</p>
</div>
<div class="container-fluid">
<div class="row">
<div class="col-md-3">
<form class="bg-dark">
<p>Filter Search</p>
<ul class="list-group bg-dark">
<li class="list-group-item bg-dark">
<label for="date">Enter Date</label>
<input type="text" placeholder="1/10/2010" id="datetime"/>
</li>
<li class="list-group-item bg-dark">
<label for="city">Enter a City</label>
<input type="text" placeholder="roswell" id="city">
</li>
<li class="list-group-item bg-dark">
<label for="state">Enter a State</label>
<input type="text" placeholder="ca" id="state">
</li>
<li class="list-group-item bg-dark">
<label for="Country">Enter a Country</label>
<input type="text" placeholder="us" id="country">
</li>
<li class="list-group-item bg-dark">
<label for="Shape">Enter a Shape</label>
<input type="text" placeholder="crcle" id="shape">
</li>
<!-- <li class="list-group-item bg-dark">
<button id="filter-btn" type="button" class="btn btn-dark" >Clear Table</button>
</li> -->
</ul>
</form>
</div>
<div class="col-md-9">
<table class="table table-striped">
<thead>
<tbody>
<tr>
<th>Date</th>
<th>City</th>
<th>State</th>
<th>Country</th>
<th>Shape</th>
<th>Duration</th>
<th>Comments</th>
</tr>
</tbody>
</thead>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.11.0/d3.js"></script>
<script type="text/javascript" src="./static/js/data.js"></script>
<script type="text/javascript" src="./static/js/ufo_starterCode.js"></script>
</body>
</html>
data.js
var data = [
{
datetime: "1/1/2010",
city: "benton",
state: "ar",
country: "us",
shape: "circle",
durationMinutes: "5 mins.",
comments: "4 bright green circles high in the sky going in circles then one bright green light at my front door."
},
{
datetime: "1/1/2010",
city: "bonita",
state: "ca",
country: "us",
shape: "light",
durationMinutes: "13 minutes",
comments: "Three bright red lights witnessed floating stationary over San Diego New Years Day 2010"
}
];
The goal is to be able to filter records in a table based on the filter search criteria entered by the user.
Please note that I'm very new to Javascript. Any help is appreciated.
As you are new to JavaScript I would recommend that you start with the basics. And that means: try and leave out libraries and frameworks as much as possible. In the following snippet I removed your references to bootstrap, D3, datatables and jQuery as they are not really needed to solve the basic problem of filtering your table. This is also a requirement for posting code here in SO. You should always try to provide an "MCVE" (a minimum complete and viable example).
I chose a very basic concept for the filtering: Seeing that the input fields correspond directly to the first five columns of your table I applied the trick of going through the values of all theses inputs and compare them to the corresponding table values. These values are found by doing a forEach() loop over the table rows (<tr>) and then making sure that I get a "positive match" for the first five <td>s ([...tr.children].slice(0,5)) of each row. The text comparison is made between the lower-case version of each inp.value (stored in vals[I]) and the corresponding td.textContent, but only, if vals[i] is not empty (otherwise a positive match is returned, as an empty vals[i] means that there is no filtering for that column in place). So, if all five columns (.every()-loop) fulfil the "matching" condition the .style.display property for the current <tr> is set to "", otherwise to "none".
const data = [
{ datetime: "1/1/2010", city: "benton", state: "ar", country: "us", shape: "circle", durationMinutes: "5 mins.",
comments: "4 bright green circles high in the sky going in circles then one bright green light at my front door." },
{ datetime: "1/1/2010", city: "bonita", state: "ca", country: "us", shape: "light", durationMinutes: "13 minutes",
comments: "Three bright red lights witnessed floating stationary over San Diego New Years Day 2010" },
{ datetime: "1/13/2010", city: "Bonita", state: "ca", country: "us", shape: "square", durationMinutes: "3 minutes",
comments: "Early in January we saw a blue square appear right out of nowhere." }];
// fill table:
const tb=document.querySelector("table tbody");
tb.innerHTML=
data.map(r=>"<tr><td>"+Object.values(r).join("</td><td>")+"</td></td>").join("\n");
// filter table:
const inps=[...document.querySelectorAll("ul input")];
document.querySelector("ul").addEventListener("input",ev=>{
const vals=inps.map(inp=>inp.value.toLowerCase());
// filter table according to content of first 5 columns:
[...tb.children].forEach(tr=> // check for every table record:
tr.style.display=[...tr.children].slice(0,5).every((td,i)=>
vals[i]==="" || td.textContent.toLowerCase().includes(vals[i])
) ? "" : "none"
// show record if vals[i]==="" or if vals[i] is part of the corresponding column contents
)
})
.table-striped tbody tr:nth-child(odd) {background-color:#ddd}
<div class="wrapper">
<div class="jumbotron">
<h1 class="display-4">The Truth Is Out There</h1>
</div>
<div class="container-fluid">
<div class="row">
<div class="container-fluid">
<div class="row">
<div class="col-md-3">
<form class="bg-dark">
<p>Filter Search</p>
<ul class="list-group bg-dark">
<li class="list-group-item bg-dark">
<label for="date">Enter Date</label>
<input type="text" placeholder="1/10/2010" id="datetime" />
</li>
<li class="list-group-item bg-dark">
<label for="city">Enter a City</label>
<input type="text" placeholder="roswell" id="city">
</li>
<li class="list-group-item bg-dark">
<label for="state">Enter a State</label>
<input type="text" placeholder="ca" id="state">
</li>
<li class="list-group-item bg-dark">
<label for="Country">Enter a Country</label>
<input type="text" placeholder="us" id="country">
</li>
<li class="list-group-item bg-dark">
<label for="Shape">Enter a Shape</label>
<input type="text" placeholder="crcle" id="shape">
</li>
<li class="list-group-item bg-dark">
<button id="filter-btn" type="button" class="btn btn-dark">Clear Table</button>
</li>
</ul>
</form>
</div>
<div class="col-md-9">
<table class="table table-striped">
<thead>
<tr>
<th>Date</th>
<th>City</th>
<th>State</th>
<th>Country</th>
<th>Shape</th>
<th>Duration</th>
<th>Comments</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
The original code was trying to filter the data object while looping through the filters; The code implementation below loops through the filters object while looping through the data object.
Since I would always have more rows than filters, I ran the .filter method once rather than per filter as I initially tried to do.
// 9. Loop through all of the filters and keep any data that matches the filter values
let filteredData = tableData.filter((obj) => {
for(filterId in filters) {
if(obj[filterId] !== filters[filterId]) {
return false;
}
}
return true;
});

Hide complex column with colspan and rowspan with jQuery

I am building more or less a complex table with a lot of colspan and rowspan td's. Now i would like to create an onclick event on those pink column. So as soon as you click on one of these + column with class collapse, i would like to hide columns. For example, when I click the first +, I would like to hide the whole First driver column including Driver Name, first-driver-01, Driver ID, etc.
nth-child(x) is not helping really, because it does not ignore the col- and rowspans. I tried to group the td's in a seperated tag, like this:
<tr>
<td rowspan="3">CIM</td>
<!-- First driver -->
<group class="first-driver-01">
<td colspan="4">First driver</td>
</group>
<td rowspan="3" class="collapse">+</td>
<group class="second-driver-213">
<td colspan="4">Second driver</td>
</group>
<td rowspan="3" class="collapse">+</td>
</tr>
Unfortunately my chrome browser does this to the tags:
I'd use div's and CSS for something like this and style them like a table. I'm not going to re-create your entire table but here is an example I made using a smaller table, I'll leave you to have some fun.
Javascript
document.getElementById("clickme").onclick = function(){
var divsToHide = document.getElementsByClassName("hide"); //divsToHide is an array
if(document.getElementById("clickme").innerHTML == "-"){
for(var i = 0; i < divsToHide.length; i++){
divsToHide[i].style.visibility = "hidden"; // or
divsToHide[i].style.display = "none"; // depending on what you're doing
}
document.getElementById("clickme").innerHTML = "+"
}
else {
for(var i = 0; i < divsToHide.length; i++){
divsToHide[i].style.visibility = "visible"; // or
divsToHide[i].style.display = "table-cell"; // depending on what you're doing
}
document.getElementById("clickme").innerHTML = "-"
}
};
HTML
<div class="table">
<div class="row">
<div class="cell header">Team</div>
<div class="cell header">Wins</div>
<div class="cell header">Losses</div>
<div class="cell header hide ">Pct</div>
</div>
<div class="row">
<div class="cell">Bulls</div>
<div class="cell">29</div>
<div class="cell">18</div>
<div class="cell hide">.617</div>
</div>
<div class="row">
<div class="cell">Pacers</div>
<div class="cell">28</div>
<div class="cell">19</div>
<div class="cell hide">.596</div>
</div>
<div class="row">
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell" id="clickme">-</div>
</div>
CSS
.table {
display:table;
}
.row {
display:table-row;
}
.cell {
display:table-cell;
padding:2px;
}
.header {
font-weight:bold;
text-align:center;
}
Fiddle Here
I hope this helps,
Good luck

Angular JS displaying a specific ng-grid in a ng-repeat

Friends, i have a tree that is dynamically created from JSON. It also creates the grids that i want for a particular element on the tree and hides them all. Then i have a ng-click that shows it. My problem is that it shows ALL of them instead of the one that i want. For example, if user clicks on the header in 'Record 1' it should display the first grid and so on and so on. Here is my JSBin.
My HTML looks like this. Please see my JSBin for JavaScript file:
<body ng-controller="AbnTestController" style="margin:20px">
<button ng-click="try_changing_the_tree_data()" class="btn btn-default btn-sm">Submit File</button>
<p>
<table width="100%" style="height: 100%;" cellpadding="10" cellspacing="0" border="0">
<tr>
<!-- ============ LEFT COLUMN (TREE) ============== -->
<td width="250px" style="vertical-align:top" bgcolor="whitesmoke">
<div style="width:250px;background:whitesmoke;border:1px solid lightgray;border-radius:5px;">
<abn-tree ng-click="visible.grid = true" tree-data="my_data" tree-control="my_tree" on-select="my_tree_handler(branch)" expand-level="2"></abn-tree>
</div>
</td>
<!-- ============ RIGHT COLUMN (CONTENT) ============== -->
<td width="80%" valign="top" bgcolor="#d2d8c7">
<div style="vertical-align:top;">
<div ng-repeat="rule in rules">
<div ng-show="visible.grid == true" class="gridStyle" ng-grid="rule.grid" ></div>
</div>
<div id="results"></div>
</div>
</td>
</tr>
</table>
</p>
</body>
Here's a jsbin
HTML (diff):
<div ng-repeat="rule in rules">
<div
ng-show="rulesMap[rule.uid] == 'isVisible'"
class="gridStyle"
ng-grid="rule.grid"></div>
</div>
JavaScript remove calls to createGrids and:
$scope.my_tree_handler = function(branch) {
createGridsFromBranch(branch);
};
/*Function that builds the grid*/
$scope.rulesMap = {};
$scope.rules = [];
createGridsFromBranch = function(branch) {
var gridUid = 'g_'+branch.uid;
for(var i in $scope.rulesMap) {
$scope.rulesMap[i] = 'notVisible';
}
if($scope.rulesMap[gridUid]) {
$scope.rulesMap[gridUid] = 'isVisible';
return;
}
$scope.rulesMap[gridUid] = 'isVisible';
$scope.rules.push({
uid: gridUid,
grid: {
...
}
});

Page keeps loading when inserting reference to jquery

I really feel this is a stupid question but I could not figure out:
Here my cshtml file, and it's rendered just fine:
#model CrashTestScheduler.Entity.Model.Channel
#{
string editFormat = string.Format("<button type='button' class='editForm' data-val-id=\"{0}\"><span class='ico-edit'></span></button>", ".Id");
const string DeleteFormat = "<button type='button' class='awe-btn' onclick=\"awe.open('deleteChannel', { params:{ id: .Id } })\"><span class='ico-del'></span></button>";
const string EditFormat = "<button type='button' class='awe-btn' onclick=\"awe.open('editChannel', { params:{ id: .Id } })\"><span class='ico-edit'></span></button>";
}
<script>
$(function() {
awe.popup = bootstrapPopup;
});
var getChannelGroupNameHandler = function (item) {
if (item.ChannelGroupName == null || item.ChannelGroupName=='') {
item.ChannelGroupName = $("#ChannelGroupId option:selected").text();
}
}
</script>
<div id="wrap">
<div id="page-heading">
<ol class="breadcrumb">
<li>Home</li>
<li class="active">Channels</li>
<li style="display:none;"></li>
</ol>
</div>
<div class="container">
<div class="col-md-12" id="gridRowChannels">
<div class="col-md-12">
<div class="panel panel-midnightblue-header">
<div class="panel-heading">
<h3>Channel List</h3>
<div class="options">
</div>
</div>
<div class="panel-body">
<div class="row-sub">
<button type="button" id="btnAddProject" class="btn btn-primary" onclick="awe.open('createChannel')">
Add Channel
</button>
</div>
<div class="row-sub">
#Html.Awe().InitPopupForm().Name("createChannel").Url(Url.Action("Create", "ChannelsGrid")).Success("itemCreated('ChannelsGrid',getChannelGroupNameHandler)").OkText("Add").Title("Add Channel")
</div>
<div class="row-sub">
#Html.Awe().InitPopupForm().Name("deleteChannel").Url(Url.Action("Delete", "ChannelsGrid")).Success("itemDeleted('ChannelsGrid')").Parameter("gridId", "ChannelsGrid").Height(200).Modal(true).Title("Delete Channel").OkText("Delete")
</div>
<div class="row-sub">
#Html.Awe().InitPopupForm().Name("editChannel").Group("Channel").Url(Url.Action("Edit", "ChannelsGrid")).Success("itemUpdated('ChannelsGrid',getChannelGroupNameHandler)").OkText("Save").Title("Edit Channel")
</div>
<div class="row-sub">
#(Html.Awe().Grid("ChannelsGrid")
.Url(Url.Action("GetItems", "ChannelsGrid"))
.Columns(
new Column {Name = "Name", Header = "Channel Name", Sort = Sort.Asc},
new Column {Name = "ChannelGroup.Name", Header = "Channel Group", ClientFormat = ".ChannelGroupName"},
new Column {ClientFormat = DeleteFormat, Width = 50},
new Column {ClientFormat = EditFormat, Width = 50}
)
.Sortable(true)
.SingleColumnSort(true)
.LoadOnParentChange(false)
.PageSize(20)
.Groupable(false))
</div>
</div>
</div>
</div>
</div>
<div class="col-md-12" id="pnlEditproject" style="display: none;">
</div>
</div>
</div>
But I want to use jquery to use jquery validation later on. So here I inserted them to the file.
<script src="~/Scripts/jquery-1.11.2.min.js"></script>
<script type="text/javascript" src="~/Scripts/jquery.validate.min.js"></script>
Now the file could not be rendered and the page keeps loading and loading. Any clues?
Looks like you already have access to jQuery library in this page since you are using...
$(function() {
awe.popup = bootstrapPopup;
});
Please remove the new references and try to view page source to find out the list of libraries that are already available.

Display image as none on drop event

So I have 2 columns filled with images. I want to drag an image from the left column and drop it on the right column's image. The original image on the left must then have it's display set to none so that it disappears.
Here is an example of the html:
<div id="container1">
<table class="table1">
<tr>
<td>
<div class="info1" id="info1" ondragover="allowDrop(event)" ondrop="drop(event)">
<div style="float:left">
<img class="myimg" style="max-height:80px;" src="Pictures/Smiley.png">
</div>
<div style="float:left;">
<p class="myname">Name: Jane Doe</p>
<p class="myprof">Profession: Carpenter</p>
</div>
</div>
</td>
</tr>
</table>
</div>
<div id="container2">
<table class="table2">
<tr>
<td>
<div class="info2" onmousedown = "returnDrop(this.querySelector('img').src)" ondragover="allowDrop(event)" ondrop="drop()" >
<div style="float:left">
<img class="myimg2" style="max-height:80px;" src="Pictures/QuestionMark.png">
</div>
<div style="float:left;">
<p class="myname2">Name: Unspecified</p>
<p class="myprof2">Profession: Unspecified</p>
</div>
</div>
</td>
</tr>
</table>
</div
Here is some of the Javascript I've tried - it's probably best not to look as it as it simply doesn't work. I can use jquery if it's necessary.
document.getElementsByClassName('info2')[0].drop = function() {
document.getElementsByClassName('myimg2')[0].src = storeOnClick;
document.getElementsByClassName('myname2')[0].innerHTML=name;
document.getElementsByClassName('myprof2')[0].innerHTML=prof;
updateRecord();
return;
}
function updateRecord(div){
div.parentNode.parentNode.parentNode.style.display='none';
}
function returnDrop(el){
if(el=="file:///C:/Users/nmonk/Desktop/Tree/Pictures/QuestionMark.png"){
}
else if(el=="file:///C:/Users/nmonk/Desktop/Tree/Pictures/Smiley.png"){
updateRecord1(el);
}
else if(el=="file:///C:/Users/nmonk/Desktop/Tree/Pictures/Smiley2.png"){
updateRecord2(el);
}
else if(el=="file:///C:/Users/nmonk/Desktop/Tree/Pictures/Smiley3.png"){
updateRecord3(el);
}
else if(el=="file:///C:/Users/nmonk/Desktop/Tree/Pictures/Smiley4.png"){
updateRecord4(el);
}
else if(el=="file:///C:/Users/nmonk/Desktop/Tree/Pictures/Smiley5.png"){
updateRecord5(el);
}
}
function allowDrop(ev) {
ev.preventDefault();
}
Necessary but unrelated to the issue:
function start(){
first();
}
function first () {
var _divs = document.querySelectorAll('.info1');
for (var i = 0; i < _divs.length; i++) {
_divs[i].addEventListener("mousedown", function () { changeInfo1(this) }, false);
}
}
function changeInfo1(el) {
myimg = el.querySelector('.myimg'),
myname = el.querySelector('.myname'),
myprof = el.querySelector('.myprof')
// img
storeOnClick = myimg.src;
// name
name = myname.innerHTML;
// profession
prof = myprof.innerHTML;
}
You could very simply add the following for each of your images: (note the last line)
document.getElementsByClassName('info2')[0].drop = function() {
document.getElementsByClassName('myimg2')[0].src = storeOnClick;
document.getElementsByClassName('myname2')[0].innerHTML=name;
document.getElementsByClassName('myprof2')[0].innerHTML=prof;
if(storeOnClick=='file:///C:/Users/nmonk/Desktop/Tree/Pictures/Smiley.png'){
document.getElementsByClassName('info1')[0].parentNode.style.display='none';
}

Categories