Mechanism binding click event handler to massive <td> elements - javascript

I'm writing a big HTML table which has same-data-coloring feature by user's double-clicking on a certain cell, the table has over 8000 cells and cells will be increased.
At this point, I thought it could be a burdened working to a web-browser.
Yes, I want to know the in-depth mechanism and burdening degree of attaching event-handler to massive <td> elements.
The code:
<script>
var otable = document.getElementById("htbl_drawresult");
var irIndex = 0;
var icIndex = 0;
var sintxt = "";
for(var i = 1; i < otable.rows.length; i++)
{
for(var j = 0; j < otable.rows[i].cells.length; j++)
{
otable.rows[i].cells[j].ondblclick = function()
{
irIndex = this.parentElement.rowIndex;
icIndex = this.cellIndex+1;
sintxt = this.innerText;
f_colorcell(sintxt, otable);
};
}
}
function f_colorcell(stxt, otbl){
var irow = otbl.rows.length;
var icol = otbl.rows[1].cells.length;
var i,j=0;
for(i=1; i<irow; i++)
{
for(j=0; j<icol; j++)
{
if (otbl.rows[i].cells[j].innerText == stxt){
otbl.rows[i].cells[j].style.background=\"red\";
}
}
}
}
</script>

Just summarising #C.RaysOfTheSun's answer:
Yes, it would be burdensome to attach an event each on every cell of the table.
However, you could structure your HTML in such a way that the cells (TDs) can each be uniquely identified. And when events propagate from a target to an ancestor (TABLE element for instance) where a listener is *commonly* attached, it's simple to determine the actual target in the listener.
document.addEventListener("DOMContentLoaded", main, false);
function main() {
var table = document.getElementsByTagName("TABLE")[0];
table.addEventListener("dblclick", handleDoubleClickOnTable, false);
}
function handleDoubleClickOnTable( /* event => */ e) {
var target = e.target;
var row, column;
var rowNumber, columnNumber;
if ("TD" !== target.tagName) {
return;
}
row = target.parentNode;
column = target;
rowNumber = row.dataset.rowNumber;
columnNumber = column.dataset.columnNumber;
alert(`You clicked on ( row[ ${ rowNumber } ], column[ ${ columnNumber } ] )`);
}
* {
font-family: monospace;
box-sizing: border-box;
}
table {
width: 100%;
margin-bottom: 1rem;
background-color: transparent;
border-collapse: collapse;
}
td {
vertical-align: bottom;
border-bottom: 2px solid #dee2e6;
border-top: 1px solid #dee2e6;
padding: 2rem;
}
<!-- Sample 3 x 3 table -->
<table>
<tr data-row-number="1">
<td data-column-number="1">( 1, 1 )</td>
<td data-column-number="2">( 1, 2 )</td>
<td data-column-number="3">( 1, 3 )</td>
</tr>
<tr data-row-number="2">
<td data-column-number="1">( 2, 1 )</td>
<td data-column-number="2">( 2, 2 )</td>
<td data-column-number="3">( 2, 3 )</td>
</tr>
<tr data-row-number="3">
<td data-column-number="1">( 3, 1 )</td>
<td data-column-number="2">( 3, 2 )</td>
<td data-column-number="3">( 3, 3 )</td>
</tr>
</table>

