I am adding listeners to the cells of the table so that i can get the cell index when a particular cell is clicked. However i am unable to get the value of row index in chrome. This works fine in IE10 and Firefox. The code is:
function AttachEvents() {
var cls = document.getElementById("TableContents").getElementsByTagName("td");
for ( var i = 0; i < cls.length; i++ ) {
if ( cls[i].addEventListener ) {
cls[i].addEventListener("click", alertRowCell, false);
} else if ( cls[i].attachEvent ) {
cls[i].attachEvent("onclick", alertRowCell);
}
}
}
function alertRowCell(e) {
var cell = e.target || window.event.srcElement;
//alert( cell.cellIndex + ' : ' + cell.parentNode.rowIndex );
if (cell.cellIndex == 1) {
alert(" The row index is " + cell.parentNode.rowIndex);
highlight();
}
}
How this can be resolved in Chrome?
You can easily refer to the clicked element with this.
In your case:
function alertRowCell(evt) {
var tr = this.parentNode;
// do something with tr...
}
The reason I'm saying it is because if your table structure is...
<tr>
<td><span>Hello</span></td>
</tr>
... then e.target is span whose parentNode is td and not tr.
Try this example: http://jsfiddle.net/naJBq/
Related
Sorry but I'm completly new to js and jquery.
I got dynamic table which values are in localstorage. I can add new row, delete row, and edit cells. This is working.
I want to add a sorting this table by clicked colum. I found here code and try it. It just working when I write table and not use my javascript to add rows from localstorage. Table in two cases looks same in html code. I have no idead why sorting isnt working with dynamic table.
This is w/o my dynamic table from localstore, sorting as supposed to:
http://jsfiddle.net/eW8Kg/1/
This is with table from localstorage(not working in jsfiddle?) on my comupter this is working good, but table is not sorting! (I left this static values):
http://jsfiddle.net/XAu5G/
I think my problem can be in creation of table content:
var Html = "<tbody>";
for (var i = 1; i < localStorage.length; i++) {
var input = "<td><input style='border:hidden' class=\"fields\" name = " + localStorage.key(i) + " type='text' onchange='change(\"" + localStorage.key(i) + "\")' /></td>"
Html += "<tr class=\"field\">";
for (var j = 0; j < 4; ++j) {
Html += input;
}
var button = "<td><input type='button' value = 'UsuĊ' onclick='Remove(\"" + localStorage.key(i) + "\")'></td>";
Html += button + "</tr>";
}
Html += "<tr id=\"actions\"></tr></tbody>"
document.getElementById("list").innerHTML += Html;
This jquery code do sorting:
$(document).ready(function() {
var table = $('#list');
jQuery.fn.sortElements = (function() {
var sort = [].sort;
return function(comparator, getSortable) {
getSortable = getSortable || function() {return this;};
var placements = this.map(function() {
var sortElement = getSortable.call(this),
parentNode = sortElement.parentNode,
// Since the element itself will change position, we have
// to have some way of storing it's original position in
// the DOM. The easiest way is to have a 'flag' node:
nextSibling = parentNode.insertBefore(
document.createTextNode(''),
sortElement.nextSibling
);
return function() {
if (parentNode === this) {
throw new Error(
"You can't sort elements if any one is a descendant of another."
);
}
// Insert before flag:
parentNode.insertBefore(this, nextSibling);
// Remove flag:
parentNode.removeChild(nextSibling);
};
});
return sort.call(this, comparator).each(function(i) {
placements[i].call(getSortable.call(this));
});
};
})();
$('#x').click(function(){
$('#list').hide();
});
$('#nazwa-header').wrapInner('<span title="sort this column"/>').each(function() {
var th = $(this),
thIndex = th.index(),
inverse = false;
th.on('click', function() {
table.find('td').filter(function() {
return $(this).index() === thIndex;
}).sortElements(function(a, b) {
console.log($(a).find('input').val(),$(b).find('input').val());
return $(a).find('input').val() > $(b).find('input').val() ?
inverse ? -1 : 1
: inverse ? 1 : -1;
}, function() {
// parentNode is the element we want to move
return this.parentNode;
});
inverse = !inverse;
});
});
});
The topic of changing the Dojo DataGrid row background has been previously discussed on this board as well as the Dojo documentation, which gives a full example (http://dojotoolkit.org/reference-guide/1.9/dojox/grid/DataGrid.html).
My issue is a little bit different. I need to change the background color of the rows based on a common field - let's call it 'CityId'. If two rows have the same CityId, then they should have the same background. Note that this question is not concerned with the grouping nor ordering of the data in the grid, but only with the changing of the row style for adjacent rows sharing a common ID field.
The two main paths for this issue involve either hooking into the 'onStyleRow' event or the private '_onFetchComplete' event.
Here's my onStyleRow attempt:
var idx = 0;
var prevId = 0;
function myStyleRow(row) {
var item = grid.getItem(row.index);
if(item) {
var currId = store.getValue(item, "CityId", null);
if ( !!currId ) {
if ( prevId != currId ) {
prevId = currId;
idx++;
}
if ( idx%2 == 0 ) {
row.customStyles += 'background-color:#FFF000;';
} else {
//row.customStyles += 'background-color:#000;';
}
}
}
grid.focus.styleRow(row);
grid.edit.styleRow(row);
}
which gets called during the grid creation among other parameters
grid = new dojox.grid.DataGrid({onStyleRow:myStyleRow});
The reason why this approach is unstable is because the onStyleRow event gets triggered on mouse hover, causing the rows to be re-painted due to the prevId value. I would like to know whether/how I could disable onStyleRow from triggering on mouse hovers. This would solve my issue.
In the _onFetchComplete approach, I am stuck trying to find a way to access grid rows. Here's my code:
var idx = 0;
var prevId = 0;
grid.connect(grid, '_onFetchComplete', function() {
// wait until everything is loaded
for (var i in grid._pending_requests) {
if (grid._pending_requests[i]) {
return;
}
}
// parse through row data
for ( var j=0; j < grid.rowCount; j++) {
var item = grid.getItem(j);
if(item) {
var currId = store.getValue(item, "CityId", null);
if ( !!currId ) {
if ( prevId != currId ) {
prevId = currId;
idx++;
}
if ( idx%2 == 0 ) {
row.customStyles += 'background-color:#FFF000;';
} else {
//row.customStyles += 'background-color:#000;';
}
}
}
}
});
This is obviously a work in progress as there are two missing points: a way to iterate through the grid's rows (grid.rowCount does not work properly) and a way to fetch the grid's rows in order to apply the custom styles. I could not find something like grid.getRow() to address the issue.
Any pointers are appreciated.
Here's the final code:
var idx = 0;
var prevId = 0;
var passing = {};
var color = {};
dojo.connect(grid, 'onStyleRow', this, function (row) {
var item = grid.getItem(row.index);
if(item) {
var currId = store.getValue(item, "CityId", null);
if ( !passing[currId] ) {
passing[currId] = true;
if ( prevId != currId ) {
prevId = currId;
idx++;
}
if ( idx%2 == 0 ) {
row.customStyles += 'background-color:#FFF000;';
color[currId] = 'background-color:#FFF000;';
} else {
row.customStyles += 'background-color:#F2F7F7;';
color[currId] = 'background-color:#F2F7F7;';
}
} else {
row.customStyles += color[currId];
}
}
});
The 'passing' object is used to mark the first pass through the rows - this point is important because the 'prevId' value is updated correctly. The code works well with multiple calls to get more data into the grid because 'prevId' maintains its integrity. The 'color' object holds the values recorded for row backgrounds. This is needed because the onStyleRow event is called on mouseover, which implies the need to re-paint every time. I hope this helps someone else as well.
I'm using the following javascript to get the data in a clicked table cell:
var table = document.getElementById('ThisWeek'),
cells = table.getElementsByTagName('td');
for (var i=0,len=cells.length; i<len; i++)
{
cells[i].onclick = function()
{
document.getElementById("txtVal").value = this.innerText;
}
}
How can I modify this so I can also obtain the contents of the first cell in the clicked column and the first cell in the clicked row? E.g. if I click on "s" in the table below, I get the results "2" and "B" returned as two variables:
0 1 2 3
A q w e
B a s d
C z x c
Please note that I need a javascript solution, not jQuery. Ideally, I would also like clicks on the first row and first column to return empty strings.
This snippet uses the properties I've mentioned in my comment:
window.onload = function () {
var table = document.getElementById('table');
table.addEventListener('click', function (e) {
var target = e.target,
col = target.cellIndex,
row;
while (target = target.parentElement) {
if (!col && col !== 0) {
col = target.cellIndex;
}
if (target.tagName.toLowerCase() === 'tr') {
row = target.rowIndex;
break;
}
}
console.log(table.rows[row].cells[0].innerHTML + ', ' + table.rows[0].cells[col].innerHTML);
});
}
A live demo at jsFiddle.
I'd suggest:
function index(c){
var i = 0;
while (c.previousSibling){
/* if the previousSibling has a nodeType and that nodeType === 1
(indicating the previousSibling is an element) increment the i variable */
if (c.previousSibling.nodeType && c.previousSibling.nodeType === 1){
i++;
}
// reset c to the previousSibling
c = c.previousSibling;
}
/* i is the count of previous-siblings, and therefore the index
amongst those siblings: */
return i;
}
function getHeaders(e){
/* this is the table element,
e.target is the clicked element */
var el = e.target,
text = 'textContent' in document ? 'textContent' : 'innerText',
headers = [el.parentNode.getElementsByTagName('td')[0][text],this.getElementsByTagName('tr')[0].getElementsByTagName('td')[index(el)][text]];
// set the text of the nextElementSibling of the table:
this.nextElementSibling[text] = headers.join(', ');
}
document.getElementById('table').addEventListener('click', getHeaders);
JS Fiddle demo.
You can add this to your cells[i].onclick function:
var row = this.parentElement; // TR
var table = row.parentElement.parentElement; // TBODY > TABLE
document.getElementById("columnVal").value = row.rowIndex && this.cellIndex ? table.rows[0].cells[this.cellIndex].innerText : "";
document.getElementById("rowVal").value = row.rowIndex && this.cellIndex ? row.cells[0].innerText : "";
I have an onclick function attached to each <td> element. The function needs to know the placement in the table (row and column).
I found an attribute called rowIndex for <tr>s, but that would involve getting the parent element and still doesn't help with column number.
Here is my function so far (it's within a loop, so it's attaching to every td)
td.onclick = function(event) {
event = (event) ? event : window.event;
console.log('rowIndex, colIndex');
}
I could figure this out with jQuery, but I'm trying to do without.
My first thoughts were:
var rows = document.getElementsByTagName('tr');
var cells = document.getElementsByTagName('td');
var cellsPerRow = cells.length/rows.length;
var i = 0;
for (r=0;r<rows.length;r++){
for (c=0;c<cellsPerRow;c++){
cells[i].setAttribute('data-col',c + 1);
cells[i].setAttribute('data-row',r + 1);
cells[i].onclick = function(){
var row = this.getAttribute('data-row');
var col = this.getAttribute('data-col');
alert('Row: ' + row + '; col: ' + col);
};
i++;
}
}
JS Fiddle demo.
This was then refined to:
var cells = document.getElementsByTagName('td');
for (i=0;i<cells.length;i++){
cells[i].onclick = function(){
var row = this.parentNode.rowIndex + 1;
var col = this.cellIndex + 1;
alert('Row: ' + row + '; col: ' + col);
};
}
JS Fiddle demo.
element.cellIndex
will give you the column zero-indexed position.
Example
Is it possible in your situation to echo out the row and column into the td element's id in the server-side script? Such as ...id="' . $row . '_' . $col . '"...
Then it's just a case of parsing the values out from this.id.
Here you go: - http://jsfiddle.net/FloydPink/Lu8Yw/
var tds = document.getElementsByTagName('td');
for (var i = 0; i < tds.length; i++) {
var td = tds[i];
td.onclick = function(event) {
event = (event) ? event : window.event;
console.log('rowIndex: ' + this.parentNode.rowIndex + ', colIndex: ' + this.cellIndex);
}
}
First, creating click events for each td is not efficient. Recommend using event delegation. You can google it for the benefits of using Event delegation.
http://www.nczonline.net/blog/2009/06/30/event-delegation-in-javascript/
Basically, the more cells you have in the table, the more memory will be consumed. Instead of creating multiple cells, create one single event to delegate.
var table = document.getElementById('test-table');
table.onclick = function(e) {
var target = e.target,
parent;
if (target.tagName === 'TD') {
parent = target.parentNode;
console.log('rowIndex', parent.getAttribute('rowindex'), 'colIndex', target.getAttribute('colindex'));
}
}
Here is the example in jsfiddle http://jsfiddle.net/EWGzB/1/
In this specific case, the element is a table row.
Untested but something like:
var tbl = document.getElementById('tableID');
var row = document.getElementById('rowID');
tbl.removeChild(row);
or
var row = document.getElementById('rowID');
row.parentNode.removeChild(row);
var row = document.getElementById("row-id");
row.parentNode.removeChild(row);
var zTag = document.getElementById ('TableRowID');
zTag.parentNode.removeChild (zTag);
Or in jQuery:
$('#TableRowID').remove ();
Jquery
$('#myTableRow').remove();
This works fine if your row has an id, such as:
<tr id="myTableRow"><td>blah</td></tr>
Pure Javascript :
Javascript Remove Row From Table
function removeRow(id) {
var tr = document.getElementById(id);
if (tr) {
if (tr.nodeName == 'TR') {
var tbl = tr; // Look up the hierarchy for TABLE
while (tbl != document && tbl.nodeName != 'TABLE') {
tbl = tbl.parentNode;
}
if (tbl && tbl.nodeName == 'TABLE') {
while (tr.hasChildNodes()) {
tr.removeChild( tr.lastChild );
}
tr.parentNode.removeChild( tr );
}
} else {
alert( 'Specified document element is not a TR. id=' + id );
}
} else {
alert( 'Specified document element is not found. id=' + id );
}
}