Javascript onClick event in all cells - javascript

I'm learning JavaScript and I've not that much experience.
But I'm making a HTML table and I want to add in every table cell (<td>) a onClick event.
<table id="1">
<tr>
<td onClick="tes()">1</td><td onClick="tes()">2</td>
</tr>
<tr>
<td onClick="tes()">3</td><td onClick="tes()">4</td>
</tr>
</table>
Is there another way to do this event in every cell?

I know this is a bit old, but you should use a click envent on the table and use the target value to get the cell. Instead of having a 10 x 10 table = 100 event you will have only 1.
The best thing with that method is when you add new cells you don't need to bind an event again.
$(document).ready( function() {
$('#myTable').click( function(event) {
var target = $(event.target);
$td = target.closest('td');
$td.html(parseInt($td.html())+1);
var col = $td.index();
var row = $td.closest('tr').index();
$('#debug').prepend('<div class="debugLine">Cell at position (' + [col,row].join(',') + ') clicked!</div>' );
});
});
td {
background-color: #555555;
color: #FFF;
font-weight: bold;
padding: 10px;
cursor: pointer;
}
#debug {
background-color: #CCC;
margin-top: 10px;
padding: 10px;
}
#debug .debugLine {
margin: 2px 0;
padding: 1px 5px;
background-color: #EEE;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="myTable">
<tr>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
</table>
<div id="debug"></div>

You may try this too (using event delegation)
window.onload = function(){
document.getElementById('tbl1').onclick = function(e){
var e = e || window.event;
var target = e.target || e.srcElement;
if(target.tagName.toLowerCase() == "td") {
alert(target.innerHTML);
}
};
};
EXAMPLE.
Using jQuery
$(function(){
$('#tbl1').on('click', 'td', function(){
alert($(this).html());
});
});
EXAMPLE.

There are two ways:
var cells = table.getElementsByTagName("td");
for (var i = 0; i < cells.length; i++) {
cells[i].onclick = function(){tes();};
}
and the other way using jQuery:
$('td').click(function(){tes();});
upd:
To get exactly what is needed, firstly the table must be selected, so, for the first option:
var table = document.getElementById('1');
var cells = table.getElementsByTagName("td");
...
and for the second, the jQ selector should be like this:
$('#1 td')

Just the following code will return the contained text of the clicked element. In this case the td
event.target.innerText
Example:
td
{
border: 1px solid red;
}
<table onclick="alert(event.target.innerText)">
<tr>
<td>cell 1</td>
<td>cell 2</td>
</tr>
<tr>
<td>cell 3</td>
<td>cell 4</td>
</tr>
</table>
Of course you can implement it into a js and attach it to the onclick event as usual (search for the addEventListener() function in javascript).
If needed you can separate the table into thead, tbody tfoot and add the onclick event to the tbody only. In this way the event will be triggered only if the user clicks on this section of the table and not when he clicks on other elements...

Try :
var tds = document.getElementsByTagName("td");
for(var i in tds) tds[i].onclick = tes;
and a Demo...
Replace document with any other dom element that you need to find td's in.

You can do something like that:
var tbl = document.getElementById("1");
var numRows = tbl.rows.length;
for (var i = 1; i < numRows; i++) {
var ID = tbl.rows[i].id;
var cells = tbl.rows[i].getElementsByTagName('td');
for (var ic=0,it=cells.length;ic<it;ic++) {
cells[ic].OnClick = new function() {tes()};
}
}

if you have access to jquery, do this
$('#1 td').click(function(){
});

You might not require putting onclick event on every TD element in your table. Providing onclickevent at the table level can do the trick easily as shown in the below code snippet:
function tes(event) {
if (event.target.nodeName == "TD") {
alert('TD got clicked');
}
}
td {
border: 1px solid black;
}
<html>
<head>
<title>Tic-Tac-Toe</title>
<meta charset="UTF-8" />
</head>
<body>
<div id="app">
<table id='gameBoard' width="300" height="300" onclick="tes(event);">
<tr>
<td data-index = "0 0"></td>
<td data-index = "0 1"></td>
<td data-index = "0 2"></td>
</tr>
<tr>
<td data-index = "1 0"></td>
<td data-index = "1 1"></td>
<td data-index = "1 2"></td>
</tr>
<tr>
<td data-index = "2 0"></td>
<td data-index = "2 1"></td>
<td data-index = "2 2"></td>
</tr>
</table>
</div>
</body>
</html>
You can do the appropriate handling inside tes function with the help of event parameter.

Related

