How to loop through array with objects inside - javascript

Actually its working with simple array
let box1 =[01, 02, 03];
function hitMiss(box) {
$("td").on("click", function(){
let y = $(this).attr("id");
if (box.find(boxId => boxId == y)) {
$(this).addClass("yes");
console.log("full");
} else {
$(this).addClass("no");
console.log("empty");
}
});
};
codepen
But i need to use objects in array
let boxes = [
{ locations: [01, 02, 03]},
{ locations: [23, 24, 25]},
{ locations: [41, 42, 43]}
];

ES6
You can also use reduce() and the spread operator. you can achieve your required result.
CODE SNIPPET
boxes = boxes.reduce((r, {locations}) => [...r, ...locations], []);
DEMO
let boxes = [{
locations: [01, 02, 03]
}, {
locations: [23, 24, 25]
}, {
locations: [41, 42, 43]
}];
hitMiss(boxes);
function hitMiss(box) {
box = box.reduce((r, {
locations
}) => [...r, ...locations], []);
$("td").on("click", function() {
let y = $(this).attr("id");
if (box.some(boxId => boxId == y)) {
$(this).addClass("yes");
console.log("full");
} else {
$(this).addClass("no");
console.log("empty");
}
});
};
html {
background-color: #859cac;
}
table {
margin-right: auto;
margin-left: auto;
}
td {
height: 40px;
width: 40px;
background-color: darkcyan;
border: solid 2px;
border-color: black;
}
.yes {
background-color: red;
}
.no {
background-color: yellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr>
<td id="00">00</td>
<td id="01">01</td>
<td id="02">02</td>
<td id="03"></td>
<td id="04"></td>
<td id="05"></td>
<td id="06"></td>
</tr>
<tr>
<td id="10"></td>
<td id="11"></td>
<td id="12"></td>
<td id="13"></td>
<td id="14"></td>
<td id="15"></td>
<td id="16"></td>
</tr>
<tr>
<td id="20"></td>
<td id="21"></td>
<td id="22"></td>
<td id="23"></td>
<td id="24"></td>
<td id="25"></td>
<td id="26"></td>
</tr>
<tr>
<td id="30"></td>
<td id="31"></td>
<td id="32"></td>
<td id="33"></td>
<td id="34"></td>
<td id="35"></td>
<td id="36"></td>
</tr>
<tr>
<td id="40"></td>
<td id="41"></td>
<td id="42"></td>
<td id="43"></td>
<td id="44"></td>
<td id="45"></td>
<td id="46"></td>
</tr>
<tr>
<td id="50"></td>
<td id="51"></td>
<td id="52"></td>
<td id="53"></td>
<td id="54"></td>
<td id="55"></td>
<td id="56"></td>
</tr>
<tr>
<td id="60"></td>
<td id="61"></td>
<td id="62"></td>
<td id="63"></td>
<td id="64"></td>
<td id="65"></td>
<td id="66"></td>
</tr>
</table>

Concatenate all the locations using reduce as
var allLocs = boxes.reduce( (a,c) => a.concat(c.locations), [])
Change your internal if-condition to
if (allLocs.find(boxId => boxId == y))
{
$(this).addClass("yes");
console.log("full");
}
else
{
$(this).addClass("no");
console.log("empty");
}
Please find updated pen

Related

Save state of collapsed rows

I'm having troubles with saving the state of collapsed rows :
I have child and parent rows in a table. Parents have a +/- buttons allowing users to collapse/expand the child rows (which have a bigger data-level). The expand collapse itself works fine but if I collapse a row and then collapse the above row again, when I expand the higher row it expands everything after but I'd like to keep the collapsed rows collapsed.
In this example it works the way I'd like : Fiddle which works.
If you for example collapse the second row, then the first one, and expand the first, the second and all its children are kept collapsed and hidden.
In this example (which I'm struggling with) it doesn't work anymore : Fiddle which doesn't work
Does anyone have an idea of what's the problem ? I can't see why it works in the first case but not the second.
Thanks in advance for your help !
Sincerely,
EDIT :
The data-level needs to be equal to the headers="h_M1" td and each tr which have a lower data-level than its follower needs to be a parent that can be collapsed. For example in your edit there is tr3 as a child, but it needs to be a parent which can collapse all the tr after it (since there's no other 3 or lower after it). And it needs to stay collapsed if we collapse/expand tr2
// Expand/collapse when clicking on first column //
function getChildren($row) {
var children = [], level = $row.attr('data-level');
while($row.next().attr('data-level') > parseInt(level)) {
children.push($row.next());
$row = $row.next();
}
return children;
}
$('.colex').on('click', function() {
var action;
if($(this).parent('.parent').hasClass('collapsed')) {
$(this).parent('.parent').removeClass('collapsed');
$(this).text('-');
action = 'show';
} else {
$(this).parent('.parent').addClass('collapsed');
$(this).text('+');
action = 'hide';
}
var level = $(this).parent('.parent').attr('data-level');
var children = getChildren($(this).parent('.parent'));
$.each(children, function() {
if(action == "show") {
if ($(this).attr('data-level')==parseInt(level)+1
|| $(this).hasClass('hidden')===false) {
/* un-hide direct children, and not hidden sub-children */
$(this).removeClass('hidden').show();
}
} else {
if ($(this).attr('data-level')==parseInt(level)+1) {
/* apply hidden to direct children */
$(this).addClass('hidden');
}
/* hide all children */
$(this).hide();
}
});
})
body {
font-family: sans-serif;
}
body * {
box-sizing: border-box;
/*color: #59547c;*/
margin: 0;
}
main {
/* max-width: 60rem;*/
margin: 1px auto;
padding: 1rem;
}
h1 {
margin-bottom: 1rem;
}
p {
margin-bottom: 1rem;
}
input.variante[type=checkbox] {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
}
input.variante[type=checkbox] {
height: 15px;
width: 15px;
background: #fff;
border: 1px solid #ccc;
}
input.variante[type="checkbox"]:checked
{
background: orange;
&:before {
font-family: FontAwesome;
content: '\f00c';
display: block;
color: grey;
font-size: 15px;
position: absolute;
}
}
table {
empty-cells: show;
}
th {
text-align:center;
border: 1px solid antiquewhite;
}
.parent > .colex {
color: black;
cursor: pointer;
}
.table_header {
background-color:#484e82;
color:#fdfdff;
font-weight: bold;
}
.intro {
font-size: 1.125rem;
}
.Titre_1 {
color: red;
}
.Titre_2 {
color: purple;
}
.Titre_3 {
color: fuchsia;
}
.Titre_4 {
color: green;
}
.Titre_5 {
color: lime;
}
.Titre_6 {
color: navy;
}
.Titre_7 {
color: blue;
}
.Titre_8 {
color: aqua;
}
.Titre_9 {
color: orange;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<body>
<intro>
<p class="intro">description</p>
</intro>
<main>
<table id="mytable" align=center rules=groups frame=box hborder=0 cellspacing=1 cellpadding=4 vborder=1>
<thead class="table_header">
<th id="colex" width=2%>Co<br/>Ex</th>
<th id="h_M8" width=2%>V<br/>M8</th>
<th id="h_M1" width=2%>cd<br/>M1</th>
<th id="h_M2" width=5%>N°<br/>M2</th>
<th id="h_M4" width=23%>Désignation<br/>M4</th>
<th id="h_M7" width=3%>Uté<br/>M7</th>
<th id="h_M9" width=3%>Qté <br/>M9</th>
<th id="h_M18" width=5%>PR Fourniture unitaire<br/>M18</th>
<th id="h_M20" width=3%>Type FO<br/>M20</th>
<th id="h_M14" width=3%>K Acc<br/>M14</th>
<th id="h_M19" width=6%>PR Total fourniture<br/>M19</th>
<th id="h_M23" width=5%>Tps pose unitaire<br/>M23</th>
<th id="h_M26" width=3%>Type MO<br/>M26</th>
<th id="h_M22" width=3%>K Pose<br/>M22</th>
<th id="h_M42" width=5%>Tps pose total<br/>M42</th>
<th id="h_M40" width=5%>PR unitaire<br/>M40</th>
<th id="h_M41" width=5%>PR Total<br/>M41</th>
<th id="h_M27" width=3%>qte vendue<br/>M27</th>
<th id="h_M32" width=5%>PV unitaire<br/>M32</th>
<th id="h_M44" width=6%>PV Total<br/>M44</th>
</thead>
<tbody>
<tr class="parent" data-level="1">
<td headers="colex" class="colex">-</td>
<td headers="h_M8"><input class="variante" type="checkbox"></td>
<td headers="h_M1">1</td>
<td headers="h_M2">A</td>
<td headers="h_M4">Titre 1, n'appartient à personne</td>
<td headers="h_M7">ens</td>
<td headers="h_M9">1</td>
<td headers="h_M18"></td>
<td headers="h_M20"></td>
<td headers="h_M14"></td>
<td headers="h_M19"></td>
<td headers="h_M23"></td>
<td headers="h_M26"></td>
<td headers="h_M22"></td>
<td headers="h_M42"></td>
<td headers="h_M40"></td>
<td headers="h_M41"></td>
<td headers="h_M27"></td>
<td headers="h_M32"></td>
<td headers="h_M44"></td>
</tr>
<tr class="parent" data-level="2">
<td headers="colex" class="colex">-</td>
<td headers="h_M8"><input class="variante" type="checkbox"></td>
<td headers="h_M1">2</td>
<td headers="h_M2">A.1</td>
<td headers="h_M4">Titre 2 - la ligne doit appartenir au titre niveau 1, N°A ci-dessus</td>
<td headers="h_M7">ens</td>
<td headers="h_M9">1</td>
</tr>
<tr class="parent" data-level="3">
<td headers="colex" class="colex">-</td>
<td headers="h_M8"><input class="variante" type="checkbox"></td>
<td headers="h_M1">3</td>
<td headers="h_M2"></td>
<td headers="h_M4">cette ligne "terminale" doit appartenir au titre niveau 2, N°A.1 ci-dessus</td>
<td headers="h_M7">km</td>
<td headers="h_M9">6</td>
</tr>
<tr class="parent" data-level="4">
<td headers="colex" class="colex">-</td>
<td headers="h_M8"><input class="variante" type="checkbox"></td>
<td headers="h_M1">4</td>
<td headers="h_M2"></td>
<td headers="h_M4">cette ligne doit aussi appartenir au titre niveau 2, N°A.1 ci-dessus</td>
<td headers="h_M7">m</td>
<td headers="h_M9">10,5</td>
</tr>
<tr class="child" data-level="5">
<td headers="colex" class="colex"></td>
<td headers="h_M8"><input class="variante" type="checkbox"></td>
<td headers="h_M1">5</td>
<td headers="h_M2">B</td>
<td headers="h_M4">un autre Titre 1, n'appartient à personne</td>
<td headers="h_M7">ens</td>
<td headers="h_M9">1</td>
</tr>
<tr class="parent" data-level="5">
<td headers="colex" class="colex">-</td>
<td headers="h_M8"><input class="variante" type="checkbox"></td>
<td headers="h_M1">5</td>
<td headers="h_M2">B.1</td>
<td headers="h_M4">Titre 2 - la ligne doit appartenir au titre niveau 1, N°B ci-dessus</td>
<td headers="h_M7">ens</td>
<td headers="h_M9">1</td>
</tr>
<tr class="parent" data-level="6">
<td headers="colex" class="colex">-</td>
<td headers="h_M8"><input class="variante" type="checkbox"></td>
<td headers="h_M1">6</td>
<td headers="h_M2">B.1.1</td>
<td headers="h_M4">Titre 3 - la ligne doit appartenir au titre niveau 2, N°B.1 ci-dessus</td>
<td headers="h_M7">ens</td>
<td headers="h_M9">1</td>
</tr>
<tr class="child" data-level="9">
<td headers="colex" class="colex"></td>
<td headers="h_M8"><input class="variante" type="checkbox"></td>
<td headers="h_M1">9</td>
<td headers="h_M2"></td>
<td headers="h_M4">cette ligne "terminale" doit appartenir au titre niveau 3, N°B.1.1 ci-dessus</td>
<td headers="h_M7">kg</td>
<td headers="h_M9">2</td>
</tr>
<tr class="child" data-level="9">
<td headers="colex" class="colex"></td>
<td headers="h_M8"><input class="variante" type="checkbox"></td>
<td headers="h_M1">9</td>
<td headers="h_M2"></td>
<td headers="h_M4">cette ligne doit aussi appartenir au titre niveau 3, N°B.1.1 ci-dessus</td>
<td headers="h_M7">m</td>
<td headers="h_M9">10,5</td>
</tr>
<tr class="child" data-level="9">
<td headers="colex" class="colex"></td>
<td headers="h_M8"><input class="variante" type="checkbox"></td>
<td headers="h_M1">9</td>
<td headers="h_M2">B.1.2</td>
<td headers="h_M4">Titre 3 - la ligne doit appartenir au titre niveau 2, N°B.1 ci-dessus</td>
<td headers="h_M7">ens</td>
<td headers="h_M9">1</td>
</tr>
</tbody>
</table>
</main>
</body>
updating the JS code as per your changes in question.
this should do what you are trying to do.
// recursive method to get the child of the element
const gc = (a) => {
var children = [];
// loop till the data-level is lower than the parent node or it's a child at the same level.
while (
parseInt(a.next().attr("data-level")) > parseInt(a.attr("data-level")) ||
(parseInt(a.next().attr("data-level")) == parseInt(a.attr("data-level")) &&
a.hasClass("child"))
) {
// if next node is parent call the recursive method
if (a.next().hasClass("parent")) {
var temp = gc(a.next()); // store children in temp var.
children.push({
p: true,
c: temp.c,
n: a.next().get(0),
h: a.next().hasClass("collapsed"),
});
// push the children in array 'p' : to identify if node is parent, 'c' : all child to the element, 'n' : current node, 'h' : to identify if its colapsed.
a = temp.r; // move to the next row (jumping all child rows)
} else {
children.push({ p: false, n: a.next().get(0) }); // if the node is child push without anything
a = a.next(); // move to next row.
}
}
return { r: a.next(), c: children }; // return object 'r' : next row for iteration, 'c' : children of the node a
};
// method to hide/unhide row
const up = (item, show) => {
if (item.p && !item.h) for (var child of item.c) up(child, show); // if the node is parent and not collapsed update all children recursively on all children of the node.
show ? $(item.n).show() : $(item.n).hide(); // show/hide node
};
// on click method for colex tr
$(".colex").on("click", function () {
if ($(this).text() == "") return; // if child do nothing
var show = $(this).text() == "+"; // set if to show or hide on basis of icon value '+' : show, '-' : hide
$(this).text(show ? "-" : "+"); // switch the icon and add/remove the collapsed class
$(this).parent(".parent").toggleClass("collapsed"); // toggle class collapsed
for (var child of gc($(this).parent(".parent")).c) up(child, show); // iterate on all children and show/hide them
});
Let me know if you don't understand anything about it.

Dynamic DataTable to chart one row across the row

I have a datatable that is drawing data from a database dynamically, and correctly displaying the data on a piechart. However, after having searched abundantly, I am still having problems doing the following, please keep in mind I am new to javascript and it could be something minor that I am missing.
The piechart is working fine, but I would like the chart to display data only from the first row, and not all rows as it is currently doing. I have tried:
"startRow: 2, endRow: 3" - This works with other charts but with the code I have below, it doesn't work no matter where I put it.
I have also tried ""pageLength": 1," which applies to the datatable but the chart still displays all rows.
On a separate chart from the same datatable, I would like to chart data across the row and not down the column. I have tried "switchRowsAndColumns: true".
Again this solution works with other tables but not with the code I'm using, which draws the chart according to the info in the table, which will be generated through the search function or filters. If I can have both charts displayed as a series each rendered to a separate container that would be great.
Any help would be greatly appreciated. Here is the jsfiddle (pls ignore slice labels)
Attached is the code (I am using a static table but my table is dynamic):
$(document).ready(function() {
// Initialize table
var c20BhvDt = $("#c20Bhv").DataTable({
});
var kc20BhvPieChart = Highcharts.chart("container", {
chart: {
type: "pie",
backgroundColor: "transparent",
},
plotOptions: {
pie: {
colors: ['#64c987', '#d16035', '#e58b38', '#fafa6e', '#b53535', '#099FFF'],
allowPointSelect: true,
slicedOffset: 30,
cursor: 'pointer',
innerSize: '10%',
borderWidth: 3,
borderColor: '#2d3035',
dataLabels: {
enabled: true,
color: '#EF8C99',
connectorColor: '#EF8C99'
}
}
},
series: [{
data: chartData(c20BhvDt, 7),
name: 'Students',
dataLabels: {
style: {
fontSize: 16,
textOutline: '#2d3035'
},
formatter: function() {
const point = this.point;
return '<span style="color: ' + point.color + '">' +
point.name + ' - ' + point.y + ' Students</span>';
},
},
},
],
});
c20BhvDt.on("draw", function() {
kc20BhvPieChart.series[0].setData(chartData(c20BhvDt));
});
});
function chartData(c20BhvDt, column = 7) {
var counts = {};
c20BhvDt
.column(column, {
search: "applied"
})
.data()
.each(function(val) {
if (counts[val]) {
counts[val] += 1;
} else {
counts[val] = 1;
}
});
return $.map(counts, function(val, key) {
return {
name: key,
y: val,
};
});
};
#container {
height: 400px;
}
.highcharts-figure,
.highcharts-data-table table {
min-width: 310px;
max-width: 800px;
margin: 1em auto;
}
#c20Bhv {
font-family: Verdana, sans-serif;
border-collapse: collapse;
border: 1px solid #ebebeb;
margin: 10px auto;
text-align: center;
width: 100%;
max-width: 500px;
}
#c20Bhv caption {
padding: 1em 0;
font-size: 1.2em;
color: #555;
}
#c20Bhv th {
font-weight: 600;
padding: 0.5em;
}
#c20Bhv td,
#c20Bhv th,
#c20Bhv caption {
padding: 0.5em;
}
#c20Bhv thead tr,
#c20Bhv tr:nth-child(even) {
background: #f8f8f8;
}
#c20Bhv tr:hover {
background: #f1f7ff;
}
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/v/bs5/dt-1.12.1/sb-1.3.3/sp-2.0.1/datatables.min.js"></script>
<script src="https://nightly.datatables.net/searchpanes/js/dataTables.searchPanes.js?13"></script>
<script src="https://nightly.datatables.net/select/js/dataTables.select.js?_=9a6592f8d74f8f520ff7b22342fa1183"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/highcharts-more.js"></script>
<script src="https://code.highcharts.com/modules/data.js"></script>
<figure class="highcharts-figure">
<div id="container">
</div>
<table id="c20Bhv" class="Stabel" style="width:100%">
<thead>
<tr class="bg-secondary text-light text-large">
<td colspan="8" class="text-center">Student Info</td>
</tr>
<tr>
<th class="text-center">ID</th>
<th class="text-center">EX</th>
<th class="text-center">NP</th>
<th class="text-center">Sl</th>
<th class="text-center">LT</th>
<th class="text-center">WR</th>
<th class="text-center">BTH</th>
<th class="text-center">SCR</th>
</tr>
</thead>
<tbody>
<tr>
<td class="text-center">21204</td>
<td class="text-center">4</td>
<td class="text-center">7</td>
<td class="text-center">3</td>
<td class="text-center">7</td>
<td class="text-center">2</td>
<td class="text-center">1</td>
<td class="text-center">87</td>
</tr>
<tr>
<td class="text-center">21205</td>
<td class="text-center">5</td>
<td class="text-center">3</td>
<td class="text-center">5</td>
<td class="text-center">9</td>
<td class="text-center">5</td>
<td class="text-center">2</td>
<td class="text-center">83</td>
</tr>
<tr>
<td class="text-center">21206</td>
<td class="text-center">8</td>
<td class="text-center">3</td>
<td class="text-center">5</td>
<td class="text-center">6</td>
<td class="text-center">1</td>
<td class="text-center">6</td>
<td class="text-center">93</td>
</tr>
<tr>
<td class="text-center">21207</td>
<td class="text-center">6</td>
<td class="text-center">3</td>
<td class="text-center">8</td>
<td class="text-center">4</td>
<td class="text-center">7</td>
<td class="text-center">4</td>
<td class="text-center">83</td>
</tr>
<tr>
<td class="text-center">21208</td>
<td class="text-center">3</td>
<td class="text-center">7</td>
<td class="text-center">6</td>
<td class="text-center">3</td>
<td class="text-center">2</td>
<td class="text-center">8</td>
<td class="text-center">74</td>
</tr>
<tr>
<td class="text-center">21209</td>
<td class="text-center">3</td>
<td class="text-center">4</td>
<td class="text-center">3</td>
<td class="text-center">8</td>
<td class="text-center">9</td>
<td class="text-center">6</td>
<td class="text-center">69</td>
</tr>
</tbody>
</table>
</figure>

