determine which table cell triggered hammer.js event - javascript

I have an html table in which all the cells within a column have the same css class 'className'.
I want to apply hammer.js on 'hold' event to these cells. I call hammer.js like so:
Hammer('td.className').on('hold', doModal);
I need to find out exactly what cell was 'hold'. In my modal window I have a select element that will set the new value of the cell.
I can not set an ID for each cell on that column, because the table is dynamically generated. My doModal callback gets called several times, because I select all cells with class 'className'. I can get the doModal to be called only once, but I can not determine which cell (row + column) triggered the 'hold' event.
How can I achieve that ?

You can find out the held table cell using the target property in the event object.
for example,
var tab = document.getElementById("tab"); // reference to your table
Hammer(tab).on('hold',function(ev){
console.log(ev)
ev.target.style.background='red'; //will give red background for the held cell
});
i tried to put together a fiddle but can't find a working link to hammer.
update: fiddle

Related

AngularJS - Listen for onclick events for all table <td>

Is there a way to use angular.element(...).on('click', onTdClick); (for example) in a way that executes onTdClick (providing the element to it) on every that gets clicked?
Let's say I have 2 tables, both have cells and columns.
I want to be able to click on CELLS and send the element of what I clicked and send it to onTdClick($event).
$scope.onTdClick = function(ev){
window.getSelection().selectAllChildren(ev.target);
};
Essentially doing the same as: ng-click="onTdClick($event)" without having to put ng-click on hundreds of <td>'s
I dynamically add table rows and table cells with .insertRow and .insertCell
https://www.w3schools.com/jsref/met_table_insertrow.asp
So statically doing angular.element().find('td').on() wont work well here.
Whats my end result?
I'm attempting to make it so I can click <td>'s to essentially highlight cells by just clicking them.
The highlight code is already tested and works:
window.getSelection().selectAllChildren(ev.target);
(where ev is the td element)
You shouldn't use insertRow with AngularJS. Instead, you should use ng-repeat with an array that has an object for every row, and just push objects when you want to insert a row.
$scope.insertRow = function(){
$scope.tdList.push({});//push whatever you want
}
If you want the number of cells to be variable, you can store some param in this object to tell the view how many cells the row has, and put a nested ng-repeat inside to create the cells

JQuery Datatables Responsive extension: column class not retained for cells in expanded rows

I am using columnClass property to assign different rendering (and event processing) to cells belonging to different columns.
When the table fits within the screen every element gets the class as specified by the columnClass property of its column and I can easily hook some rendering/processing functions to the elements.
However, when some of the columns don't fit within the page and I expand the row (by clicking the '+' button) the cells are renedered with no reference to the class of the column. I reviewed the custom renderer for the cells of the expanded columns and also see no way finding out what the column class of a cell is.
Ideally, I would like to use the same custom field renderer as defined in the table. Is there a way I can do it?
Example:
Let's say I have 3 columns: name, dob, salary.
I defined 3 classes for the columns: name_class, dob_class, salary_class.
For each class I use a jquery selector and assign diffrerent rendering/behavior for each cell of that column.
Now, I resize the table so that dob and salary get overflown and click on the '+' button to expand the row of interest.
I would expect to get the dob cell with the dob_class attribute and salary cell with the salary_class attribute, so I am able to link the same cell renderer to them.
However, ****the class attribute is no assigned (not retained) and I cannot link with jquery using the class attribute. ****
**Could you please suggest an solution that would allow me to retain the column class on the cells of the expanded row? **
Sorry, no, that's not currently possible. It has been raised against the code already, see https://github.com/DataTables/Responsive/issues/93, so it is on the todo list. I'm not sure why the OP has been voted down, seems a bit unfair to me, as it is a valid question.

Info panel below TRs