Alternative to .nextSibling?

I'm currently working on a project and I have to fill different column of a table, for that I'm using .nextSibling, but the lines can be very long if I target, let's say the 4th column:
firstTd.nextSibling.nextSibling.nextSibling.nextSibling.innerHTML = "example";
So I was wondering if there was any more elegant way of doing it, that doesn't require writing .nextSibling every time?
Just make a small helper:
const sibling = (el, count) => count ? sibling(el.nextSibling, count - 1) : el;
Which can be used as
sibling(firstTd, 5).innerHTML = "example";
Rather than relying on a specific position like that, which is inherently brittle (what if you add a new column?), I'd suggest giving your target td some kind of identifying mark, like a class name or data-* attribute. Then you'd use:
tr.querySelector(".the-class").innerHTML = "example";
if you don't have tr handy, you can get it from firstTd.parentNode.
Naturally, because querySelector doesn't just look at children but all descendants, you'll want to plan for that.
Live example:
// In a real situation I'd use a delegated handler, but the goal here is to
// show that the same code works regardless of the starting point
document.querySelectorAll("td:not(.x)").forEach(el => {
el.addEventListener("click", function() {
this.parentNode.querySelector(".ex").innerHTML = Math.random();
});
});
table {
border-collapse: collapse;
border: 1px solid #aaa;
}
td {
border: 1px solid #aaa;
padding: 4px;
}
<table>
<tbody>
<tr>
<td>Click me</td>
<td>Or me</td>
<td>Or me</td>
<td class="ex"></td>
</tr>
</tbody>
</table>
Alternately, give yourself a "find my next matching sibling" function that accepts a selector:
const findNext = (el, selector) => {
let sib = el.nextElementSibling;
while (sib && !sib.matches(selector)) {
sib = sib.nextElementSibling;
}
return sib;
};
then
findNext(firstTd, ".the-class").innerHTML = "example";
Live example:
const findNext = (el, selector) => {
let sib = el.nextElementSibling;
while (sib && !sib.matches(selector)) {
sib = sib.nextElementSibling;
}
return sib;
};
// In a real situation I'd use a delegated handler, but the goal here is to
// show that the same code works regardless of the starting point
document.querySelectorAll("td:not(.x)").forEach(el => {
el.addEventListener("click", function() {
findNext(this, ".ex").innerHTML = Math.random();
});
});
table {
border-collapse: collapse;
border: 1px solid #aaa;
}
td {
border: 1px solid #aaa;
padding: 4px;
}
<table>
<tbody>
<tr>
<td>Click me</td>
<td>Or me</td>
<td>Or me</td>
<td class="ex"></td>
</tr>
</tbody>
</table>
Table rows and cells can be accessed by index:
table1.rows[2].cells[2].innerText = 42
<table id=table1>
<tr> <th> A </th> <th> B </th> <th> C </th> </tr>
<tr> <td> 1 </td> <td> 2 </td> <td> 3 </td> </tr>
<tr> <td> 4 </td> <td> 5 </td> <td> 6 </td> </tr>
</table>

Why does JQuery show() function only work on one (rather than all) of elements with the selector?

JSFiddle.
In the following SSCCE, there is a <table> nested inside another <table>.
The question is about the click listener for #add button. Specifically, the last if/else block of the function. When you run this code, click the Add TextField button once (or more times), and you will see that the #remove button on which show() should be executed, is only shown for the first matched selector, and not both (or all) of them.
Ideally the Remove TextField should be shown for all the #remove selectors.
The question is why? How do I fix this?
$(document).on("click", "button#add", function() {
event.preventDefault();
var parentTable = $(this).parent().parent().parent().parent().parent().parent().parent().parent();
var lastTableRow = parentTable.children('tbody').children('tr:last');
//Adding the new row
parentTable.children('tbody').append(lastTableRow.clone());
//Reset lastRow variable
lastTableRow = parentTable.children('tbody').children('tr:last');
//Reset the fields
lastTableRow.find('table tbody tr td input').each(function() {
$(this).val('');
});
//update numberOfRows variable
var numberOfRows = parentTable.children('tbody').children('tr').length;
alert("numberOfRows:" + numberOfRows); //check
if (!(numberOfRows > 1)) {
$("#remove").hide();
} else {
$("#remove").show();
}
});
#outer-table {
padding: 20px;
border: 3px solid pink;
}
#inner-table {
border: 3px solid orange;
}
#remove {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="outer-table">
<tbody>
<tr>
<td>
<table id="inner-table">
<tbody>
<tr>
<td>
<p style="display:inline-block">Enter first complain:</p>
<input type="text" />
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td>
<button id="add">Add Textfield</button>
<button id="remove">Remove Textfield</button>
</td>
</tr>
</tfoot>
</table>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td>Table Footer</td>
</tr>
</tfoot>
</table>
That's because you're using id for a group of objects. id should be unique per document. You should use a class name instead.

