Highlight repeating strings - javascript

I have up to three almost-identical divs that contain tables of usernames. Some names may be repeated across the three divs. I'd like to highlight the names that are repeated. The first occurrence of the user should not be colored, the second occurrence should have an orange background and the third should have a red background. The divs go from left to right in order so the first div should not have any highlighted usernames.
My HTML looks like:
<div class="col-md-4">
<table class="table table-striped">
<tr>
<th>2/26/2014</th>
</tr>
<tr>
<td>user1</td>
</tr>
<tr>
<td>user2</td>
</tr>
<tr>
<td>user5</td>
</tr>
<tr>
<td>user17</td>
</tr>
</table>
</div>
<div class="col-md-4">
<table class="table table-striped">
<tr>
<th>2/27/2014</th>
</tr>
<tr>
<td>user13</td>
</tr>
<tr>
<td>user5</td>
</tr>
<tr>
<td>user7</td>
</tr>
</table>
</div>
<div class="col-md-4">
<table class="table table-striped">
<tr>
<th>2/28/2014</th>
</tr>
<tr>
<td>user5</td>
</tr>
<tr>
<td>user45</td>
</tr>
<tr>
<td>user1</td>
</tr>
</table>
</div>
I know that the username table cells will be selected with $('table.table td') (if I use jQuery) but I'm not sure what to do from there.
Please let me know if you have any questions.
Thank you.

Is this what you want?
I created a map to store text-occurrence pairs. Each time the text is repeated, the counter associated with it gets incremented. If the counter climbs to a certain value, the background will be set to another color. Give it a shot!
DEMO
var map = new Object();
$('td').each(function() {
var prop = $(this).text()
var bgColor = '#FFFFFF';
if (map[prop] > 1) {
bgColor = '#FF0000';
} else if (map[prop] > 0) {
bgColor = '#FF7F00';
}
$(this).css('background', bgColor);
if (map.hasOwnProperty(prop)) {
map[prop]++;
} else {
map[prop] = 1;
}
});

You could try something like this but I didn't test it
$('td').each(function(){
var text = this.html();
$('td:contains("'+text+'"):nth-child(2)').css({'background':'orange'});
$('td:contains("'+text+'"):nth-child(3)').css({'background':'red'});
});
Edit:
Not particularly elegant but it seems to work
http://jsfiddle.net/63L7L/1/
var second = [];
var third = [];
$('td').each(function(){
var text = $(this).html();
second.push($("td").filter(function() {
return $(this).text() === text;
})[1])
third.push($("td").filter(function() {
return $(this).text() === text;
})[2])
});
$(second).each(function(){
$(this).css({'background':'red'});
});
$(third).each(function(){
$(this).css({'background':'orange'});
});

With pure Javascript (ECMA5)
CSS
.orange {
background-color:orange;
}
.red {
background-color:red;
}
Javascript
Array.prototype.forEach.call(document.querySelectorAll('.table-striped td'), function (td) {
var textContent = td.textContent;
if (this.hasOwnProperty(textContent)) {
td.classList.add(++this[textContent] === 2 ? 'orange' : 'red');
} else {
this[textContent] = 1;
}
}, {});
On jsFiddle

Related

Showing and Hiding Table Rows Based Off Alphabet Buttons