How to remove class by hovering

I would like to set classaqua by hovering from clicked cells.
I attempt to getfirst id and then change class to hovering cells
But, I stacked removeclasswhen hovering,
My desired result is to change class fromfirstto last hoveredcells.
Are there any method for them?
Thanks
var first;
$(function() {
$("td").click(function() {
first = this.id;
$(this).addClass("aqua");
console.log(first);
});
$('td').hover(function() {
const id = +$(this).attr('id');
console.log(id);
for(var j=first;j<=id;j++){
$("#"+id).addClass("aqua");}
});
});
.aqua{
background-color: aqua;
}
td {
padding: 5px
transition-duration: 0.4s;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<td id="1">1</td>
<td id="2">2</td>
<td id="3">3</td>
<td id="4">4</td>
<td id="5">5</td>
<td id="6">6</td>
<td id="7">7</td>
<td id="8">8</td>
<td id="9">9</td>
<td id="10">10</td>
</table>
You should declare the variable first outside of the click handler function. You also should convert the string id to number:
const id = Number($(this).attr('id'));
$(function() {
var first;
$("td").click(function() {
first = this.id;
$(this).addClass("aqua");
console.log(first);
});
$('td').hover(function() {
const id = Number($(this).attr('id'));
console.log(id);
for(var j = first;j <= id; j++){
$("#"+id).addClass("aqua");
}
});
});
.aqua{
background-color: aqua;
}
td {
padding: 5px
transition-duration: 0.4s;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<td id="1">1</td>
<td id="2">2</td>
<td id="3">3</td>
<td id="4">4</td>
<td id="5">5</td>
<td id="6">6</td>
<td id="7">7</td>
<td id="8">8</td>
<td id="9">9</td>
<td id="10">10</td>
</table>
THere are a bunch of ways to do this. But i tried to change your initial code as little as i could.
First, you need to convert the id ( which are strings ) to numbers. You can do that with parseInt. Because comparing 2 strings is not correct in this situation. Because '2'<'10' will return false. String comparison happens on character basis. Which mean each character is compared with the corresponding character from the other string.
So '2' is greater > than '10' because '2' > '1' in alphabetical order.
Second, You should remove the aqua class from all td when clicking again on a td.
Third, you do not need a loop. Just check if the current hovered td id is greater than the one you first clicked then add class.
$(function() {
$("td").click(function() {
const first = parseInt(this.id, 10);
$(this).addClass("aqua");
const notThisTd = $('td').not(this)
notThisTd.removeClass("aqua");
notThisTd.hover(function() {
const id = parseInt(this.id, 10);
if (id > first) {
$(this).addClass("aqua");
}
});
});
});
.aqua{
background-color: aqua;
}
td {
padding: 5px
transition-duration: 0.4s;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<td id="1">1</td>
<td id="2">2</td>
<td id="3">3</td>
<td id="4">4</td>
<td id="5">5</td>
<td id="6">6</td>
<td id="7">7</td>
<td id="8">8</td>
<td id="9">9</td>
<td id="10">10</td>
</table>

How to cancel previous input in html tables

In samples,I can change color by clicking each cells.
I would like to cancel previous inputby clicking cancel button.
Are there any way to do this? If someone has expererienced such issue. please let me know.
Thanks
$(function() {
$("td").click(function() {
$(this).addClass("red");
});
});
.red{
background-color: red;
}
td {
padding: 5px
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<td id="1">1</td>
<td id="2">2</td>
<td id="3">3</td>
<td id="4">4</td>
<td id="5">5</td>
<td id="6">6</td>
<td id="7">7</td>
<td id="8">8</td>
<td id="9">9</td>
<td id="10">10</td>
</table>
<button>cancel</button>
Here you go:
$(function() {
let clicked = [];
$("td").click(function() {
let clickedID = $(this).attr('id');
clicked.push(clickedID);
$(this).addClass("red");
});
$("#btnCancel").on('click',() => {
if(clicked.length) {
let lastClicked = clicked.pop();
$(`td#${lastClicked}`).removeClass("red");
}
})
});
.red{
background-color: red;
}
td {
padding: 5px
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<td id="1">1</td>
<td id="2">2</td>
<td id="3">3</td>
<td id="4">4</td>
<td id="5">5</td>
<td id="6">6</td>
<td id="7">7</td>
<td id="8">8</td>
<td id="9">9</td>
<td id="10">10</td>
</table>
<button id="btnCancel">cancel</button>
var lastel = null;
$(function() {
$("td").click(function() {
$(this).addClass("red");
lastel = $(this);
});
$('button').click(function() {
if (lastel !== null)
lastel.removeClass('red');
});
});
You can do this by keeping track of the history:
const history = [];
function addToHistory(e) {
const index = e.target.id;
if (history.indexOf(index) < 0) history.push(index);
color();
}
function undo() {
history.pop();
color();
}
function color() {
const cells = document.getElementsByTagName("td");
for (let i = 0; i < cells.length; i++) {
cells[i].classList.remove("red");
}
history.forEach(index => {
document.getElementById(index).className = "red";
});
}
.red{
background-color: red;
}
td {
padding: 5px
}
<table>
<td onclick="addToHistory(event)" id="1">1</td>
<td onclick="addToHistory(event)" id="2">2</td>
<td onclick="addToHistory(event)" id="3">3</td>
<td onclick="addToHistory(event)" id="4">4</td>
<td onclick="addToHistory(event)" id="5">5</td>
<td onclick="addToHistory(event)" id="6">6</td>
<td onclick="addToHistory(event)" id="7">7</td>
<td onclick="addToHistory(event)" id="8">8</td>
<td onclick="addToHistory(event)" id="9">9</td>
<td onclick="addToHistory(event)" id="10">10</td>
</table>
<button onclick="undo()">cancel</button>

How to grab the surrounding td elements?

Ok so i have this html structure jsfiddle and what I want do is grab all 8 surrounding tds when one is clicked.
So for example if the user clicks on #c3 then I want an array of the ['b2', 'b3', 'b4', 'c2', 'c4', 'd2', 'd3', 'd4'] but if they select #a2 since it doesnt have 8 surrounding corners it would return ['a1', 'a3', 'b1', 'b2', 'b3']
This is the direction I was going with but I think this will get pretty complicated ...any better ideas or is this the best way
function surrounding_table_rows(id){
var table_rows = new Array();
var letters = new Array("a","b","c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o");
var letter = id[0];
var number = id[1];
var index = letters.indexOf(letter);
if (index == 0) {
// need to add this logic here
}else{
var prior_letter = letters[index - 1];
var after_letter = letters[index + 1];
if (number == 0) {
// need to add this logic here
}else if(number == 14){
// need to add this logic here
}else{
table_rows.push("#"+letter+(parseInt(number)-1));
table_rows.push("#"+letter+(parseInt(number)+1));
table_rows.push("#"+prior_letter+(parseInt(number)-1));
table_rows.push("#"+prior_letter+(number));
table_rows.push("#"+prior_letter+(parseInt(number)+1));
table_rows.push("#"+after_letter+(parseInt(number)-1));
table_rows.push("#"+after_letter+(number));
table_rows.push("#"+after_letter+(parseInt(number)+1));
}
}
return table_rows;
}
my javascript function does work on middle
surrounding_table_rows("d4")
["#d3", "#d5", "#c3", "#c4", "#c5", "#e3", "#e4", "#e5"]
here is the html
<table class='config'>
<tr>
<td id='a1'></td>
<td id='a2'></td>
<td id='a3'></td>
<td id='a4'></td>
<td id='a5'></td>
<td id='a6'></td>
<td id='a7'></td>
<td id='a8'></td>
<td id='a9'></td>
<td id='a10'></td>
<td id='a11'></td>
<td id='a12'></td>
<td id='a13'></td>
<td id='a14'></td>
<td id='a15'></td>
</tr>
<tr>
<td id='b1'></td>
<td id='b2'></td>
<td id='b3'></td>
<td id='b4'></td>
<td id='b5'></td>
<td id='b6'></td>
<td id='b7'></td>
<td id='b8'></td>
<td id='b9'></td>
<td id='b10'></td>
<td id='b11'></td>
<td id='b12'></td>
<td id='b13'></td>
<td id='b14'></td>
<td id='b15'></td>
</tr>
<tr>
<td id='c1'></td>
<td id='c2'></td>
<td id='c3'></td>
<td id='c4'></td>
<td id='c5'></td>
<td id='c6'></td>
<td id='c7'></td>
<td id='c8'></td>
<td id='c9'></td>
<td id='c10'></td>
<td id='c11'></td>
<td id='c12'></td>
<td id='c13'></td>
<td id='c14'></td>
<td id='c15'></td>
</tr>
<tr>
<td id='d1'></td>
<td id='d2'></td>
<td id='d3'></td>
<td id='d4'></td>
<td id='d5'></td>
<td id='d6'></td>
<td id='d7'></td>
<td id='d8'></td>
<td id='d9'></td>
<td id='d10'></td>
<td id='d11'></td>
<td id='d12'></td>
<td id='d13'></td>
<td id='d14'></td>
<td id='d15'></td>
</tr>
<tr>
<td id='e1'></td>
<td id='e2'></td>
<td id='e3'></td>
<td id='e4'></td>
<td id='e5'></td>
<td id='e6'></td>
<td id='e7'></td>
<td id='e8'></td>
<td id='e9'></td>
<td id='e10'></td>
<td id='e11'></td>
<td id='e12'></td>
<td id='e13'></td>
<td id='e14'></td>
<td id='e15'></td>
</tr>
<tr>
<td id='f1'></td>
<td id='f2'></td>
<td id='f3'></td>
<td id='f4'></td>
<td id='f5'></td>
<td id='f6'></td>
<td id='f7'></td>
<td id='f8'></td>
<td id='f9'></td>
<td id='f10'></td>
<td id='f11'></td>
<td id='f12'></td>
<td id='f13'></td>
<td id='f14'></td>
<td id='f15'></td>
</tr>
Here is a rudimentary solution to your problem, using jQuery: http://jsfiddle.net/ujDsS/9/
$(function() {
$("td").css("cursor","pointer").click(function() {
$("td").css("background","white");
var $i, $j;
var cell = $(this), parentRow = cell.parent(), container = parentRow.parent();
var x = parentRow.children("td").index(cell), y = container.children("tr").index(parentRow);
var myID = cell.attr("id");
for ($i = -1; $i <= 1; $i++) {
if (y-$i < 0) continue;
var row = container.children("tr").eq(y-$i);
if (!row.length) continue;
for ($j = -1; $j <= 1; $j++) {
if (x-$j < 0) continue;
var cell2 = row.children("td").eq(x-$j);
if (!cell2.length) continue;
cell2.css("background","red");
}
}
});
});
What I am doing is pretty simple: on each click, I convert the cell into its x-y coordinates, and then loop through the 8 neighbors + itself and paint them red.
jQuery has an issue (it's a feature, really) where the indices of eq can be negative. Fixing this is left as an exercise - it's as simple as checking if y-$i is negative :-)
This assumes one thing: You will not use colspan or rowspan

Categories