Moving the div container scroll position reative to the nth row in an HTML table row

Fellow Gurus and Experts, I am seeking your help in attempting to move the div scroll position in the center position relative to the target Nth row (using the index) in an HTML table.
At the request of a user on this site, I have reformed my existing code to match the javascript function in question that requires further modification below.
How can I add on functionality to my existing jQuery javascript code using the function highlight() to not only highlight the specified target row, but to also move the div container scroll position in sync to the center position, relative to the target Nth row in an HTML table?
For ease of reference, I have created a fiddle as well: http://jsfiddle.net/3YbSe/1/
I am jQuery friendly :)
function highlight(tableIndex) {
// Just a simple check. If .highlight has reached the last, start again
if( (tableIndex+1) > rowCount) {
tableIndex = 0;
}
// Element exists?
if($('#data tbody tr:eq('+tableIndex+')').length > 0) {
// Remove other highlights
$('#data tbody tr').removeClass('highlight');
// Highlight your target
$('#data tbody tr:eq('+tableIndex+')').addClass('highlight');
$("#rownum").val(tableIndex+1)
}
else {
$("#rownum").val(0)
}
}
HTML Markup:
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<style type="text/css">
#data_container {
height: 100px;
border: 1px solid red;
width: auto;
overflow: scroll;
}
.highlight {
background-color: rgb(255,0,0);
}
</style>
<script type="text/javascript">
window.onload = function() {
var rowCount = $('#data tbody tr').length
$("#maxrows").val(rowCount)
function highlight(tableIndex) {
// Just a simple check. If .highlight has reached the last, start again
if( (tableIndex+1) > rowCount) {
tableIndex = 0;
}
// Element exists?
if($('#data tbody tr:eq('+tableIndex+')').length > 0) {
// Remove other highlights
$('#data tbody tr').removeClass('highlight');
// Highlight your target
$('#data tbody tr:eq('+tableIndex+')').addClass('highlight');
$("#rownum").val(tableIndex+1)
}
else {
$("#rownum").val(0)
}
}
$( "#data tbody tr" ).click(function() {
highlight($(this).index());
});
}
</script>
</head>
<body>
<div id="data_container">
<table id="data" border="1" cellspacing="1" cellpadding="1">
<thead>
<tr>
<th>#</th>
<th>Color</th>
<th>Fruit</th>
<th>Name</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>red</td>
<td>kiwi</td>
<td>Lindsay</td>
<td>closed</td>
</tr>
<tr>
<td>2</td>
<td>blue</td>
<td>mangos</td>
<td>Sarah</td>
<td>open</td>
</tr>
<tr>
<td>3</td>
<td>green</td>
<td>oranges</td>
<td>Joseph</td>
<td>hold</td>
</tr>
<tr>
<td>4</td>
<td>yellow</td>
<td>pears</td>
<td>Jenny</td>
<td>open</td>
</tr>
<tr>
<td>5</td>
<td>orange</td>
<td>bananas</td>
<td>Mike</td>
<td>closed</td>
</tr>
<tr>
<td>6</td>
<td>purple</td>
<td>lemon</td>
<td>Jerry</td>
<td>open</td>
</tr>
<tr>
<td>7</td>
<td>teal</td>
<td>apples</td>
<td>Larry</td>
<td>hold</td>
</tr>
</tbody>
</table>
</div>
Row Number:
<br>
<input type="text" id="rownum"><br>
of
<br>
<input type="text" id="maxrows" readonly>
</body>
</html>
Ok, I think I figured out what you are trying to accomplish. You can use the position() function for this, and then a little bit of simple math. You will also need to give your table a position so that you can check the position of the highlighted <tr> to the table it's in instead of the container. Here's some codez:
//Scroll to cntr position
var trPos = $("tr.highlight").position();
var trCtr = ($("tr.highlight").height()) / 2;
var dataTblctr = ($("#data_container").height()) / 2;
$("#data_container").scrollTop(trPos.top - dataTblctr + trCtr);
DEMO

finding the closest previous sibling that contains .myClass

