Let's say I create a table in HTML which contains a background colour and text. Essentially I want to extract that text from the table using JS in row-major order as long as the text colour doesn't match the background colour.
For example, say this is my table:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Build a table</title>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="test.js"></script>
<table>
<tbody>
<tr>
<td style="color: #ff00ff; background-color:#FFFFFF">Q</TD>
<td style="background-color: #442244; color: #442244">Y</td>
<td style="color: #FFFF00; background-color:#442244">A</td>
</tr>
<tr>
<td style="color: #FFEEFE; background-color:#990000">Q</td>
<td style="color: #FFFF00; background-color:#FF0">M</td>
<td style="color: #000000; background-color:#FF7777">O</td>
</tr>
</tbody>
</table>
<p id="result"></p>
</body>
I'd get a 3x2 table.
So now I want to get the output to be a concatenated string such as
QAQO since Y and M are invisible
Obviously I need to create a function in JS and I have looked around But i'm not sure what to exactly search when it comes to extracting text from a table and printing it out whilst concatenating
test.js
function getText() {
var arr = $('td').map(function() {
let $td = $(this);
return $td.css('background-color') !== $td.css('color') ? $td.text() : null;}).get();
console.log(arr.join(''));
$('#result').text(arr.join(''));
}
You need to loop through each row and find the td where the background-color is different to the color.
The simplest way to do that would be to use map() to build an array of the values which you can then loop through, or concatenate as needed:
jQuery(function($) {
var arr = $('td').map(function() {
let $td = $(this);
return $td.css('background-color') !== $td.css('color') ? $td.text() : null;
}).get();
console.log(arr.join(''));
$('#result').text(arr.join(''));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tbody>
<tr>
<td style="color: #ff00ff; background-color: #FFFFFF;">Q</td>
<td style="color: #442244; background-color: #442244;">Y</td>
<td style="color: #FFFF00; background-color: #442244;">A</td>
</tr>
<tr>
<td style="color: #FFEEFE; background-color: #990000;">Q</td>
<td style="color: #FFFF00; background-color: #FF0;">M</td>
<td style="color: #000000; background-color: #FF7777;">O</td>
</tr>
</tbody>
</table>
<p id="result"></p>
Using jQuery:
let concString = "";
$('table tbody').find('tr').each(function(){
$(this).find('td').each(function(){
// condition to get only visible td
if($(this).css('background-color') !== $(this).css('color')){
concString += $(this).text();
}
});
});
console.log(concString);
Related
I want to build a page like this, where column B should be editable and whenever the user makes changes in value in column B, Total should be recalculated accordingly.
I want to build a page like this, where column B should be editable and whenever the user makes changes in value in column B, Total should be recalculated accordingly.
I want to build a page like this, where column B should be editable and whenever the user makes changes in value in column B, Total should be recalculated accordingly.
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<style>
table, td, th {
border: 1px solid black;
}
table {
border-collapse: collapse;
}
th {
}
</style>
</head>
<body>
<table id="myTable">
<col width="130">
<col width="80">
<tr>
<th>A</th>
<th>B</th>
</tr>
<tr>
<td>Rent</td>
<td class="someClass" contenteditable="true">400</td>
</tr>
<tr>
<td>Food</td>
<td class="someClass" contenteditable="true">200</td>
</tr>
<tr>
<td>Entertainment</td>
<td class="someClass" contenteditable="true">100</td>
</tr>
<tr>
<td>Transportation</td>
<td class="someClass" contenteditable="true">50</td>
</tr>
<tr>
<th>Total</th>
<td class="someTotalClass">200</td>
</tr>
</table>
<script>
function sumOfColumns(){
var totalQuantity = 0;
var totalPrice = 0;
$(".someClass").each(function(){
totalQuantity += parseInt($(this).html());
$(".someTotalClass").html(totalQuantity);
});
$(".classPrice").each(function(){
totalPrice += parseInt($(this).html());
$(".someTotalPrice").html(totalPrice);
});
}
sumOfColumns()
</script>
</body>
</html>
.blur() will bind a handler to function to the blur JavaScript event - you should be fine to just add this beneath your current function in the script tags.
Normally I would say use .change() but that doesn't seem to work with contenteditable divs. If it is possible for you to change to using <input> rather than <div contenteditable="true"> then this could be an alternative for you
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<style>
table,
td,
th {
border: 1px solid black;
}
table {
border-collapse: collapse;
}
th {}
</style>
</head>
<body>
<table id="myTable">
<col width="130">
<col width="80">
<tr>
<th>A</th>
<th>B</th>
</tr>
<tr>
<td>Rent</td>
<td class="someClass" contenteditable="true">400</td>
</tr>
<tr>
<td>Food</td>
<td class="someClass" contenteditable="true">200</td>
</tr>
<tr>
<td>Entertainment</td>
<td class="someClass" contenteditable="true">100</td>
</tr>
<tr>
<td>Transportation</td>
<td class="someClass" contenteditable="true">50</td>
</tr>
<tr>
<th>Total</th>
<td class="someTotalClass">200</td>
</tr>
</table>
<script>
function sumOfColumns() {
var totalQuantity = 0;
var totalPrice = 0;
$(".someClass").each(function() {
totalQuantity += parseInt($(this).html());
$(".someTotalClass").html(totalQuantity);
});
$(".classPrice").each(function() {
totalPrice += parseInt($(this).html());
$(".someTotalPrice").html(totalPrice);
});
}
sumOfColumns();
$('.someClass').blur(function() {
sumOfColumns()
});
</script>
</body>
</html>
so we all know document.getElementsByClassName and document.getElementsByTagName are live HTMLCollections.
I googled and can't seem to find the answer to this, maybe I just don't get it, who can explain it to me?
So I made 2 examples, one with adding a class attribute, the other with bgcolor. Why does the first act like expected and the other gets it's job done...
Why does the TagName one work differently even it's a HTMLCollection in the first example?
How can I know which will work normally and which wont??
https://jsfiddle.net/adkuca/84ryjp7s/2/
https://jsfiddle.net/adkuca/f1o9h7be/
var ran = document.getElementsByClassName('wasd');
/*var ran = document.getElementsByTagName('td');*/
document.getElementById('btn').addEventListener('click', func);
function func() {
console.log(ran); //HTMLCollection, all 6
console.log(ran.length); //6 with both
for (let i = 0; i < ran.length; i++) {
ran[i].setAttribute("class", "green");
}
console.log(ran); //HTMLCollection, all 6 with TagName, every 2nd with ClassName
console.log(ran.length); //6 with TagName, 3 with ClassName
}
tr, td {
border: 1px solid black;
height: 20px;
width: 20px;
}
.green {
background-color: green;
}
<!doctype html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<button id="btn">func</button>
<table>
<tr>
<td class="wasd"></td>
<td class="wasd"></td>
<td class="wasd"></td>
</tr>
<tr>
<td class="wasd"></td>
<td class="wasd"></td>
<td class="wasd"></td>
</tr>
</table>
</body>
</html>
var ran = document.getElementsByClassName('wasd');
/*var ran = document.getElementsByTagName('td');*/
document.getElementById('btn').addEventListener('click', func);
function func() {
console.log(ran); //HTMLCollection, all 6
console.log(ran.length); //6 with both
for (let i = 0; i < ran.length; i++) {
ran[i].setAttribute("bgcolor", "green");
}
console.log(ran); //HTMLCollection, all 6
console.log(ran.length); //6 with both
}
tr, td {
border: 1px solid black;
height: 20px;
width: 20px;
}
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<button id="btn">func</button>
<table>
<tr>
<td class="wasd"></td>
<td class="wasd"></td>
<td class="wasd"></td>
</tr>
<tr>
<td class="wasd"></td>
<td class="wasd"></td>
<td class="wasd"></td>
</tr>
</table>
</body>
</html>
They both work normally and in the same way. The className appears to work differently because you're effectively removing elements from the list you're working with, while you're going through it.
when you use setAttribute("class", "green"); you're replacing the "wasd" class with "green"
This will work if you add a class instead of replacing the current one using ele.classList.add(class)
https://jsfiddle.net/84ryjp7s/3/
Ok to sum it up for ppl who might have same question.
so if you get a collection with ClassName, means everything will be behaving normally untill you remove the current class you gathered the collection with.
if it was class="a b", you can add any class, but if you delete/change 1 of those it ruins the HTML collection
Same with any other HTMLCollection / live NodeList
if you gather with getElementsByTagName, you can change class but you can't change the td's, if you try to remove the div, you ruined the collection
https://jsfiddle.net/adkuca/c00fqmts/
as it counts you're removing td's, therefore chaning the HTML collection, shrinking it by 1, therefore shrinking the ran.length by 1, so you get half iterations, and you add a new td half less.
examine this: https://jsfiddle.net/adkuca/c7jb0es8/
but if you really want to do gather classes with classname and then change them, you can store them into an array and then change.
Array.from(document.getElementsByClassName('wasd')).forEach(function(itm){
itm.setAttribute('replaced-wasd');
});
var ran = document.getElementsByClassName('wasd');
/*var ran = document.getElementsByTagName('td');*/
document.getElementById('btn').addEventListener('click', func);
function func() {
console.log(ran); //HTMLCollection, all 6
console.log(ran.length); //6 with both
for (let i = 0; i < ran.length; i++) {
console.log(ran.length);
ran[i].setAttribute("class", "green");
console.log(ran.length);
console.log("i = " + i);
console.log(ran);
}
console.log(ran); //HTMLCollection, all 6 with TagName, every 2nd with ClassName
console.log(ran.length); //6 with TagName, 3 with ClassName
}
tr, td {
border: 1px solid black;
height: 20px;
width: 20px;
}
.green {
background-color: green;
}
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<button id="btn">func</button>
<table>
<tr>
<td class="wasd"></td>
<td class="wasd"></td>
<td class="wasd"></td>
<td class="wasd"></td>
<td class="wasd"></td>
<td class="wasd"></td>
</tr>
<tr>
<td class="wasd"></td>
<td class="wasd"></td>
<td class="wasd"></td>
<td class="wasd"></td>
<td class="wasd"></td>
<td class="wasd"></td>
</tr>
</table>
</body>
</html>
Hiding a column on unchecking a checkbox
NOTE: Before you point to links based on the same question, I need to tell I tried all the relevant solutions here and nothing worked. I signed up precisely coz none of the solutions here actually worked.
So, my code lets you create a table dynamically and edit the table contents as well. For every new column created,a checkbox is also added which when unselected hides the created column.
This is my code:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="https://code.jquery.com/jquery-1.9.1.js"></script>
<script type="text/javascript" src="https://code.jquery.com/jquery-1.4.4.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type='text/javascript'>
function addrow()
{
first_row = $('#Row1');
first_row.clone().appendTo('random');
}
function addcol()
{
var myform = $('#myform'),
iter = 1;
myform.find('tr').each(function(){
var trow = $(this);
if(trow.index() === 0){
trow.append('<th contenteditable="true" class="COLUMN_'+iter+'"><b>COLUMN # '+iter+'</b></td>');
var labelname = "Show COLUMN #" +iter;
var create = $('<input type="checkbox" name="COLUMN_'+iter+'" checked="checked"><label>'+labelname+'</label><br>');
$(".noprint").append(create);
}else{
trow.append('<td class="COLUMN_'+iter+'" contenteditable="true"></td>');
}
});
iter += 1;
}
$(window).load(function(){
$("input:checkbox").click(function(){
var column = "."+$(this).attr("name");
$(column).toggle();
});
});
</script>
<style>
table {
font-family: arial, sans-serif;
border-collapse: collapse;
}
td, th {
border: 1px solid #dddddd;
text-align: left;
padding: 8px;
}
tr:nth-child(even) {
background-color: #dddddd;
}
</style>
</head>
<body>
<input type="button" value="Add new row" onclick="addrow()"/> <input type="button" value="Add new column" onclick="addcol()"/>
<br>
<br>
<span class="noprint"> </span>
<form id="myform">
<table id="random" width="70%">
<tr>
<th>Name 1</th>
<th>Name 2</th>
</tr>
<tr id="Row1">
<td contenteditable="true">Entry 1</td>
<td contenteditable="true">Entry 2</td>
</tr>
<tr>
<td contenteditable="true">Entry 3</td>
<td contenteditable="true">Entry 4</td>
</tr>
</table>
</form>
</body>
</html>
I'm unable to hide the columns based on the checkbox status. Can someone tell me what I'm doing wrong?
Try this...
$(“#myform”).on(“click”,”input[type=‘checkbox’]”,function(){
var column = "."+$(this).attr("name");
$(column).toggle();
});
Since your checkbox elements are added later, you need to listen for the click event on the parent element and then bind to the child.
I'm trying my hand at building a tic-tac-toe game with plain vanilla Javascript, so I'm hoping we can stay in the boundaries of keeping it vanilla.
What I require is the following: If a square is already clicked on/occupied by either and "X" or an "O", that square cannot be overridden and an alert/pop-up appears and says to choose another square.
Thank you for your assistance and time!
Here is the code I have got so far:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Tic Tac Toe</title>
<style>
td {
border: 1px solid black;
height: 250px;
width: 250px;
font-family: sans-serif;
font-size: 150pt;
text-transform: uppercase;
}
</style>
</head>
<body>
<table>
<tr>
<td align="center" id="square1" onclick="displayMarker('square1');"></td>
<td align="center" id="square2" onclick="displayMarker('square2');"></td>
<td align="center" id="square3" onclick="displayMarker('square3');"></td>
</tr>
<tr>
<td align="center" id="square4" onclick="displayMarker('square4');"></td>
<td align="center" id="square5" onclick="displayMarker('square5');"></td>
<td align="center" id="square6" onclick="displayMarker('square6');"></td>
</tr>
<tr>
<td align="center" id="square7" onclick="displayMarker('square7');"></td>
<td align="center" id="square8" onclick="displayMarker('square8');"></td>
<td align="center" id="square9" onclick="displayMarker('square9');"></td>
</tr>
</table>
<script>
var cp1 = 1;
function displayMarker(allSquares) {
if (cp1==1) {
document.getElementById(allSquares).innerHTML = "X";
cp1 = 2;
}
else {
document.getElementById(allSquares).innerHTML = "O";
cp1 = 1;
}
}
</script>
</body>
</html>
Check if value (innerHTML) of the square is not empty. Alert and return from the function in that case.
function displayMarker(allSquares) {
var square = document.getElementById(allSquares);
if (square.innerHTML.trim() != "") {
return alert("Choose another square");
}
// ...
I want to highlight the current line when mouse moves, is it possible?
It's not table rows, just plain text in paragraphs.
I'm writing a reading helper plugin for Google Chrome, to help browsing within a big chunk of text.
Depends on your definition of "line". If it's a table row or something you can refer to, you can simply do something like this
<table>
<tbody>
<tr>
<td> Item 1</td><td> Item 2</td>
</tr>
<tr>
<td> Item 1</td><td> Item 2</td>
</tr>
</tbody>
</table>
And use this in your stylesheet
table tr:hover td {
background-color: #dddddd;
}
If you want to highlight Table row then apply this
<STYLE>
<!--
tr { background-color: #DDDDDD}
.initial { background-color: #DDDDDD; color:#000000 }
.normal { background-color: #CCCCCC }
.highlight { background-color: #8888FF }
//-->
</style>
<table border="0" cellspacing="0" bgcolor="#CCCCCC" cellpadding="0">
<tr>
<td bgcolor="#FFCC00" WIDTH="100"><b>Brand</b></td>
<td bgcolor="#FFCC00" WIDTH="100"><b>Dimensions</b></td>
<td bgcolor="#FFCC00" WIDTH="100"><b>Price</b></td>
</tr>
<tr style="background-color:#CCCCCC;"
onMouseOver="this.className='highlight'" onMouseOut="this.className='normal'">
<td>Row A</td>
<td>200x300</td>
<td>$200,000.00</td>
</tr>
</table>
If each line is enclosed with in HTML element of there own the and event handler can be attached.
<html>
<script type="text/javascript" src="./jquery-1.4.2.min.js"> </script>
<script type="text/javascript" >
$(document).ready(function() {
$(".lineclass").hover(function() {
$(this).css("backgroundColor","red");
},
function() {
$(this).css("backgroundColor","");
});
});
</script>
<body>
<p class="lineclass">This is line 1</p><br />
<p class="lineclass">This is line 2</p><br />
<p class="lineclass">This is line 3</p><br />
</body>
</html>