Knowing which column is being updated - javascript

I am trying to get handsontable to give me which column is being updated, but have not been able to find a proper solution. I understand they are using a textarea to get the input and then putting the values into a table, but I just cannot figure out how to find out which column is being update.
Any help would be appreciated.
Thanks

This method will tell you what row/column is selected:
$('#example1grid').handsontable('getSelected')
This will be return the same coordinates as the currently edited cell, except for cases when there are multiple cells selected (but even then the currenyly edited cell is always within selected cells).
I am thinking about creating a new method getCurrent or callback onBeginEditing to return currently edited cell. Which would be better for you? I think the callback would be better.

onChange: function (data) {
for (i in data) {
if(data[i][2] != data[i][3]) {
var column = $('#dataTableLoc td:nth-child(' + (data[i][1] + 1) + ')')[0].innerText;
}
}
}
This is obviously far from elegant. It will conflict with any extensions like the "removeRow" example in buttons.html but obviously can be adjusted accordingly. Its necessary when pulling data from an SQL table and trying to update using a query.

Related

Adding new instance of row, unable to update cell raw values

I've stumped myself on what I thought was a pretty simple JavaScript function. The function takes 2 parameters. The first is a listbox (oField), and the second is a table (nTable).
The listbox is populated by the user, and each time this listbox's values are changed, I want the function below to be called, to recreate nTable, the original header, and rows for each value in the list box.
function table_build(oField, nTable){
//clear table when selection changes
nTable._HeaderRow.setInstances(1);
//add new selection to table
for(i=0;i<oField.length;i++){
nTable._HeaderRow.addInstance(true);
nTable.HeaderRow[i+1].Cell1.rawValue = oField.getDisplayItem(i);
}
}
The issue that I am having is with the following line:
nTable.HeaderRow[i+1].Cell1.rawValue = oField.getDisplayItem(i);
I am able to update the value of the header row using:
nTable.HeaderRow.Cell1.rawValue = oField.getDisplayItem(i);
Which is weird, because I would have expected it to require HeaderRow[0] after the new instance is added.
What is wrong here?
I have worked out a solution. The addInstance() function returns the new row instance. So I have updated my table_build() function to assign that value to a variable(nRow), then use nRow to reference the row.
var nRow = nTable._HeaderRow.addInstance(true);
nRow.Cell1.rawValue = oField.getDisplayItem(i);
Hope this helps anyone else with a similar query :)

infragistics igGrid: how to remove a row with javascript