I have a bunch of <tr> some of them contain a <td> that has class="myClass" but some don't. So it looks like something like this.
<tr>
<td class="myClass"></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
</tr>
If I'm at a <tr>, how do I go up in rows until I hit the closest row that contains a td.myClass? Is there a clever way to do this? What I have now is a while loop that checks prev() and if it finds .myClass, it breaks.
$currentTr.prevAll(':has(td.myClass)').first()
Here's a working example, not so great, but works. http://jsfiddle.net/H2k8m/2/
1) The td with class "color" will be the selected ones.
2) Either you can use that or you can directly assign the selected object to some variable and use it outside the function.
HTML :
<table>
<tr>
<td class="myClass">Hi</td>
<td>world</td>
</tr>
<tr>
<td class="myClass">1</td>
<td class="myClass" >2</td>
</tr>
<tr>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>5</td>
<td>6</td>
</tr>
</table>
CSS :
.color {
background: #000;
color: #fff;
}
table {
cursor: pointer;
}
tr, td {
min-width: 50px;
border: 1px #000 solid;
padding: 5px;
text-align: center;
}
Jquery :
$(document).ready(function()
{
$("table tr td").click(function() {
if( $(this).prevAll('[class="myClass"]').length <= 0 ) {
var parents = $(this).parent().siblings();
for( i = $(this).parent().index(); i >= 0; i-- ) {
parents.eq( i ).find(".myClass").last().addClass("color");
if( parents.eq( i ).find(".myClass").length > 0) {
break;
}
}
}
else {
$(this).prevAll('[class="myClass"]').first().addClass("color");
}
});
});
Here's another approach that will find the actual closest td with the myClass classname. If you want the tr, you can simply get the parent of what it finds:
var td$ = $("#myTable td.myClass");
$("#myTable td").click(function() {
td$.removeClass("found");
var temp$ = td$.add(this);
var i = temp$.index(this);
if (i > 0) {
temp$.eq(i - 1).addClass("found");
}
});
This gets a list of all td's with myClass. It then adds the clicked on element to that jQuery object (jQuery will sort it into DOM order after adding it). It then finds the index of the clicked on element in that jQuery object and if it's not the first item, it just gets the item before it which will be the closest td.myClass object before it in the table.
Working jsFiddle: http://jsfiddle.net/jfriend00/XqLzb/

JavaScript - How can I change the background color on all TDs in a TR at the same time on Mouseover/Mouseout?