I have a table with a lot of rows in it, and I want to give users the ability to click an 'A' button and all the results that start with 'A' are displayed. They could do the same for every letter. This is what I've come up with so far:
HTML
<input type="button" id="aSort" value="A" onclick="alphaSort(this.value);">
<table>
<thead>
<tr>
<td>Title</td>
<td>Description</td>
<td>Active</td>
</tr>
</thead>
<tbody>
<tr>
<td name="title">Apple</td>
<td>It's a fruit</td>
<td>Active</td>
</tr>
<tr>
<td name="title">Pear</td>
<td>It's also fruit</td>
<td>No</td>
</tr>
</tbody>
</table>
JS
function alphaSort(val) {
//pseudocode
var $rows = $('td[name=title]');
$rows.forEach(function(e) {
if(e.innerText == val + '%') {
e.closest('tr').show();
} else {
e.closest('tr').hide();
}
}
}
So with what I have here, the idea is if the user clicked the button only the Apple row would show. Ideally the function would be case insensitive. Could someone help me with how to properly iterate through all the table rows efficiently and compare the value stored in the title row?
you can use startsWith function : https://www.w3schools.com/jsref/jsref_startswith.asp
like this :
$("#aSort").click(function(){
var $rows = $('td[name=title]');
var val = $(this).val()
$rows.each(function() {
if($(this).text().startsWith(val)) {
$(this).closest('tr').show();
} else {
$(this).closest('tr').hide();
}
})
})
https://jsfiddle.net/xpvt214o/899140/

Hide table if its <td> is empty (Using only JS)

I want to hide a table if its "td" empty.
I'm trying to use this function, but it's not working:
function isEmptyTable(){
var tdTable = document.getElementsByName('tdTable').textContent;
var table = document.getElementsByName('tableToday');
if(tdTable == "")
table.style.display = 'none';
}
Any tips?
HTML:
<body onload="isEmptyTable()">
<table name="tableToday">
<thead>
<tr>
<th>Prêmio</th>
<th>Resultado</th>
<th>Grupo</th>
</tr>
</thead>
<tbody>
<tr>
<th>1º</th>
<td name="tdTable">oi</td>
<td name="tdTable"></td>
</tr>
</tbody>
</table>
I'd use the getElementById and the getElementsByClassName selectors to achieve this:
function isEmptyTable(myId){
let tds = document.getElementsByClassName(myId);
let hide = false
for (let element of tds) {
if (element.innerHTML.length == 0) hide = true
}
let myTable = document.getElementById(myId);
if (hide) myTable.style.display = 'none';
}
isEmptyTable("myTable")
isEmptyTable("myTable2")
td {
border: 1px solid red;
}
<table id="myTable">
<tr>
<td class="myTable"></td>
<td class="myTable">
lololo
</td>
</tr>
</table>
<table id="myTable2">
<tr>
<td class="myTable2">asdasd</td>
<td class="myTable2">
lololo
</td>
</tr>
</table>
in your code just change these two lines. because the td will return in collection so use array index [0]
function isEmptyTable(){
var tdTable = document.getElementsByName('tdTable')[0].textContent;
var table = document.getElementsByName('tableToday')[0];
if(tdTable == "")
table.style.display = 'none';
}
it will work fine.
The problem is in the part:
var tdTable = document.getElementsByName('tdTable').textContent;
and
table.style.display = 'none';
Because the function document.getElementsByName() doesn't return a simple variable , it's return an array , so to solve the problem you have to change the part:
var tdTable = document.getElementsByName('tdTable').textContent;
to
var tdTable = document.getElementsByName('tdTable')[0].textContent;
and change table.style.display = 'none'; to table[0].style.display = 'none';
For more information about document.getElementsByName() Click here

CSS odd & even on dynamic table

I'm using the following piece of jQuery applied to an input field to narrow a list of items shown in a table (a real table, with tr and td layout):
$(function(){
$("#search").keyup(function() {
var value = this.value.toLowerCase();
$(".table").find("tr").each(function(index) {
if (index === 0) return;
var id = $(this).find("td").text().toLowerCase();
$(this).toggle(id.indexOf(value) !== -1);
});
});
});
It works perfectly otherwise, but as the .table has .table tr:nth-child(odd) and (even) targeted styling for the initial layout, the odd & even rows get messed up when the list narrowing search filter applies.
So far I've been unlucky with removeClass and addClass when the rows change dynamically, am I missing something essential..?
A JSFiddle example can be check at https://jsfiddle.net/4cf8a01L/3/
kinda of a hacky way to do it - https://jsfiddle.net/6rk09jb0/1/
add odd and even class
.table tr:nth-child(odd),
.table tr.odd.odd {
background-color: #fff;
}
.table tr:nth-child(even),
.table tr.even.even {
background-color: #c0c0c0;
}
apply odd and even when filtering
$("#search").keyup(function() {
var value = this.value.toLowerCase();
var count = 0;
$(".table").find("tr").each(function(index) {
if (index === 0) return;
var id = $(this).find("td").text().toLowerCase();
var test = id.indexOf(value) !== -1;
var className = '';
if (test) {
count += 1;
className = count % 2 ? 'odd' : 'even';
}
$(this).toggle(test).attr('class', className);
});
});
Unfortunately :nth-child takes in to account all child elements, regardless of their visibility. To fix this you could use jQuery to apply your row stripes on visible rows on load of the page and also when the filter is changed, like this:
$("#search").keyup(function() {
var value = this.value.toLowerCase();
var $table = $('table');
$table.find("tbody tr").each(function(index) {
var id = $(this).find("td").text().toLowerCase().trim();
$(this).toggle(id.indexOf(value) !== -1);
});
stripeRows($table);
});
function stripeRows($table) {
$table.find('tr:visible:odd').css('background', '#FFFFFF');
$table.find('tr:visible:even').css('background', '#C0C0C0');
}
stripeRows($('table'));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="search" autofocus>
<table class="table">
<thead>
<tr>
<th>title 1</th>
<th>title 2</th>
<th>title 3</th>
</tr>
</thead>
<tbody>
<tr>
<td>data</td>
<td>goes</td>
<td>here</td>
</tr>
<tr>
<td>and</td>
<td>then</td>
<td>here</td>
</tr>
<tr>
<td>rows</td>
<td>repeat</td>
<td>this way</td>
</tr>
<tr>
<td>consisting</td>
<td>of hundres</td>
<td>of rows</td>
</tr>
<tr>
<td>cell</td>
<td>cell</td>
<td>cell</td>
</tr>
<tr>
<td>content</td>
<td>content</td>
<td>content</td>
</tr>
</tbody>
</table>
Note that the above only searches for tr within the tbody, instead of explicitly excluding the row at index 0.
Alternatively you can use the CSS you are now, but you need to remove() or detach() the tr when filtering, and then also have a system of putting them back in the correct place, either through sorting or explicitly setting their location.
While the CSS of this solution will be simpler, the logic required will be far more complex.

plain text to input text on click using javascript

I have a table that needs edit buttons in each row, on click the plain text should become input, I've read many tutorial but i understand none as i am new to javascript, can anyone help?
this is what i started with:
<script type="text/javascript">
function Edit(clickedButton){
//get row of the clicked button
var row = clickedButton.closest('tr');
'retrieve each info
var tdID = row.cells[0];
var tdFirstName = row.cells[1];
var tdLastName = row.cells[2];
var tdDOB = row.cells[3];
var tdGender = row.cells[4];
var tdStatud = row.cells[5];
</script>
and this in my table:
<table id="table" class="table .table-bordered" style="width:80%">
<thead>
<tr>
<th>ID</th>
<th>First Name</th>
<th>Last Name</th>
<th>DOB</th>
<th>Gender</th>
<th>Martial Status</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr id="frow">
<td>1</td>
<td>Samir</td>
<td>Khattar</td>
<td>1-12-1990</td>
<td>Male</td>
<td>Married</td>
<td>
<button onclick="Edit(this)">Edit</button>
<button onclick="Delete(this)">Delete</button>
</td>
</tr>
</tbody>
</table>
and whats the difference between .innerhtml and .html
At first take a form to get input as you want. Then hide the input area as default. And show As you are showing your table inside the form. If any of the button is clicked then the hidden input area will be shown and the the default table row will be hidden. This is the idea to do so.
innserHTML is a javascript DOM property. It return DOM's inner html, it can also be used as to change the inner html of that dom. On the other hand, html() is a jQuery library function to do the same work. May be this method of jQuery actually use the innserHTML property.
To know about the performance of innerHTML and & html() you can check out this link: .append VS .html VS .innerHTML performance
Best of luck
Simply do like this...it will work...
$(function () {
$("#table td").click(function (e) {
e.preventDefault(); // <-- consume event
e.stopImmediatePropagation();
$this = $(this);
if ($this.data('editing')) return;
var val = $this.text();
$this.empty()
$this.data('editing', true);
$('<input type="text" class="editfield">').val(val).appendTo($this);
});
putOldValueBack = function () {
$("#table .editfield").each(function(){
$this = $(this);
var val = $this.val();
var td = $this.closest('td');
td.empty().html(val).data('editing', false);
});
}
$(document).click(function (e) {
putOldValueBack();
});
});
//Refer this example
<table id="table">
<tr>
<th>RecID</th>
<th>Col1</th>
<th>Col2</th>
</tr>
<tr>
<td>RecID</td>
<td>Val1.1</td>
<td>Val1.2</td>
</tr>
<tr>
<td>RecID</td>
<td>Val2.1</td>
<td>Val2.2</td>
</tr>
<tr>
<td>RecID</td>
<td>Val3.1</td>
<td>Val3.2</td>
</tr>
</table>
Try this
function Edit(clickedButton){
var getTR = clickedButton.parentNode.parentNode;
var getLength = getTR.childElementCount;
var getTds = getTR.querySelectorAll("td")
for (i in getTds){
if(i < (getLength-1)){
getTds[i].innerHTML = "<input type='text' value='"+getTds[i].innerHTML+"'>";
}
}
}

How to keep adding data to next table column

This Fiddle Example shows a comparison table that dynamically shows information in a column when a button is clicked. Once the table is filled up, I want to start the whole process again. But as the example shows, the buttons are stuck at adding information to th:nth-child(2) and td:nth-child(2) during the second time instead of moving on to the next column like during the first time.
I'm guessing this part needs some change if( allCells === fullCells ) { to keep information being added to next columns.
HTML
<div class="area">
<button>Gah</button>
</div>
<div class="area">
<button>Kaj</button>
</div>
<div class="area">
<button>Fdw</button>
</div>
<div class="area">
<button>ffdf</button>
</div>
<table>
<thead>
<tr>
<th>Placeholder</th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>Age</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>Name</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>Race</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>Nationality</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>Education</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>Language</td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
Code:
$(function() {
$('.area').each(function(){
var area = $(this),
filltable ='',
button = $(this).find('button'),
buttontext = button.text();
button.on("click",function(){
var allCells = $('table').find('th,td').length;
var fullCells = $('table').find('th,td').filter(function() {
return $(this).text() != '';
}).length;
if( allCells === fullCells ) { // If table is full
$('table').find('th,td').not(':first-child').removeClass('addinfo');
filltable();
}
else { // If table isn't full
filltable = function(){
var i = $('th.addinfo').length !== 0 ? $('th.addinfo:last').index() : 0;
console.log( i );
i + 2 > $('th').length ||
$('th,td').filter(':nth-child(' + (i + 2) + ')')
.addClass( 'addinfo' ).html(buttontext);
}
filltable();
}
}); // end button on click function
});
});
Please see the attached link for demo. I have created a function name cleartable() which clears the table if its full and have used your old filltable() function to repopulate. There is repetition of code which you will have to clean up.
th:nth-child(2) identifies second child of th.
td:nth-child(2) identifies second column.
Similarly if you wanted to do something with let say second row, you can use tr:nth-child(2).
I hope this helps you understand a little about parent-child relationship in jquery.
JSFIDDLE DEMO
function clearTable() {
$('table th:nth-child(2)').html('');
$('table th:nth-child(3)').html('');
$('table th:nth-child(4)').html('');
$('table td:nth-child(2)').html('');
$('table td:nth-child(3)').html('');
$('table td:nth-child(4)').html('');
}
http://jsfiddle.net/jqVxu/1/
I think you'd better to count th only. count all td and th make me confused.
$(function () {
function filltable(buttontext) {
var i = $('th.addinfo').length !== 0 ? $('th.addinfo:last').index() : 0;
i + 2 > $('th').length || $('th,td').filter(':nth-child(' + (i + 2) + ')')
.addClass('addinfo').html(buttontext);
}
$('.area').each(function () {
var area = $(this),
button = $(this).find('button'),
buttontext = button.text();
button.on("click", function () {
var allCells = $('table').find('th').length-1;
var fullCells = $('table th.addinfo').length;
console.log(allCells, fullCells);
if (allCells === fullCells) { // If table is full
$('table .addinfo').removeClass('addinfo');
filltable(buttontext);
} else { // If table isn't full
filltable(buttontext);
}
});
});
});

Categories

Resources