I have a table, and I'd like to add a hideable/showable panel below each row for more controls and info than can reasonably fit in the table row. My first thought was to have a sibling tr for each original tr, and put a single td inside with an appropriate colspan:
<tbody>
<tr>
<td>...</td>
...
<tr>
<tr class="tablesorter-childRow">
<td colspan="4">...</td>
</tr>
...
</tbody>
Each original row would have a button that would hide() or show() the corresponding tr, and the td in the child row would have all the extra controls that don't need to be seen normally.
This gets tricky because I'm using d3 to build the table, and d3 doesn't like multiple elements per datum (see this stack post and this other thing).
It's also tricky because I'm using tablesorter, which sorts the table client-side using the values in tds, so the original data has to stay in table format. (It could keep pairs of rows together using a css class "tablesorter-childRow".) I also don't believe I can have multiple tbodies because they aren't sorted along with rows -- each tbody's rows are sorted.
I thought about using jquery afterwards to insert a tr after each original tr, but then d3 won't update the table properly when something changes (since the data won't join properly), and the reason I'm using d3 is because it makes building lots of dom elements easier (for me at least).
So, question time: how else can I create this panel that
moves with the original table rows
doesn't affect sorting
can be hidden or shown?
If you want two sibling elements to share the same data, the easiest way in d3 is to group them under a parent element. You assign the parent element the data, and then when you create its two child elements (without assigning data) they both inherit the parent's data.
In SVG, the usual parent element is a <g>. For your purpose, the natural parent element would be <tbody> which can be used to group table rows. However, you'd have to modify the table sorting code that you're using, to sort individual <tbody> elements instead of individual rows.
The only other option would be to dynamically set the content of the info row and insert it in the correct place every time you want to show it, similar to how many tooltip examples work: it's the same tooltip, just moved around and with new data. If you're using d3 to attach the event handler on the table rows, it will pass the data object of the clicked-on row to the event handling function, so you can use that data to fill the information content without creating a data-join. To insert the info row after the clicked <tr> element, you could use d3's insert() function, but the format isn't ideal; better to use plain Javascript or JQuery. You'd also have to remove the info row before running your sort.
tableRows.on("click", showInfo);
/* remember to give your rows a tabIndex, so that keyboard users can
trigger the click action */
/* Create the persistent info box */
var infoRow = d3.select( document.createElement("tr") )
//create a new <tr>, unattached to the document
.attr("class", "infoBox";//set class to allow unique formatting
infoRow.append("td") //add a <td> within the <tr>
.attr("colspan", colNames.length); //set to fill all columns
/* Show the info row for a clicked element */
function showInfo(d,i) {
/* Hide info box if currently shown */
infoRow.style("display", "none");
/* Set content to match clicked row */
infoRow.select("td") //select the <td> element
.html(/* create html from the d object
you don't need a function(d), just
concatenate the string. */)
/* Insert the row in the correct place.
This will automatically remove it from any current location */
this.parentNode.insertBefore(infoRow, this.nextSibling);
//"this" is the tableRow object that received the click event
infoRow.style("display", null);
//revert to default display setting (i.e. table-row)
}
function sort(/*parameters*/) {
infoRow.remove();
//remove the infoRow element from the document,
//so it only exists as a Javascript object again
/* Run your sort code */
}

event is fired multiple times for dynamically created DOM objects

The program has two javascript functions to generate a table (generateTable) and delete one selected row (deleteOneRow).
generateTable function generates a table based on server data. Each row is in the following format:
<tr><td><span class="desc">aaa</span>Delete</td> </tr>
Basically, each row is some text followed by a 'delete' link.
When the script finish the table generation, it calls $(".delete-choice").click(deleteOneRow) to bind click to the event handler.
In the event handler function deleteOneRow, it first simply deletes all the rows in the table. Then call generateTable again to display the remaining data entries. Code structure is like follows:
function deleteOneRow() {
var choiceIdx = ... //get index
$(".delete-choice").unbind('click');
CurrentChoices.splice(choiceIdx, 1); // remove the entry from the array
$("#problem-choice-table tr").each(function(){ // delete the DOM entries
$(this).remove();
})
generateTable();
}
If the table have two rows, after clicking the delete link in the 1st row, the first row was deleted. Then it generates a table with the 2nd row moving to the 1st. However, the deleteOneRow is called again, then the 2nd row is removed eventually.
I guess this is due to event is fired multiple times. I tried unbind, stopPropagation, etc. Nothing works.
Using jquery's live to attach an event is perfect for situations like this where content is added / removed dynamically and you want to match against the same selector, have you looked into using that?

How do I get column name from rowselection in an ExtJS grid?

I have a extjs gridpanel setup, and I want to be able to do things based on a user clicking on text or icons in the grid. For example, filter the grid if the user clicks (or double clicks) a word in a column, or show a popup if the user clicks on an icon. I can easily get the row they clicked on, and values by column name from that row, but I don't know which column was clicked.
Alternatively, I could add an onClick to the entire grid, which I could then get the individual text from the row/column, but I don't know what row index or column that value belongs to. I could add a CSS class that would tell me a column name, but that seems like a hack.
Is there anything built-in that can do this?
The "cellclick" event on the grid is the way to go. A function listening on this event gets passed:
( Grid this, Number rowIndex, Number columnIndex, Ext.EventObject e )
If you want to get the text of the gridCell, calling yourGrid.getView().getCell(rowIndex, colIndex) will return the DOM element.
If you want to get the column header, call: yourGrid.getColumnModel().getColumnHeader(colIndex)
If you want to find anything else out about a particular column, call yourGrid.getColumnModel().getColumnAt(colIndex)
I think if you are interested in column wise events rowselection is the wrong event to look into. As Joshua suggested the cellclick event will the event you have to look into.
This event can give the dataIndex of the column as given
var fieldName = grid.getColumnModel().getDataIndex(columnIndex);
Please look at edit-grid.html example for checkbox rendering and event handling.

Categories

Resources