When I mouseover one TD in a row I want all the TDs to change background color at the same time, then reverse on mouseout.
How do I do this?
In CSS you could do
tr td { background-color: white }
tr:hover td { background-color: black };
or just
tr { background-color: white }
tr:hover { background-color: black };
if the tds don't have their own background color.
Both should make the row black on mouseover, and white otherwise.
You could also do it in Javascript of course, but that isn't necessary (except for IE6, which doesn't understand the :hover pseudo-class on anything but <a> tags)
var tds = document.getElementsByTagName("td");
for(var i = 0; i < tds.length; i++) {
tds[i].onmouseover = function() {
this.parentNode.style.backgroundColor = "#ff0000";
}
tds[i].onmouseout = function() {
this.parentNode.style.backgroundColor = "#fff";
}
}
This actually changes the background colour of the parent tr, not each td, but it could be easily modified to do so. You could also attach the events to the tr elements instead of the td elements, and then you wouldn't have to use parentNode, but I don't know whether you need to do other stuff in the event handler specifically related to the td.
<table border="1" cellpadding="5" cellspacing="0">
<tr>
<th></th>
<th>Water</th>
<th>Air</th>
<th>Fire</th>
<th>Earth</th>
</tr>
<tr onmouseover="ChangeBackgroundColor(this)" onmouseout="RestoreBackgroundColor(this)">
<td>Spring thunderclouds</td>
<td>Yes</td>
<td>Yes</td>
<td>No</td>
<td>No</td>
</tr>
<tr onmouseover="ChangeBackgroundColor(this)" onmouseout="RestoreBackgroundColor(this)">
<td>Roasting chestnuts</td>
<td>No</td>
<td>No</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr onmouseover="ChangeBackgroundColor(this)" onmouseout="RestoreBackgroundColor(this)">
<td>Winter snowbanks</td>
<td>Yes</td>
<td>Yes</td>
<td>No</td>
<td>Yes</td>
</tr>
<tr onmouseover="ChangeBackgroundColor(this)" onmouseout="RestoreBackgroundColor(this)">
<td>Ice cream on a hot summer day</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
</tr>
</table>
<script type="text/javascript">
// Specify the normal table row background color
// and the background color for when the mouse
// hovers over the table row.
var TableBackgroundNormalColor = "#ffffff";
var TableBackgroundMouseoverColor = "#9999ff";
// These two functions need no customization.
function ChangeBackgroundColor(row) {
row.style.backgroundColor = TableBackgroundMouseoverColor;
}
function RestoreBackgroundColor(row) {
row.style.backgroundColor = TableBackgroundNormalColor;
}
</script>
I don't know what your exact use-case is, but for such tasks I would stick to CSS only:
td {
background: #f00; }
tr:hover td {
background: #fc0; }
http://jsfiddle.net/feeela/53JBV/
<td onmouseover="changeColorTo(this.parentNode, put color here)" onmouseout="changeColorTo(this.parentNode, put color here)">
...
<script>
function changeColorTo(parent, color)
{
var i, tdArray = parent.getElementsByTagName('td');
for(i in tdArray)
{
tdArray[i].style.backgroundColor = color;
}
}
</script>
This is faster than using jQuery, also, not everybody uses jQuery.
This jsFiddle I created shows you how to do it with jQuery.
I am using jQuery's hover event to handle what you are trying to do.
If you want a framework-agnostic solution, you can try this:
function highlightCells(tableRow) {
for (var index = 0; index < tableRow.childNodes.length; index++) {
var row = tableRow.childNodes[index];
if (row.style) {
row.style.backgroundColor = "red";
}
}
}
function unhighlightCells(tableRow) {
for (var index = 0; index < tableRow.childNodes.length; index++) {
var row = tableRow.childNodes[index];
if (row.style) {
row.style.backgroundColor = "white";
}
}
}
Example: http://jsfiddle.net/9nh9a/
Though practically speaking, wouldn't it be simpler to just bind your listener to the <tr> elements instead of the <td> elements? Is there some reason you want to listen only on the <td> elements?
<style type="text/css">
.table1 tr:hover td{
background-color:#ccc;
}
</style>
<table class="table1">
<tr>
<td>cell 1-1</td>
<td>cell 1-2</td>
<td>cell 1-3</td>
<td>cell 1-4</td>
</tr>
<tr>
<td>cell 2-1</td>
<td>cell 2-2</td>
<td>cell 2-3</td>
<td>cell 2-4</td>
</tr>
<tr>
<td>cell 2-1</td>
<td>cell 2-2</td>
<td>cell 2-3</td>
<td>cell 2-4</td>
</tr>
</table>
$(selector).mouseenter(handlerIn).mouseleave(handlerOut);
You can use code like this:
HTML
<table>
<tr>
<td>cell1,1</td>
<td>cell1,2</td>
<td>cell1,3</td>
</tr>
<tr>
<td>cell2,1</td>
<td>cell2,2</td>
<td>cell2,3</td>
</tr>
</table>
Style sheet
.hover {
background-color: silver;
}
JavaScript
$("td").hover(
function () {
$(this).parent("tr").addClass("hover");
},
function () {
$(this).parent("tr").removeClass("hover");
}
);
The .hover class obviously can be styled as you like.
Regards and happy coding!
In jQuery:
$('td').mouseover(function( obj ) {
$(obj).parent().children().css("background-color","green");
});
$('td').mouseout(function( obj ) {
$(obj).parent().children().css("background-color","red");
});
Or in Javascript:
var tds = document.getElementsByTagName( "td" );
for( var i = 0; i < tds.length; i++ ) {
tds[i].addEventListener("mouseover",function(){
var children = this.parentNode.getElementsByTagName("td");
for( var j = 0; j < children.length; j++ )
children[j].style.background-color = "green";
});
tds[i].addEventListener("mouseout",function(){
var children = this.parentNode.getElementsByTagName("td");
for( var j = 0; j < children.length; j++ )
children[j].style.background-color = "red";
});
}
When I did it in all java script I did it like this
<!DOCTYPE html>
<html>
<head>
<title>Chapter 11 Problem 1</title>
<script>
function blueText()
{
var paragraphObject = document.
getElementById("Paragraph");
paragraphObject.style.color = 'blue',
paragraphObject.style.background= 'white';
}
function whiteText()
{
var paragraphObject = document.
getElementById("Paragraph");
paragraphObject.style.color = 'white',
paragraphObject.style.background = 'blue';
}
</script>
</head>
<body>
<p id="Paragraph" style = "color:white; background-color:blue";
onmouseover="blueText()" onmouseout="whiteText()">
Paragraph Text
</p>
</body>
</html>
I really hope this doesn't garble it all up

Categories