How to get value of nextsibling if element search by specific string? - javascript

I am trying to get the text which is in the next element of searched element by string.Let me explain by code
<table id="myTable">
<tbody>
<tr>
<th>Name</th>
<td>foo</td>
</tr>
<tr>
<th>age</th>
<td>20</td>
</tr>
</tbody>
</table>
I have to search string if "age" exist. then return 20 as its value.
I tried to search string by contains: But unable to access value

You could use jQuery next() and contains selector to achieve what you need.
$(document).ready(function() {
console.log($("th:contains(age)").next().html());
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="myTable">
<tbody>
<tr>
<th>Name</th>
<td>foo</td>
</tr>
<tr>
<th>age</th>
<td>20</td>
</tr>
</tbody>
</table>

This solution will go through all the elements that are children of trs and check to see that their text is equal to the search. If it is equal, it assigns the next element to nextElem.
let search = "age";
let nextElem;
$('#myTable tr').children().each(function() {
if ($(this).text() === search)
nextElem = $(this).next();
});
console.log(nextElem.text())
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="myTable">
<tbody>
<tr>
<th>Name</th>
<td>foo</td>
</tr>
<tr>
<th>age</th>
<td>20</td>
</tr>
</tbody>
</table>

You've already set up the table to display name-value pairs, where each name is contained within <th>...</th> and its corresponding value is contained within <td>...</td>.
So one approach to this is straightforward Document Object Model navigation, using:
getElementsByTagName('th')
getElementsByTagName('td')
var table = document.getElementsByTagName('table')[0];
var button = document.getElementsByTagName('button')[0];
var summary = document.getElementsByClassName('summary')[0];
var searchedFor = summary.getElementsByTagName('p')[0];
var correspondingResult = summary.getElementsByTagName('p')[1];
function displayResult() {
var returnValue = '';
var searchString = document.getElementsByTagName('input')[0].value;
var lowerCaseSearchString = searchString.toLowerCase();
var tableRows = document.getElementsByTagName('tr');
for (var i = 0; i < tableRows.length; i++) {
var name = tableRows[i].getElementsByTagName('th')[0].textContent.toLowerCase();
if (name === lowerCaseSearchString) {
returnValue = tableRows[i].getElementsByTagName('td')[0].textContent;
}
if (returnValue === '') {
returnValue = 'No Matches';
}
}
searchedFor.textContent = 'You searched for... ' + '"' + searchString + '"';
correspondingResult.textContent = 'The corresponding result is... ' + '"' + returnValue + '"';
}
button.addEventListener('click',displayResult,false);
table, .search-panel {
display: inline-block;
vertical-align: top;
margin-right: 24px;
}
table {
border: 2px solid rgb(127,127,127);
}
th, td {
padding: 12px;
}
th {
text-align: left;
background-color: rgb(191,191,191);
}
th::after {
content:':';
}
.search-results p span {
font-weight:bold;
}
<table>
<tbody>
<tr>
<th>Name</th>
<td>Foo</td>
</tr>
<tr>
<th>Age</th>
<td>20</td>
</tr>
</tbody>
</table>
<div class="search-panel">
<form>
<input type="text" placeholder="Enter your string here..." value="" />
<button type="button">Search for String</button>
</form>
<div class="summary">
<p>You searched for... </p>
<p>The corresponding result is... </p>
</div>
</div>

Related

HTML table filter with unique values only

I have a 300x11(rowXcolumn) html table that I wanted to filter exactly like Excel or Google Sheets's filter. However, after searching a bit I found out the following code below in a website. This works as I wanted but it has one major problem. It shows same value multiple times. For example in the 2nd column, there are 2 values same "Apple" and 2 whitespaces . In the current code, it displays Apple twice and whitespace twice. However, I want it should show the same values only once. For example, it will show "Apple" only once, and if I select apple it will filter both rows containing apple.
Thank you very much for your help.
index.html
<!DOCTYPE html>
<html>
<head>
<script data-require="jquery#2.0.3" data-semver="2.0.3" src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<table class="grid">
<thead>
<tr>
<td index=0>Name
<div class="filter"></div>
</td>
<td index=1>Address
<div class="filter"></div>
</td>
<td index=2>City
<div class="filter"></div>
</td>
</tr>
</thead>
<tbody>
<tr>
<td>first</td>
<td>first add</td>
<td>SDF dfd</td>
</tr>
<tr>
<td>second</td>
<td></td>
<td>SDF dfd</td>
</tr>
<tr>
<td>third</td>
<td>Apple</td>
<td>SDF dfd</td>
</tr>
<tr>
<td>third</td>
<td></td>
<td>SDF hello</td>
</tr>
<tr>
<td>third</td>
<td>Apple</td>
<td>SDF hello</td>
</tr>
</tbody>
</table>
</body>
</html>
script.js
$(document).ready(function(){
$(".grid thead td").click(function(){
showFilterOption(this);
});
});
var arrayMap = {};
function showFilterOption(tdObject){
var filterGrid = $(tdObject).find(".filter");
if (filterGrid.is(":visible")){
filterGrid.hide();
return;
}
$(".filter").hide();
var index = 0;
filterGrid.empty();
var allSelected = true;
filterGrid.append('<div><input id="all" type="checkbox" checked>Select All</div>');
var $rows = $(tdObject).parents("table").find("tbody tr");
$rows.each(function(ind, ele){
var currentTd = $(ele).children()[$(tdObject).attr("index")];
var div = document.createElement("div");
div.classList.add("grid-item")
var str = $(ele).is(":visible") ? 'checked' : '';
if ($(ele).is(":hidden")){
allSelected = false;
}
div.innerHTML = '<input type="checkbox" '+str+' >'+currentTd.innerHTML;
filterGrid.append(div);
arrayMap[index] = ele;
index++;
});
if (!allSelected){
filterGrid.find("#all").removeAttr("checked");
}
filterGrid.append('<div><input id="close" type="button" value="Close"/><input id="ok" type="button" value="Ok"/></div>');
filterGrid.show();
var $closeBtn = filterGrid.find("#close");
var $okBtn = filterGrid.find("#ok");
var $checkElems = filterGrid.find("input[type='checkbox']");
var $gridItems = filterGrid.find(".grid-item");
var $all = filterGrid.find("#all");
$closeBtn.click(function(){
filterGrid.hide();
return false;
});
$okBtn.click(function(){
filterGrid.find(".grid-item").each(function(ind,ele){
if ($(ele).find("input").is(":checked")){
$(arrayMap[ind]).show();
}else{
$(arrayMap[ind]).hide();
}
});
filterGrid.hide();
return false;
});
$checkElems.click(function(event){
event.stopPropagation();
});
$gridItems.click(function(event){
var chk = $(this).find("input[type='checkbox']");
$(chk).prop("checked",!$(chk).is(":checked"));
});
$all.change(function(){
var chked = $(this).is(":checked");
filterGrid.find(".grid-item [type='checkbox']").prop("checked",chked);
})
filterGrid.click(function(event){
event.stopPropagation();
});
return filterGrid;
}
style.css
table thead tr td{
background-color : gray;
min-width : 100px;
position: relative;
}
.filter{
position:absolute;
border: solid 1px;
top : 20px;
background-color : white;
width:100px;
right:0;
display:none;
}
Maybe someone else will fix that limited JS for you but otherwise use DataTables. It has all you want with extensive documentation, and it's a popular plugin so it's not hard to find any answers to questions you might have about it. Here's an example with everything you desired in your post:
/* Range Search - https://datatables.net/examples/plug-ins/range_filtering.html */
$.fn.dataTable.ext.search.push(function(settings, data, dataIndex) {
var min = parseInt($('#min').val(), 10);
var max = parseInt($('#max').val(), 10);
var age = parseFloat(data[3]) || 0;
if (
(isNaN(min) && isNaN(max)) ||
(isNaN(min) && age <= max) ||
(min <= age && isNaN(max)) ||
(min <= age && age <= max)
) {
return true;
}
return false;
});
$(document).ready(function() {
/* Init dataTable - Options[paging: off, ordering: off, search input: off] */
var table = $('#table').DataTable({
"paging": false,
"ordering": false,
dom: 'lrt'
});
/* Column Filters */
$(".filterhead").each(function(i) {
if (i != 4 && i != 5) {
var select = $('<select><option value="">Filter</option></select>')
.appendTo($(this).empty())
.on('change', function() {
var term = $(this).val();
table.column(i).search(term, false, false).draw();
});
table.column(i).data().unique().sort().each(function(d, j) {
select.append('<option value="' + d + '">' + d + '</option>')
});
} else {
$(this).empty();
}
});
/* Range Search -> Input Listener */
$('#min, #max').keyup(function() {
table.draw();
});
});
.container {
max-width: 80%;
margin: 0 auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/dt/dt-1.13.1/datatables.min.css" />
<script type="text/javascript" src="https://cdn.datatables.net/v/dt/dt-1.13.1/datatables.min.js"></script>
<body>
<div class="container">
<input type="text" id="min" name="min" placeholder="Min Number">
<input type="text" id="max" name="max" placeholder="Max number">
<table id="table" class="display">
<thead>
<tr>
<th class="filterhead">Name</th>
<th class="filterhead">Address</th>
<th class="filterhead">City</th>
<th class="filterhead">Number</th>
</tr>
<tr>
<th>Name</th>
<th>Address</th>
<th>City</th>
<th>Number</th>
</tr>
</thead>
<tbody>
<tr>
<td>first</td>
<td>first add</td>
<td>SDF dfd</td>
<td>18</td>
</tr>
<tr>
<td>second</td>
<td>as</td>
<td>SDF dfd</td>
<td>50</td>
</tr>
<tr>
<td>third</td>
<td>Apple</td>
<td>SDF dfd</td>
<td>2</td>
</tr>
<tr>
<td>third</td>
<td>as</td>
<td>SDF hello</td>
<td>25</td>
</tr>
<tr>
<td>third</td>
<td>Apple</td>
<td>SDF hello</td>
<td>10</td>
</tr>
</tbody>
</table>
</div>
</body>

Javascript Filtering by multiple columns

Borrowing code from the post below I am able to filter on 2 columns using the || (Or) operator.
However, I'd like to be able to filter using the && (And) operator.
I have been unsuccessful in my multiple attempts. I could use some help.
Filtering table multiple columns
function myFunction() {
var input0, input1, filter0, filter1, table, tr, td, cell, i, j;
document.getElementById("myInput0").value = 'Female';
document.getElementById("myInput1").value = 'Engineering';
input0 = document.getElementById("myInput0");
input1 = document.getElementById("myInput1");
filter0 = input0.value.toUpperCase();
filter1 = input1.value.toUpperCase();
table = document.getElementById("myTable");
tr = table.getElementsByTagName("tr");
for (i = 1; i < tr.length; i++) {
// Hide the row initially.
tr[i].style.display = "none";
td = tr[i].getElementsByTagName("td");
for (var j = 0; j < td.length; j++) {
cell = tr[i].getElementsByTagName("td")[j];
if (cell) {
if (cell.textContent.toUpperCase().indexOf(filter0)>-1 ||
cell.textContent.toUpperCase().indexOf(filter1)>-1) {
tr[i].style.display = "";
break;
}
}
}
}
}
<body>
<input type="text" id="myInput0">
<input type="text" id="myInput1">
<input type='button' onclick='myFunction()' value='click me' />
<table id="myTable">
<thead>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Gender</th>
<th>Department</th>
</tr>
</thead>
<tbody>
<tr>
<td>John</td>
<td>Doe</td>
<td>Male</td>
<td>Sales</td>
</tr>
<tr>
<td>Mary</td>
<td>Moe</td>
<td>Female</td>
<td>Service</td>
</tr>
<tr>
<td>July</td>
<td>Dooley</td>
<td>Female</td>
<td>Service</td>
</tr>
<tr>
<td>Anja</td>
<td>Ravendale</td>
<td>Female</td>
<td>Engineering</td>
</tr>
<tr>
<td>Thomas</td>
<td>Dubois</td>
<td>Male</td>
<td>Sales</td>
</tr>
<tr>
<td>Deidre</td>
<td>Masters</td>
<td>Female</td>
<td>Sales</td>
</tr>
<tr>
<td>Sean</td>
<td>Franken</td>
<td>Male</td>
<td>Engineering</td>
</tr>
</tbody>
</table>
</body>
For each cell, you can check each filter separately, then only change the DOM for rows where all filter conditions are met.
(This example uses a restructured version of your code.)
document.getElementById("myInput0").value = 'Female';
document.getElementById("myInput1").value = 'Engineering';
const
input0 = document.getElementById("myInput0"),
input1 = document.getElementById("myInput1"),
table = document.getElementById("myTable"),
rows = table.getElementsByTagName("tr");
function myFunction() {
filter0 = input0.value.toUpperCase(),
filter1 = input1.value.toUpperCase();
for (let row of rows) {
row.classList.add("hidden");
const cells = row.getElementsByTagName("td");
let
filter0met = false,
filter1met = false;
for (let cell of cells) {
if (cell.textContent.toUpperCase().includes(filter0)) {
filter0met = true;
}
if (cell.textContent.toUpperCase().includes(filter1)) {
filter1met = true;
}
}
if (filter0met && filter1met) {
row.classList.remove("hidden");
}
}
}
.hidden {
display: none;
}
<body>
<input type="text" id="myInput0"><input type="text" id="myInput1"><input type='button' onclick='myFunction()' value='click me' />
<table id="myTable">
<thead>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Gender</th>
<th>Department</th>
</tr>
</thead>
<tbody>
<tr>
<td>John</td>
<td>Doe</td>
<td>Male</td>
<td>Sales</td>
</tr>
<tr>
<td>Mary</td>
<td>Moe</td>
<td>Female</td>
<td>Service</td>
</tr>
<tr>
<td>July</td>
<td>Dooley</td>
<td>Female</td>
<td>Service</td>
</tr>
<tr>
<td>Anja</td>
<td>Ravendale</td>
<td>Female</td>
<td>Engineering</td>
</tr>
<tr>
<td>Thomas</td>
<td>Dubois</td>
<td>Male</td>
<td>Sales</td>
</tr>
<tr>
<td>Deidre</td>
<td>Masters</td>
<td>Female</td>
<td>Sales</td>
</tr>
<tr>
<td>Sean</td>
<td>Franken</td>
<td>Male</td>
<td>Engineering</td>
</tr>
</tbody>
</table>
</body>
After much trial and error for I was able to put together some JQuery that will dynamically search the first input, and then search those results for the second input. Note, I am using SP2016. While I've included it here in my post, I could not get the call to "https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js" to work. I found downloading and storing the file on my SharePoint site worked. For my requirement I wanted to display my list with grouped rows so I'm using a function to collapse the groups on load. The caveat is the groups in listview have to be configured as expanded.
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!DOCTYPE html>
<html>
<head>
<SCRIPT type="text/javascript"src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></SCRIPT>
<script>
//If rows are not grouped, remove this function
$(window).load(function () {
$(".ms-commentcollapse-icon").click();
});
$(document).ready(function() {
$("#myInput").on("keyup", function() {
var value = this.value.toLowerCase();
//If rows are not grouped, remove this line
$(".ms-commentexpand-icon").click();
$('.ms-listviewtable > tbody > tr').addClass('myInputMismatch').filter(function() {
return this.innerHTML.toLowerCase().indexOf(value) > -1;
}).removeClass('myInputMismatch');
});
$("#myInput1").on("keyup", function() {
var value = this.value.toLowerCase();
$('.ms-listviewtable > tbody > tr').addClass('myInput1Mismatch').filter(function() {
return this.innerHTML.toLowerCase().indexOf(value) > -1;
}).removeClass('myInput1Mismatch');
});
});
</script>
<style>
.myInputMismatch, .myInput1Mismatch { display: none; }
</style></head>
<input id="myInput" type="text" Placeholder="Search here 1st..."><input id="myInput1" type="text" Placeholder="Search here 2nd...">

Counting values from td's in jQuery

I have a problem with jQuery script. I'm trying to make a simple counting loop, for each tr. I got a table like below, and I want to select the second td, multiply it by two and add to the third td and display the result in the fourth td.
https://codepen.io/adeowsky/pen/YEgVKG
I'm trying to make it with the for each loop like below ->
<script>
(function($) {
$('.sp-league-table tbody tr').each( function() {
var pct = this.find('.data-pct').text();
console.log(pct);
//var pct = $('').hasClass('data-pct').text();
//console.log(pct);
var winy = $('.data-w').text();
var losy = $('.data-l').text();
/*var pkt = (winy*2) + (losy*2);
$('.data-pct').text(pkt);*/
});
})( jQuery );
</script>
But it doesn't work for me, where is the reason?
You are selecting all the elements with the class, not the one in the current row.
var tr = $(this);
var pCell = tr.find(".data-pct")
var wCell = tr.find('.data-w')
var lCell = tr.find('.data-l')
There are a couple of problems
Your table does not have the required class
you're not targeting the specific row's cells
You should explicitly parse the string values to integers
you've commented out the bit that does the calculation:
$(function(){
$('.sp-league-table tbody tr').each( function() {
var pct = $('.data-pct',this).text();
var winy = parseInt($('.data-w',this).text(),10);
var losy =parseInt($('.data-l',this).text(),10);
var pkt = (winy*2) + (losy*2);
$('.data-pct',this).text(pkt);
});
})
Updated: https://codepen.io/anon/pen/NwJjaO
Live example:
$(function(){
$('.sp-league-table tbody tr').each( function() {
var pct = $('.data-pct',this).text();
var winy = parseInt($('.data-w',this).text(),10);
var losy =parseInt($('.data-l',this).text(),10);
var pkt = (winy*2) + (losy*2);
$('.data-pct',this).text(pkt);
});
})
table, tr, td, th {
border: 1px solid #000;
border-collapse: collapse;
padding: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table class="sp-league-table">
<thead>
<tr>
<th>Name</th>
<th>W</th>
<th>L</th>
<th>PCT</th>
</thead>
<tr>
<td>Name 1</td>
<td class="data-w">12</td>
<td class="data-l">0</td>
<td class="data-pct">x</td>
</tr>
<tr>
<td>Name 2</td>
<td class="data-w">9</td>
<td class="data-l">3</td>
<td class="data-pct">x</td>
</tr>
</table>
<table class="sp-league-table">
<thead>
<tr>
<th>Name</th>
<th>W</th>
<th>L</th>
<th>PCT</th>
</thead>
<tr>
<td>Name 1</td>
<td class="data-w">12</td>
<td class="data-l">0</td>
<td class="data-pct">24</td>
</tr>
<tr>
<td>Name 2</td>
<td class="data-w">6</td>
<td class="data-l">5</td>
<td class="data-pct">17</td>
</tr>
</table>

dynamically added dom-elements not responding to jQuery-function

Consider the following code:
$(document).ready(function(){
var table1 = $("table").eq(0);
var row_list;
var rows;
var x;
var y;
$("#mybutton").click(function(){
row_list = table1.find("tr");
rows = row_list.length;
x = $("#field_x").val();
y = $("#field_y").val();
if(x>rows || y>rows){
var num;
if(x>y) num=x;
else num=y;
var n = num-rows;
var row; table1.find("tr").eq(0).clone();
while(1){
row = table1.find("tr").eq(0).clone();
table1.append(row);
n--;
if(n===0) break;
}
n = num-rows;
var td;
while(1){
td = table1.find("td").eq(0).clone();
table1.find("tr").append(td);
n--;
if(n===0) break;
}
}
var text = $("#text").val();
var css = $("#css").val();
$("table:eq(0) tr:eq(" + (x-1) + ") td:eq(" + (y-1) + ")").text(text).css("color", css);
});
table1.find("td").click(function(){
$(this).html("");
});
});
* {
font: 14px normal Arial, sans-serif;
color: #000000;
}
table {
margin: 50px auto;
}
table, td {
border: 1px solid #aaa;
border-collapse: collapse;
}
th {
padding: 10px;
font-weight: bold;
}
td {
background-color: #eeeeee;
width: 80px;
height: 80px;
}
table:first-child tr td {
cursor: pointer;
}
td[colspan="4"]{
text-align:center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tbody>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr>
<th colspan="4">Fill a field:</th>
</tr>
</thead>
<tbody>
<tr>
<td>Text: <br/><input type="text" id="text" value=""></td>
<td>Field X: <br/><input type="text" id="field_x" value=""></td>
<td>Field Y: <br/><input type="text" id="field_y" value=""></td>
<td>CSS: <br/><input type="text" id="css" value=""></td>
</tr>
<tr>
<td colspan="4"><button id="mybutton">Fill</button></td>
</tr>
</tbody>
</table>
What the program does is the following:
The user can choose a field by giving an x-value and a y-value. In this field the content from the input field with label "Text" is displayed.
- This part of the program works fine.
If the user chooses an x-value or a y-value larger than the current number of rows (columns), rows and columns are added until the number of rows/columns is equal to the value in the x-(or y-) field.
- This part of the program also works fine.
The only functionality that does not work is the following:
If the user clicks on one of the non-empty fields in the table, the content of the table is supposed to go back to its natural (empty) state.
To this end, the following function was added to the code (see last couple of lines in the javascript part of the code):
table1.find("td").click(function(){
$(this).html("");
});
This piece of code basically means:
If the user clicks on any box ("td") in the table, the content of this box should disappear.
This is more or less the most simple part of the code. But it's also the one aspect that doesn't work. More precisely: It works for the original boxes, but it doesn't work for any boxes that were added. - And I don't get why it behaved that way.
If you are dynamically adding elements to the DOM and expect to be attaching events to them, you should consider using event delegation via the on() function :
// This will wire up a click event for any current AND future 'td' elements
$(table1).on('click', 'td', function(){
$(this).html("");
});
Simply using click() on it's own will only wire up the necessary event handlers for elements that exist in the DOM at the time of that function being called.
You're assigning the event handlers before the user has a chance to input any data. This means that if an additional row or column is added, the new <td>s need event handlers added manually.
Alternately, you can add a single click handler to the entire table:
table1.click(function (ev) { $(ev.target).html(''); }
The ev.currentTarget property will be the <table> element because that's the element the event handler is registered to, but the ev.target property will be the <td> element that you're looking for.
Here's a JSFiddle to experiment with.
Hey there here's what I thought the answer might be,
HTML File:
<!DOCTYPE html>
<html lang="de-DE">
<head>
<meta charset="UTF-8" />
<style>
* {
font: 14px normal Arial, sans-serif;
color: #000000;
}
table {
margin: 50px auto;
}
table, td {
border: 1px solid #aaa;
border-collapse: collapse;
}
th {
padding: 10px;
font-weight: bold;
}
td {
background-color: #eeeeee;
width: 80px;
height: 80px;
}
table:first-child tr td {
cursor: pointer;
}
td[colspan="4"]{
text-align:center;
}
.pre-height {
min-height: 80px;
}
</style>
</head>
<body>
<table>
<tbody>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td class="pre-height"></td>
<td class="pre-height"></td>
<td class="pre-height"></td>
<td class="pre-height"></td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr>
<th colspan="4">Fill a field:</th>
</tr>
</thead>
<tbody>
<tr>
<td>Text: <br/><input type="text" id="text" value=""></td>
<td>Field X: <br/><input type="text" id="field_x" value=""></td>
<td>Field Y: <br/><input type="text" id="field_y" value=""></td>
<td>CSS: <br/><input type="text" id="css" value=""></td>
</tr>
<tr>
<td colspan="4"><button id="myButton">Fill</button></td>
</tr>
</tbody>
</table>
<script src="jquery.min.js"></script>
<script src="jack.js"></script>
</body>
</html>
JACK.JS file:
window.onload = function() {
'use strict';
/**
* Appends 'n' number of rows to the table body.
*
* #param {Number} n - Number of rows to make.
*/
var makeRows = function(n) {
let tbody= document.getElementsByTagName("table")[0].getElementsByTagName("tbody")[0],
tr = document.querySelector("table:first-of-type tbody tr");
for (let i = 0; i < n; i++) {
let row = Node.prototype.cloneNode.call(tr, true);
tbody.appendChild(row);
}
};
/**
* Appends 'n' number of cells to each row.
*
* #param {Number} n - Number of cells to add to each row.
*/
var makeColumns = function(n) {
let addNCells = (function(n, row) {
for (let i = 0; i < n; i++) {
let cell = Node.prototype.cloneNode.call(td, true);
row.appendChild(cell);
}
}).bind(null, n);
let tbody= document.getElementsByTagName("table")[0].getElementsByTagName("tbody")[0],
td = document.querySelector("table:first-of-type tbody tr td"),
rows = document.querySelectorAll("table:first-of-type tbody tr");
rows.forEach(function(row) {
addNCells(row);
});
};
document.getElementById("myButton").addEventListener("click", () => {
let x = document.getElementById("field_x").value,
y = document.getElementById("field_y").value;
makeColumns(x);
makeRows(y);
});
/**
* Newly added code
*/
(function() {
let table = document.querySelector("table");
// We will add event listener to table.
table.addEventListener("click", (e) => {
e.target.innerHTML = "";
e.target.style.backgroundColor = "orange";
});
})();
};
Edit: And I didn't even answer the question completely. You might wanna attach event listener to the nearest non-dynamic parent so that click event will bubble up and you can capture that, check the code under the comment newly added code.

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