If you're talking about assigning an event handler for the cells (<td>) inside your table, you can do it in two ways:
1. Event Propagation
A shorter and much simpler way of doing it. You can assign an event handler to the parent (the <table> element itself) and everything inside it will have the event handler as well. Simply put, what the parent gets, the child will also get.
Recommended if you don't need a specific thing to happen when a given element is clicked. Although, you can always narrow things down by utilizing Event.Target.
In the example below, I have assigned a click event listener to the table (parent) so that when you click on anything inside it, an alert saying "You clicked on a cell and it had the value of [cell value]" will show up
Here's a working example for event propagation.
window.onload = ()=>{
// get our table
let tb = document.getElementById('main-table');
// assign a click event to it
tb.addEventListener('click', (e)=>{
alert(`You clciked on a cell and it had the value of ${e.target.innerHTML}`)
})
}
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
<table class="table" id="main-table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Handle</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<td>Mark</td>
<td>Otto</td>
<td>#mdo</td>
</tr>
<tr>
<th scope="row">2</th>
<td>Jacob</td>
<td>Thornton</td>
<td>#fat</td>
</tr>
<tr>
<th scope="row">3</th>
<td>Larry</td>
<td>the Bird</td>
<td>#twitter</td>
</tr>
</tbody>
</table>
2. Manually assigning a specific event handler to each element
You can always set an event handler for each cell (<td>) specifically by grabbing them using JavaScript's built-in functions (i.e. querySelector, querySelectorAll, getElementById, etc...) then assigning a function to be called on a specific event using addEventListener
Not recommended for a large collection of elements.
You can play around with the snippet below here :)
window.onload = ()=>{
// get our table
let table = document.getElementById('main-table');
// get all the cells in the table element above
let tableCells = table.querySelectorAll('td');
// assign an event listener to each cell <td> element inside that table specifically
for(let i = 0; i < tableCells.length; i++){
tableCells[i].addEventListener('click', function(e){
alert(`You clicked on cell index ${i} and it had the value of ${this.innerHTML}`);
})
}
}
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
<table class="table" id="main-table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Handle</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<td>Mark</td>
<td>Otto</td>
<td>#mdo</td>
</tr>
<tr>
<th scope="row">2</th>
<td>Jacob</td>
<td>Thornton</td>
<td>#fat</td>
</tr>
<tr>
<th scope="row">3</th>
<td>Larry</td>
<td>the Bird</td>
<td>#twitter</td>
</tr>
</tbody>
</table>
:)

If you want to add click event listeners, you can use jQuery. You can use this for any HTML element.
$("#button").click(function() {
$("#result").css("background-color", "yellow");
});
$("#button").dblclick(function() {
$("#result").css("background-color", "red");
});
body {
font-family: Arial, sans-serif;
}
td {
width: 20px;
height: 20px;
text-align: center;
margin: 0;
border: .5px solid black;
}
#button {
background-color: white;
}
#result {
background-color: blue;
width: 100px;
height: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
If you click the <code>div</code> once, the square will turn yellow.<br>
If you double click the <code>div</code>, the square will turn red.<br>
CM = Click Me
<table>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>6</td>
<td>7</td>
<td id="button">CM</td>
<td>9</td>
<td>10</td>
</tr>
<tr>
<td>11</td>
<td>12</td>
<td>13</td>
<td>14</td>
<td>15</td>
</tr>
<tr>
<td>16</td>
<td>17</td>
<td>18</td>
<td>19</td>
<td>20</td>
</tr>
</table>
<div id="result"></div>

Related

Copy ( to clipboard ) only one required column contents of html data table

My requirement is simple.
I have a table with four columns. Have some mobile numbers in 2nd column "Mobile No.". I just want to copy ( to clipboard ) All the mobile numbers in the "Mobile No." column on button click.
Tried some javascript samples for the same, not worked as required. Please give some suggestions.
<html>
<head>
<style>
table {
font-family: arial, sans-serif;
border-collapse: collapse;
width: 100%;
}
td, th {
border: 1px solid #dddddd;
text-align: left;
padding: 8px;
}
tr:nth-child(even) {
background-color: #dddddd;
}
</style>
</head>
<body>
<h2>HTML Table</h2>
<button id="copy-table-button" data-clipboard-target="#datatable"> Copy Mobile No. </button>
<table id="myTable">
<thead>
<tr>
<th>Sl No</th>
<th>Mobile No.</th>
<th>Name</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>1234567890</td>
<td>Maria</td>
<td>Active</td>
</tr>
<tr>
<td>2</td>
<td>2223330</td>
<td>Ruma</td>
<td>Active</td>
</tr>
<tr>
<td>3</td>
<td>3334440</td>
<td>Kumar</td>
<td>Not-Active</td>
</tr>
<tr>
<td>4</td>
<td>44455500</td>
<td>Subba</td>
<td>Active</td>
</tr>
<tr>
<td>5</td>
<td>555666111</td>
<td>Orayyo</td>
<td>Not-Active</td>
</tr>
<tr>
<td>6</td>
<td>555666111</td>
<td>Orayyo</td>
<td>Active</td>
</tr>
<tr>
<td>7</td>
<td>555666111</td>
<td>Orayyo</td>
<td>Not-Active</td>
</tr>
</tbody>
</table>
</body>
</html>
I just need to copy them as plain text, to paste in other websites or forms.
Should paste like this after copy..
1234567890
2223330
3334440
44455500
555666111
555666111
555666111
Thanks in advance.
This works for me, let me know if you have any troubles with it:
const copyButton = document.querySelector('#copy-table-button');
const copyToClipboard = (_) => {
const dataElements = document.querySelectorAll('tr > td:first-child + td');
const data = Array.from(dataElements).map(element => element.textContent).join('\n');
const blob = new Blob([data], {type: 'text/plain'});
const clipboardItem = new ClipboardItem({'text/plain': blob});
navigator.clipboard.write([clipboardItem]);
}
copyButton.addEventListener('click', copyToClipboard);