i think my question is pretty simple but i still didn't find any answer that fits me, neither here nor out there..
so i'd be really happy if someone could help me out, it doesn't matter if it's by providing useful links or whatever...
what i'm trying to achieve:
i've got an Ignite UI Grid (igGrid), where i'd like to remove a row using javascript. it doesn't even matter which one. simple, right?
what i've tried so far:
$(row).remove(); -> in this case every single row is being removed
$(row).remove(1); -> JavaScript runtime error: Object doesn't support property or method 'replace'
get_rows(): not supported by javascript, it would work in c# though..
removeat-method: not supported by javascript, it would work in c# though..
igGridSelection: selected stuff that i want to keep will be removed, too
and now the code snippet:
$sender = $(this).attr('id');
$varTablName = gridMap.getVarTable($sender);
var rowCount = $("#" + $varTablName).igGrid("widget").igGrid('rows').length;
$("#" + $varTablName).igGrid("widget").igGrid('rows').each(function (index) {
var row = $("#" + $varTablName).igGrid("widget").igGrid("rowAt", index);
if (rowCount > 1) {
$(row).remove(); //the not quite working part
}
it's doable, right? there's no need to go all the way and write it in c# and call it with js, right..? RIGHT??^^
Infragistics guide to deleting a row programmatically
$('#grid').igGridUpdating('deleteRow', "AFG");
$('#grid').igGridUpdating('deleteRow', 1, $('#grid').igGrid("rowAt", 0));
Following to the api docs -- thnx #KonstantinDinev -- the code above will delete a row from the grid, creating a transaction and updates the UI. This functionality depends on autoCommit option of igGrid
the API should always be first option ^^
We can also target the dom element and remove or hide it ourselves. When removed the number of rows displayed changes but the data source will need to be updated
http://jsfiddle.net/gtw916um/6/
$(function() {
$("#grid").igGrid({});
//hides 2nd row (index starts at 0)
$("#grid").igGrid("allRows").each(function(index) {
if (index == 1) {
$(this).css("display", 'none');
}
});
//deletes 4th row (index starts at 0)
var row = $("#grid").igGrid("widget").igGrid("rowAt", 3);
$(row).remove();
//un-hiding 2nd row (index starts at 0)
row = $("#grid").igGrid("widget").igGrid("rowAt", 1);
$(row).css("display", 'table-row');
});
untested update data method
$("#grid").data("igGrid").dataSource.deleteRow(3, true);
$("#grid").data("igGrid").commit();
deleteRow is the method you're looking for as the other answer suggests. For this method you can provide the row element as parameter, or the row ID. Here's the API docs.
Here's the code:
var row = $("#" + $varTablName).igGrid("rowAt", index);
$("#" + $varTablName).igGridUpdating("deleteRow", row);
You could try this or some jquery equivalent. I don't know how it will affect the ultragrid though, so doublecheck if you retain all other functionality.
var row = document.querySelector('myRowReference');
row.parentNode.removeChild(row);

Sorting issue with plain text and html in the same column using Handsontable

I'm having a problem sorting a column which contains plain text as well as html like an anchor tag. The sorting seems to be occurring on the value stored in the data source array rather than the displayed value. The cells containing an anchor tag are always sorted above the plain text cells.
Below is a JSFiddle with an example. What I would like is for the third column to sort alphabetically the names regardless of whether the cell contains an anchor tag or plain text.
Example:
http://jsfiddle.net/5sL2jkqt/
{ data: 2, renderer: "html" }
I tried applying a custom cell renderer on the third column but that did not help. Any suggestions on how to get around this would be much appreciated!
What I did to get around this was to add the following function to the handsontable.full.js
// Strip out all tags not in the allowed parameter
function stripTags(input, allowed) {
if (!input) {
return "";
} else if (!isNaN(input)) {
return input;
}
// making sure the allowed arg is a string containing only tags in lowercase (<a><c>)
allowed = (((allowed || "") + "").toLowerCase().match(/<[a-z][a-z0-9]*>/g) || []).join("");
var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi,
commentsAndPhpTags = /<!--[\s\S]*?-->|<\?(?:php)?[\s\S]*?\?>/gi;
return input.replace(commentsAndPhpTags, "").replace(tags, function ($0, $1) {
return allowed.indexOf("<" + $1.toLowerCase() + ">") > -1 ? $0 : "";
});
};
I then called the stripTags function in the native handsontable function this.sort which adds the content you are sorting into the array this.sortIndex like the following:
this.sortIndex.push([i, stripTags(instance.getDataAtCell(i, this.sortColumn + colOffset), "")]);
Not 100% ideal but worked like a charm. It strips out HTML and sorts on what is left over.
Can also be found on GitHub
Unfortunately the sorting plugin will always sort on the value rather than what's being displayed. You can, however, implement your own sorting. In this case, it's your best bet.
What you'd do is disable sorting in HOT, then on click of the title, just like with HOT sorting, trigger your sorting function.
This one should act on the data object itself. Make sure to check which header was clicked so that you can translate it into an index. The rest should be straight forward:
Using something like data.sort(function(item1, item2) { //logic }), you can now sort your data array based on whatever characteristic you want. It seems like the easiest way would be to sort based on column index 1 values so you could do:
// item1 is a row and item2 is the row right after it
data.sort(function(item1, item2) {
return item1[1] > item2[1] ? 1 : -1; // returning 1 makes item1 greater
}
hotInstance.render(); // remember to re-render when done
This would be the easiest way. It also gives you more flexibility down the line. Good luck.

ExtJS - Get array on DOM nodes in Grid, highlight()?

Here's what I'm trying to accomplish. I have a grid with entries that a user can "batch update", that is a user can select a single or multiple entries from the grid, select values from a form above the grid that they want to apply to all entries, and then submit.
What I'd like to accomplish is a highlight() done on all the changes rows. The problem I'm having is I don't know how to run a highlight() on all of the changes values at once, so I've been doing it individually. I might just be running through the loop wrong. Here's what I'm doing to update the values.
// for every property we have in our batchUpdateValues
for (var propertyName in batchUpdateValues) {
// change the selected banners attributes to match
for (var i = 0 ; i < bannersToUpdate.length ; i++)
{
// if they've selected "Name", we only want to append, not replace"
var oldName = bannersToUpdate[i].get('bannerName');
if (propertyName == 'bannerName') {
bannersToUpdate[i].set(propertyName, oldName + ' ' + batchUpdateValues['bannerName']);
} else {
bannersToUpdate[i].set(propertyName, batchUpdateValues[propertyName]);
}
var changedRowId = this.getStore().indexOf(updatedBanners[i]);
var changedRow = this.getView().getRow(changedRowId);
Ext.get(changedRow).highlight();
}
}
What's happening now is if the user selects 4 "attributes" to update form the form the highlight gets run 4 times, so I'd need to put that code outside the loop. How would I grab all of the DOM attributes for each row and then run a highlight on them()?
My first suggestion is to make sure you understand the SelectionModel. It's described in the documentation. I'd link you but I'm not sure which version you're using. Actually, what version of Ext JS are you using? The answer to this question might be different in 3.x vs. 4.x.
I'd be happy to answer in more detail but I'll need you to clarify with an example. Could you build a small table with some dummy data and then explain when you're talking about rows/columns in the model?

DOM memory issue with IE8 (inserting lots of JSON data)

I am developing a small web-utility that displays some data from some database tables.
I have the utility running fine on FF, Safari, Chrome..., but the memory management on IE8 is horrendous. The largest JSON request will return information to create around 5,000 or so rows in a table within the browser (3 columns in the table).
I'm using jQuery to get the data (via getJSON). To remove the old/existing table, I'm just doing a $('#my_table_tbody').empty(). To add the new info to the table, within the getJSON callback, I am just appending each table row that I am creating to a variable, and then once I have them all, I am using $('#my_table_tbody').append(myVar) to add it to the existing tbody. I don't add the table rows as they are created because that seems to be a lot slower than just adding them all at once.
Does anyone have any recommendation on what someone should do who is trying to add thousands of rows of data to the DOM? I would like to stay away from pagination, but I'm wondering if I don't have a choice.
Update 1
So here is the code I was trying after the innerHTML suggestion:
/* Assuming a div called 'main_area' holds the table */
document.getElementById('main_area').innerHTML = '';
$.getJSON("my_server", {my: JSON, args: are, in: here}, function(j) {
var mylength = j.length;
var k =0;
var tmpText = '';
tmpText += /* Add the table, thead stuff, and tbody tags here */;
for (k = mylength - 1; k >= 0; k--)
{
/* stack overflow wont let me type greater than & less than signs here, so just assume that they are there. */
tmpText += 'tr class="' + j[k].row_class . '" td class="col1_class" ' + j[k].col1 + ' /td td class="col2_class" ' + j[k].col2 + ' /td td class="col3_class" ' + j[k].col3 + ' /td /tr';
}
document.getElementById('main_area').innerHTML = tmpText;
}
That is the gist of it. I've also tried using just a $.get request, and having the server send the formatted HTML, and just setting that in the innerHTML (i.e. document.getElementById('main_area').innerHTML = j;).
Thanks for all of the replies. I'm floored with the fact that you all are willing to help.
var tmpText = [];
for (k = mylength - 1; k >= 0; k--)
{
/* stack overflow wont let me type greater than & less than signs here, so just assume that they are there. */
tmpText.push('anything you want')
tmpText.push( 'tr class="' + j[k].row_class . '" td class="col1_class" ' + j[k].col1 + ' /td td class="col2_class" ' + j[k].col2 + ' /td td class="col3_class" ' + j[k].col3 + ' /td /tr';)
}
$('#main_area').html(tmpText.join(''))
}
you dont need document.getElementById('main_area').innerHTML = '';
this method is to push into array, then join and use jquery html function to update. This is the fastest method I know. Sorry for the format here - its my first post and I thought I'd give something back here to stackoverflow.
To get IE to respond quickly you should be creating your table rows as string representations of HTML , appending them to a string variable, and then adding the result to your table's like this.
myTable.myTbody.innerHTML = allThoseRowsAsAString;
It's not a memory issue: 5,000 rows should be trivial. That's got to be far less than one megabyte.
Robusto is right about innerHTML assignment being a better way to go. IE sucks at dynamic DOM creation
Why not form your innerHTML on the server using a jsp and stream it back via ajax in one shot. It will definitely speed things up, remove complexity from your javascript and delegate markup creation to its proper place.
As Plodder said, IE has big problems when working with DOM. jQuery best practices recommends creating code on a simple string and appending just once inside the container.
Beside this, I recently had a similar problem for a hierarchycal data, having an amount of 5,000 data records. I asked myself: did the user really need all that information available at a given moment? Then I realized the best I could do was just present a "first chunk of data" and then insert more data on user demand.
Finally, just one good tool: Dynatrace Ajax (it helps a lot to find the javascript function it takes more time to operate)
Since you are dealing with thousands of data rows I wouldn't call $('#my_table_tbody').empty() and add the new data with new DOM elements. Instead I'd follow the Object Pool Pattern. Thus instead of dropping all the tr's you can reuse existing ones and just populate with the new data.
If your new data set has less rows then the previous one, remove the rest of the rows from the DOM, but keep references to them in some pool so that garbage collector won't destroy them. If your new data set is bigger - just create new tr's on demand.
You can look at the implementation of YUI DataTable, here's the source. IIRC they use this approach to speed up the render time.

Categories

Resources