search result should appear after 3 characters

I have a problem showing the search result after 3 characters, it shows the result directly after the first character I type. I want it to show the result only after typing 3 characters at least. here is the code I used in HTML, CSS and Javascript
function myFunction() {
var input, filter, table, tr, td, i;
input = document.getElementById("myInput");
filter = input.value.toUpperCase();
table = document.getElementById("myTable");
tr = table.getElementsByTagName("tr");
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[1];
if (td) {
if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
#myInput {
width: 100%; /* Full-width */
font-size: 16px; /* Increase font-size */
padding: 12px 20px 12px 40px; /* Add some padding */
border: 1px solid #ddd; /* Add a grey border */
margin-bottom: 12px; /* Add some space below the input */
}
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Search</title>
<link rel="stylesheet" href="./assets/css/style.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
crossorigin="anonymous">
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.12.1/bootstrap-table.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</head>
<body>
<div class="container">
<h1>Search for employees</h1>
<input class="container" type="text" id="myInput"
onkeyup="myFunction()" placeholder="search...">
<div class="table-responsive{-sm|-md|-lg|-xl}">
<table class="table" id="myTable">
<tr class="header">
<th>Picture</th>
<th>Name</th>
<th>Age</th>
<th>Active</th>
<th>Email</th>
<th>Phone</th>
<th>Company</th>
<th>Balance</th>
</tr>
<tr>
<td><img src="http://placehold.it/32x32" alt=""></td>
<td>Smith Junior</td>
<td>24</td>
<td>true</td>
<td>asd#ast.com</td>
<td>+8983287687</td>
<td>Company</td>
<td>$1000</td>
</tr>
<tr>
<td><img src="http://placehold.it/32x32" alt=""></td>
<td>Linda Lindo</td>
<td>24</td>
<td>true</td>
<td>asd#ast.com</td>
<td>+8983287687</td>
<td>Company</td>
<td>$1000</td>
</tr>
<tr>
<td><img src="http://placehold.it/32x32" alt=""></td>
<td>Victoria Smith</td>
<td>24</td>
<td>true</td>
<td>asd#ast.com</td>
<td>+8983287687</td>
<td>Company</td>
<td>$1000</td>
</tr>
<tr>
<td><img src="http://placehold.it/32x32" alt=""></td>
<td>Jason Abraham</td>
<td>24</td>
<td>true</td>
<td>asd#ast.com</td>
<td>+8983287687</td>
<td>Company</td>
<td>$1000</td>
</tr>
<tr>
<td><img src="http://placehold.it/32x32" alt=""></td>
<td>Ahmed Raquent</td>
<td>24</td>
<td>true</td>
<td>asd#ast.com</td>
<td>+8983287687</td>
<td>Company</td>
<td>$1000</td>
</tr>
</table>
</div>
</div>
</body>
<script src="./assets/js/main.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.12.1/bootstrap-table.min.js"></script>
</html>
can you help me with the code ? I would be more than thankful
Check for length of input , and when input length is less than 3 , dont do anything
function myFunction() {
var input, filter, table, tr, td, i;
input = document.getElementById("myInput");
filter = input.value.toUpperCase();
table = document.getElementById("myTable");
tr = table.getElementsByTagName("tr");
if(filter.length < 3) {
return;
}
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[1];
if (td) {
if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
I will suggest two things here one is please use oninput event for capturing value change (https://www.w3schools.com/jsref/event_oninput.asp) and second please wait until value length is three, as suggested in above answer.
`https://jsfiddle.net/poojanbedi/d5q3op0j/`

How can you target a child element of an iterated object in JavaScript?

In this instance I simply want to target tables that have a thead tag.
I trying to concatenate or search using JavaScript or jQuery whichever is quicker.
e.g thead = DT[i].children('thead');
function go() {
var i = 0,
DT = document.getElementsByClassName('DT');
for (i; i < DT.length; ++i) {
var x = DT[i];
if ($(x + ' thead').length) {
//do stuff to this table
}
}
}
<table class="DT" id="gv1">
<tbody>
<tr>
<th>th</th>
</tr>
<tr>
<td>td</td>
</tr>
</tbody>
</table>
<table class="DT" id="gv2">
<thead>
<tr>
<th>thead</th>
</tr>
</thead>
<tbody>
<tr>
<td>td</td>
</tr>
</tbody>
</table>
You don't need any loops, you can use jQuery's :has() selector to retrieve an element based on whether or not it contains a specified child, like this:
function go() {
$('.DT').has('thead').addClass('foo');
}
go();
.foo { border: 1px solid #C00; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table class="DT" id="gv1">
<tbody>
<tr>
<th>th</th>
</tr>
<tr>
<td>td</td>
</tr>
</tbody>
</table>
<table class="DT" id="gv2">
<thead>
<tr>
<th>thead</th>
</tr>
</thead>
<tbody>
<tr>
<td>td</td>
</tr>
</tbody>
</table>
You can use querySelector to check if the nested thead exists.
if (x.querySelector("thead")) {
//do stuff to this table
}
Just so you know, you'd do this to accomplish what you were trying originally:
if ($(x).find("thead").length) {
//do stuff to this table
}
This is just to show how you can perform DOM selection from a given context.

show the column of the table in a color if the value in a cell is passed javascript

I have a table for some calculations and if cell value is passed I want to show that column of the table in a color.
I have this for the moment :
<script type="text/javascript">
$(document).ready(function(){
$('#myTable td.y_n').each(function(){
if ($(this).text() < 0.4) {
$(this).css('background-color','#a9edb8');
}
else {
$(this).css('background-color','#eda9ca');
}
});
});
</script>
but this is only for the cell.
Any idea? thanks!
If I understand your goal correctly, you want to set the background color of an entire column if one if the y_n cells contains a numeric value and choose the color based on that value.
To set the entire column, you could get the tablecells at the corresponding indices, but easier is to use a column group:
$(document).ready(function(){
var cols = $('#myTable col'); //get the column groups
$('#myTable td.y_n').each(function(){
var text = this.innerText; //text of the td
if(text.length > 0 && !isNaN(this.innerText)){ //check if it's a number
var ind = $(this).index(); //the index of the td inside its tr = the column index
$(cols[ind]).css('background-color', parseFloat(text) < 0.4 ? '#a9edb8' : '#eda9ca'); //set the col of the column group
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="myTable">
<colgroup>
<col>
<col>
<col>
</colgroup>
<tr>
<td>r1</td>
<td class='y_n'></td>
<td class='y_n'>.7</td>
</tr>
<tr>
<td>r2</td>
<td class='y_n'>.1</td>
<td class='y_n'>.6</td>
</tr>
<tr>
<td>r3</td>
<td>a</td>
<td>b</td>
</tr>
</table>
$(document).ready(function() {
$('#myTable td.y_n').each(function(i,v) {
if (parseFloat($(this).text()) < 0.4) {
$(this).closest("table").find("td").eq(i).addClass("pass");
} else {
$(this).closest("table").find("td").eq(i).addClass("fail");
}
});
});
.pass {
background-color: #a9edb8
}
.fail {
background-color: #eda9ca
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="myTable">
<tr>
<td class='y_n'>
.3
</td>
<td class='y_n'>
.6
</td>
</tr>
<tr>
<td class='y_n'>
.2
</td>
<td class='y_n'>
.9
</td>
</tr>
<tr>
<td class='y_n'>
.9
</td>
<td class='y_n'>
.1
</td>
</tr>
</table>
Use parseFloat() then compare
You can also achieve like this. in each i is index and e will be current element. And i just added with="100" to table so its looks proper.
$(document).ready(function() {
$('#myTable td.y_n').each(function(i,e) {
if ($(e).text() < 0.4) {
$(e).css('background-color','#a9edb8');
} else {
$(e).css('background-color','#eda9ca');
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="myTable" width="100">
<tr>
<td class='y_n'>
.3
</td>
</tr>
<tr>
<td class='y_n'>
.6
</td>
</tr>
</table>
I am not saying this is the best way because i have use so many loops, but you can achieve your requirement by this code.
$(document).ready(function() {
$('#myTable tr').each(function(index,event) {
$(event).children('td').each(function(indexI,eventI) {
if ($(eventI).text() < 0.4) {
$('#myTable tr').each(function(indexIn,eventIn) {
$(eventIn).children('td').eq(indexI).css('background- color','#eda9ca');
});
}
});
});
});
Best of luck :)
If there are many rows (a lot of them) in your table, you might be better of using colgroups with col structure in your table, and put the background on the col-element. Anyway, you can always do this:
$(function() {
$('table a').click(function(e) {
e.preventDefault();
var index = $(this).html();
colHighlight($(this).closest('table'), index);
});
});
function colHighlight(table, colIndex) {
var bodyCells = table.find('tbody td');
bodyCells.css('background-color', 'transparent');
bodyCells.filter(':nth-child(' + colIndex + ')').css({
'background-color': 'yellow'
});
}
table, td, th {
border: 1px solid #000;
border-collapse: collapse;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<thead>
<tr>
<th>Head 1</th>
<th>Head 2</th>
<th>Head 3</th>
</tr>
</thead>
<tfoot>
<tr>
<th colspan="3">
Highlight column:
1
2
3
</th>
</tr>
</tfoot>
<tbody>
<tr>
<td>Content</td>
<td>Content</td>
<td>Content</td>
</tr>
<tr>
<td>Content</td>
<td>Content</td>
<td>Content</td>
</tr>
<tr>
<td>Content</td>
<td>Content</td>
<td>Content</td>
</tr>
</tbody>
</table>

JQuery: Identify duplicate values in a table textbox column and highlight the textboxes

I'm using JQuery and I'm sure this is pretty simple stuff but I was unable to find a solution. I have an employee table with "Number" column which is editable(text box). I want to find the duplicates in the "Number" column and highlight those textboxes. For example in the table below I want to highlight all textboxes with values 10 and 20. Also when a edit is done and there are no longer duplicates, remove the highlight.
Here's the JSFiddle
Any Ideas?
<table id="employeeTable">
<tr>
<th>Id</th>
<th>Name</th>
<th>Number</th>
</tr>
<tr>
<td>1</td>
<td>John</td>
<td>10</td>
</tr>
<tr>
<td>2</td>
<td>Sally</td>
<td>20</td>
</tr>
<tr>
<td>3</td>
<td>Mary</td>
<td>10</td>
</tr>
<tr>
<td>4</td>
<td>Sam</td>
<td>30</td>
</tr>
<tr>
<td>5</td>
<td>Chris</td>
<td>20</td>
</tr>
</table>
There are different possibilities, basically you'll have to test if the value of an array exists more than one time, for example like this.
Update:
Using the value selector works fine in the initial state, but it seems that when a value is changed by direct user input or by calling .val(), the HTML attribute value is not changed (only the native JS .value). Therefore - to use the value selector in this context, the html value attribute is always updated with the JS .value.
function highlightDuplicates() {
// loop over all input fields in table
$('#employeeTable').find('input').each(function() {
// check if there is another one with the same value
if ($('#employeeTable').find('input[value="' + $(this).val() + '"]').size() > 1) {
// highlight this
$(this).addClass('duplicate');
} else {
// otherwise remove
$(this).removeClass('duplicate');
}
});
}
$().ready(function() {
// initial test
highlightDuplicates();
// fix for newer jQuery versions!
// since you can select by value, but not by current val
$('#employeeTable').find('input').bind('input',function() {
$(this).attr('value',this.value)
});
// bind test on any change event
$('#employeeTable').find('input').on('input',highlightDuplicates);
});
Updated fiddle is here.
I guess this is what you are exactly looking for:
Working : Demo
1) First for loop for taking all input values into an array inpValArr[]
2) Second for loop for sorting and finding out the duplicate ones.
3) Third for loop for adding class .highLight to duplicate ones.
Now all this is in a function: inputCheck() which is called on DOM Ready and after you edit the text field.
inputCheck();
$("#employeeTable input").bind("change paste keyup", function() {
inputCheck();
});
function inputCheck() {
var totalInp = $("#employeeTable input").length;
var inpValArr = [];
for (var j = 0; j < totalInp; j++) {
var inpVal = $("#employeeTable input:eq(" + j + ")").val();
inpValArr.push(inpVal);
}
var sorted_arr = inpValArr.sort();
var results = [];
for (var i = 0; i < inpValArr.length - 1; i++) {
if (sorted_arr[i + 1] == sorted_arr[i]) {
results.push(sorted_arr[i]);
}
}
$('#employeeTable input').removeClass('highLight');
for (var k = 0; k < totalInp; k++) {
$('#employeeTable :input[value="' + results[k] + '"]').addClass('highLight');
}
}
#employeeTable th,
#employeeTable td {
padding: 0.8em;
border: 1px solid;
}
#employeeTable th {
background-color: #6699FF;
font-weight: bold;
}
.highLight {
background: red;
}
<table id="employeeTable">
<tr>
<th>Id</th>
<th>Name</th>
<th>Number</th>
</tr>
<tr>
<td>1</td>
<td>John</td>
<td>
<input type="text" value="10" />
</td>
</tr>
<tr>
<td>2</td>
<td>Sally</td>
<td>
<input type="text" value="20" />
</td>
</tr>
<tr>
<td>3</td>
<td>Mary</td>
<td>
<input type="text" value="10" />
</td>
</tr>
<tr>
<td>4</td>
<td>Sam</td>
<td>
<input type="text" value="30" />
</td>
</tr>
<tr>
<td>5</td>
<td>Chris</td>
<td>
<input type="text" value="20" />
</td>
</tr>
</table>
You could easily give a class such as 'hasInput' to all td with inputs and then try a .each on all of them and check for value if they are 10 or 20 and then add a class to make them styled as you wish.
html:
<table id="employeeTable">
<tr>
<th>Id</th>
<th>Name</th>
<th>Number</th>
</tr>
<tr>
<td>1</td>
<td>John</td>
<td class="hasInput"><input type="text" value = "10"/></td>
</tr>
<tr>
<td>2</td>
<td>Sally</td>
<td class="hasInput"><input type="text" value = "20"/></td>
</tr>
<tr>
<td>3</td>
<td>Mary</td>
<td class="hasInput"><input type="text" value = "10"/></td>
</tr>
<tr>
<td>4</td>
<td>Sam</td>
<td class="hasInput"><input type="text" value = "30"/></td>
</tr>
<tr>
<td>5</td>
<td>Chris</td>
<td class="hasInput"><input type="text" value = "20"/></td>
</tr>
css:
#employeeTable th, #employeeTable td{
padding:0.8em;
border: 1px solid;
}
#employeeTable th{
background-color:#6699FF;
font-weight:bold;
}
.colored {
background-color: red;
}
js:
$('.hasInput > input').each(function() {
if ($(this).val() == 10 || $(this).val() == 20) {
$(this).addClass('colored');
}
});
DEMO
This would work:
var dupes=[], values=[];;
$('.yellow').removeClass('yellow');
$('#employeeTable td:nth-child(3) input').each(function(){
if($.inArray($(this).val(),values) == -1){
values.push($(this).val());
}
else{
dupes.push($(this).val());
}
});
$('#employeeTable td:nth-child(3) input').filter(function(){return $.inArray(this.value,dupes) == -1 ? false : true }).addClass('yellow');
#employeeTable th, #employeeTable td{
padding:0.8em;
border: 1px solid;
}
#employeeTable th{
background-color:#6699FF;
font-weight:bold;
}
.yellow{
background-color:yellow;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="employeeTable">
<tr>
<th>Id</th>
<th>Name</th>
<th>Number</th>
</tr>
<tr>
<td>1</td>
<td>John</td>
<td><input type="text" value = "10"/></td>
</tr>
<tr>
<td>2</td>
<td>Sally</td>
<td><input type="text" value = "20"/></td>
</tr>
<tr>
<td>3</td>
<td>Mary</td>
<td><input type="text" value = "10"/></td>
</tr>
<tr>
<td>4</td>
<td>Sam</td>
<td><input type="text" value = "30"/></td>
</tr>
<tr>
<td>5</td>
<td>Chris</td>
<td><input type="text" value = "20"/></td>
</tr>
</table>
Expanding on the answer provided by #axel.michel using .count() selector of Linq.js. I decided to go this route because I couldn't get the JQuery selector to work correctly provided in his answer. And I really like the Linq.js and find myself loving it more each time i implement a use of it.
var allTextBoxes = $().find('input:text');
// loop over all input fields on page
$(allTextBoxes)
.each(function() {
// select any other text boxes that have the same value as this one
if (Enumerable.from(allTextBoxes).count("$.value == '" + $(this).val() + "'") > 1) {
// If more than 1 have the same value than highlight this textbox and display an error message
$(this).addClass('duplicate');
$('#custom-field-validator').html('Custom fields must have unique names.');
valid = false;
} else {
// otherwise remove
$(this).removeClass('duplicate');
}
});
This is working fine without needing to worry about the value selector and syncing the value attributes.

Categories

Resources