I'm populating a TabContainer with grids (Dojo 1.8, dgrid) that are showing the results of a query for different datasets. Each tab is the result of a single dataset. The different datasets will have a varying number of fields, so I'm dynamically building each grid and adding it to a ContentPane, which gets added to the TabContainer.
My current problem is seting the width of the grids when they are built. The datasets could have from two fields to upwards of 100 fields to be shown in the grid. I've set a default width in CSS for the grid of 600px, but the grid will only show the first six fields of the dataset. If I set the width to "auto", it is only as wide as the TabContainer, removing the scroll bar and cutting off the data. Is it possible to set a width for each grid separately?
This is what the result looks like
This is the code for populating the TabContainer
function buildColumns(feature) {
var attributes = feature.attributes;
var columns = [];
for (attribute in attributes) {
if (attribute != "Shape") {
var objects = {};
objects.label = attribute;
objects.field = attribute;
columns.push(objects);
}
}
return columns;
}
function populateTC(results, evt) {
try {
if (dijit.byId('tabs').hasChildren) {
dijit.byId('tabs').destroyDescendants();
}
if (results.length == 0) {
console.log('Nothing found.');
return;
}
var combineResults = {};
for (var i = 0, len = results.length; i < len; i++) {
var result = results[i];
var feature = result.feature;
var lyrName = result.layerName.replace(' ', '');
if (combineResults.hasOwnProperty(lyrName)) {
combineResults[lyrName].push(result);
}
else {
combineResults[lyrName] = [result];
}
}
for (result in combineResults) {
var columns = buildColumns(combineResults[result][0].feature);
var features = [];
for (i = 0, len = combineResults[result].length; i < len; i++) {
features.push(combineResults[result][i].feature);
}
var data = array.map(features, function (feature) {
return lang.clone(feature.attributes);
});
var dataGrid = new (declare([Grid, Selection]))({
id: "dgrid_" + combineResults[result][0].layerId,
bufferRows: Infinity,
columns: columns,
"class": "resultsGrid"
});
dataGrid.renderArray(data);
dataGrid.resize();
dataGrid.on(".dgrid-row:click", gridSelect);
var cp = new ContentPane({
id: result,
content: "<b>" + combineResults[result][0].layerName + "\b",
//content: dataGrid,
title: combineResults[result][0].layerId
}).placeAt(dijit.byId('tabs'));
cp.addChild(dataGrid);
cp.startup();
cp.resize();
}
tc.startup();
tc.resize();
map.infoWindow.show(evt.screenPoint, map.getInfoWindowAnchor(evt.screenPoint));
}
catch (e) { console.log(e.message); }
}
The problem is not with the grid width, it's the column widths. They fit the container.
If you give a column a fixed width, you will get the desired effect.
You should be able to style .dgrid-cell or .dgrid-column-[index]
I've also had a need for more control depending on the column data. You can control the style by providing a column with its own renderHeaderCell and renderCell method as well. (style refers to dom-style)
renderHeaderCell: function(node) {
style.set(node, 'width', '50px');
}
renderCell: function(object, value, node) {
style.set(node, 'width', '50px');
}
I was able to use the AddCssRule to dynamically change the size of the grids
var dataGrid = new (declare([Grid, Selection]))({
id: "dgrid_" + combineResults[result][0].layerId,
bufferRows: Infinity,
columns: columns,
"class": "resultsGrid"
});
dataGrid.renderArray(data);
var gridWidth = "width: " + String(columns.length * 100) + "px";
dataGrid.addCssRule("#" + dataGrid.id, gridWidth);
dataGrid.resize();
dataGrid.refresh();
Here is a Fiddle that shows the result. Click on a colored polygon to show the different grids (although the content is sometimes being shoved into the header of the grid). Also, the tabs aren't being rendered correctly, but there should be 0, 224, and 227 (if you also clicked on a point).
Related
i have a for loop adding rows and cells. I want these cells to have only bottom border, thickness 1pt and black color. What is the best way to do this? the documentation is lacking examples
for (var r = 0; r < rowdata.length; r++) { //loop through data for each row
var newrow = table.insertTableRow(1+r)
//add cells and values
var cell1 = newrow.appendTableCell(rowdata[r][0])
var cell2 = newrow.appendTableCell(rowdata[r][1])
//align cell text to center
var cellStyle = {};
cellStyle[DocumentApp.Attribute.HORIZONTAL_ALIGNMENT] = DocumentApp.HorizontalAlignment.CENTER;
cell1.getChild(0).asParagraph().setAttributes(cellStyle)
cell2.getChild(0).asParagraph().setAttributes(cellStyle)
//set bottom border line width to 1pt, line color to black
//set the other borders line width to 0pt
???
}
I believe your goal is as follows.
When the rows are appended, you want to set the bottom border as 1 pt width and black color, and want to set the other borders as 0 pt width.
In the current stage, it seems that unfortunately, the Google Document service (DocumentApp) cannot manage each border. But, fortunately, when Docs API is used, your goal can be achieved. In this answer, I would like to propose achieving your goal using Docs API. When your script is modified it becomes as follows.
Modified script:
Before you use this script, please enable Google Docs API at Advanced Google services.
function myFunction() {
var doc = DocumentApp.getActiveDocument(); // Please set your Document.
var body = doc.getBody();
var table = body.getTables()[0]; // Please set your table.
var rowdata = [[,,,],[,,,],,,]; // Please set your values.
// --- This is your showing script.
for (var r = 0; r < rowdata.length; r++) {
var newrow = table.insertTableRow(1 + r);
var cell1 = newrow.appendTableCell(rowdata[r][0]);
var cell2 = newrow.appendTableCell(rowdata[r][1]);
var cellStyle = {};
cellStyle[DocumentApp.Attribute.HORIZONTAL_ALIGNMENT] = DocumentApp.HorizontalAlignment.CENTER;
cell1.getChild(0).asParagraph().setAttributes(cellStyle);
cell2.getChild(0).asParagraph().setAttributes(cellStyle);
}
// ---
doc.saveAndClose();
var docId = doc.getId();
var i = body.getChildIndex(table);
var index = Docs.Documents.get(docId).body.content[i + 1].startIndex;
var requests = [{ updateTableCellStyle: { tableCellStyle: { borderRight: { dashStyle: "SOLID", width: { magnitude: 0, unit: "PT" }, color: { color: {} } }, borderLeft: { dashStyle: "SOLID", width: { magnitude: 0, unit: "PT" }, color: { color: {} } } }, tableStartLocation: { index }, fields: "borderRight,borderLeft" } }];
Docs.Documents.batchUpdate({ requests }, doc.getId());
}
When this script is run, several rows are appended to the table on Document, and the width of vertical borders is changed to 0 pt. By this, only the bottom borders are shown.
References:
Method: documents.get
Method: documents.batchUpdate
UpdateTableCellStyleRequest
Added:
From your following reply,
that is what i am looking for with one difference. The table i am appending to already has some rows that i want to remain unchanged concerning their border style. I want to apply your code to the newly added rows only!
When you wanted to reflect the above request body to the appended rows, how about the following modification?
In your showing script, you are using var newrow = table.insertTableRow(1 + r);. In this case, the rows are put from the 2nd row. Using this script, how about the following sample script?
Sample script:
function myFunction() {
var doc = DocumentApp.getActiveDocument(); // Please set your Document.
var body = doc.getBody();
var table = body.getTables()[0]; // Please set your table.
var rowdata = [[,,,],[,,,],,,]; // Please set your values.
// --- This is your showing script.
for (var r = 0; r < rowdata.length; r++) {
var newrow = table.insertTableRow(1 + r);
var cell1 = newrow.appendTableCell(rowdata[r][0]);
var cell2 = newrow.appendTableCell(rowdata[r][1]);
var cellStyle = {};
cellStyle[DocumentApp.Attribute.HORIZONTAL_ALIGNMENT] = DocumentApp.HorizontalAlignment.CENTER;
cell1.getChild(0).asParagraph().setAttributes(cellStyle);
cell2.getChild(0).asParagraph().setAttributes(cellStyle);
}
// ---
doc.saveAndClose();
var docId = doc.getId();
var i = body.getChildIndex(table);
var index = Docs.Documents.get(docId).body.content[i + 1].startIndex;
// I modified this request body.
var requests = [{ updateTableCellStyle: { tableCellStyle: { borderRight: { dashStyle: "SOLID", width: { magnitude: 0, unit: "PT" }, color: { color: {} } }, borderLeft: { dashStyle: "SOLID", width: { magnitude: 0, unit: "PT" }, color: { color: {} } } }, tableRange: { tableCellLocation: { tableStartLocation: { index }, rowIndex: 1 }, rowSpan: rowdata.length, columnSpan: rowdata[0].length }, fields: "borderRight,borderLeft" } }];
Docs.Documents.batchUpdate({ requests }, doc.getId());
}
When this script is run, the vertical lines are removed from the appended rows from the 2nd row.
im using a handsontable https://handsontable.com/ on a webpage.
var hot = new Handsontable(container, {
data: datatable,
colHeaders: true,
rowHeaders: true,
width: 600,
licenseKey: "non-commercial-and-evaluation",
});
Now I want to dynalically highlight some cells by changing it's background color. Like this:
var dataElements = document.querySelectorAll('.handsontable td');
if (row_attr == "ALL") {
for (var k = row * numberOfCols; k < (row + 1) * numberOfCols; k++) {
dataElements[k].style.backgroundColor = color;
}
}
Thia works fine but if a scroll further down on the page and go back up to that cell it is not colored anymore.
Is anyone familliar with the handsontable.js ?
I guess the table dynamically renders the part of the table that is displayed but I'm not sure.
i am trying to get cells from a photo with a table. i have the coordonates of the cells in the image. now i want to view my cells using a konvajs library. the problem is that the table is 30x30. so i have 900 cells. when using kanva.image 900 times the browser stop working, because it tries to load 900 time the same image. i want to load one time the image and use it for croping 900 time. here are my code:
function add_i(layer,cell,row,weight,k,cloneI){
layer.add(cloneI);
cloneI.crop({
x: parseInt(cell.x),
y: parseInt(row.y),
width: cell.width,
height: row.height
});
cloneI.width(cell.width);
cloneI.height(row.height);
cloneI.y(row.y);
cloneI.x(cell.x);
}
layerP.push( new Konva.Layer());
if(weight.stage == 'pred'){
var cloneI = new Konva.Image({
id:'img_'+k,
draggable: true
});
var clone = new Image();
clone.onload = function() {
cloneI.image(clone);
layerP[0].draw();
};
for (var i in weight.predictions){
var row = weight.predictions[i];
for (var j in row.cells){
var cell = row.cells[j];
add_i(layerP[0],cell,row,weight,k,cloneI.clone());
k+=1;
}
if(i==4 && false)
break;
}
clone.src = weight.path_i;
stage.add(layerP[0]);
}
I think you should move your add_i into clone.onload like this:
function add_i(layer, cell, row, weight, k, cloneI) {
layer.add(cloneI);
cloneI.crop({
x: parseInt(cell.x),
y: parseInt(row.y),
width: cell.width,
height: row.height
});
cloneI.width(cell.width);
cloneI.height(row.height);
cloneI.y(row.y);
cloneI.x(cell.x);
}
layerP.push(new Konva.Layer());
if (weight.stage == 'pred') {
var clone = new Image();
clone.onload = function() {
var cloneI = new Konva.Image({
id: 'img_' + k,
draggable: true,
image: clone
});
for (var i in weight.predictions) {
var row = weight.predictions[i];
for (var j in row.cells) {
var cell = row.cells[j];
add_i(layerP[0], cell, row, weight, k, cloneI.clone());
k += 1;
}
if (i == 4 && false)
break;
}
layerP[0].draw();
};
clone.src = weight.path_i;
stage.add(layerP[0]);
}
cause the add_i is invoked before the onload callback because of that Konva.Image i.e. cloneI does not have native image instance when it's used.
We are using a grid with a few elements as locked.
We have set minimum and maximum height of the grid using css.
.k-grid-content {
max-height: 400px;
min-height: 0px;
}
We are facing issue setting the height of the locked grid. If we don’t set height of grid, a number of rows on the locked side get whitened at the bottom.
So how do we dynamically set the height of grid?
This is what we have on Onbound event
var grid = e.sender;
var lockedContent = grid.wrapper.children(".k-grid-content-locked")
var content = grid.wrapper.children(".k-grid-content");
if (content[0] && (content[0].scrollWidth == content[0].clientWidth))
lockedContent.height(content.height());
else
lockedContent.height(content.height()-16);
//16 is near to horizontal scroll height
grid.resize();
This is a hack and it is not working perfectly as in grouping.
We have gone through this link
http://docs.telerik.com/kendo-ui/controls/data-management/grid/how-to/Layout/change-grid-height-when-using-frozen-columns
But it doesn’t work as it assumes no height set on grid at all.
Can some one please provide the right solution?
I have prepared a dojo for you to try out to see if that works for your scenario
http://dojo.telerik.com/eSava/2
All I have done is created a function that does all the grunt work for you.
function initializeGrid(options)
{
if(options === null || options === undefined)
{
options = {
size: 0.55,
gridContentCss: ".k-grid-content",
gridLockedContentCss: ".k-grid-content-locked",
gridsToResize:[]
};
}
var windowHeight = $(window).height() * options.size;
if(options.gridsToResize !== null && options.gridsToResize.length > 0 )
{
options.gridsToResize.forEach(function (item) {
var gridContent = $('#' + item + ' > ' + options.gridContentCss);
var lockedContent = $('#' + item + ' > ' + options.gridLockedContentCss);
// console.log(gridContent, lockedContent);
gridContent.height(windowHeight);
if (lockedContent !== null && lockedContent !== undefined) {
lockedContent.height(windowHeight);
}
});
}
else
{
var gridContent = $(options.gridContentCss);
var lockedContent = $(options.gridLockedContentCss);
gridContent.height(windowHeight);
if (lockedContent !== null && lockedContent !== undefined) {
lockedContent.height(windowHeight);
}
}
$(window).resize(function () {
ResizeGrid(options);
});
}
in it's default state when this is called it will resize all grids to 55% of the windows height.
but if you want to apply different sizing rules you can by providing a simple variable like so:
var gridResize = {
size: 0.4,
gridContentCss: ".k-grid-content",
gridLockedContentCss: ".k-grid-content-locked",
gridsToResize:['grid']
}
initializeGrid(gridResize);
so in the above example it will override the default and resize the grid to 40% of the available screen size. In addition it will only resize the control with the id of grid. So if you had multiple grids on the screen at once then the function will them alone and preserve there heights.
Any issues let me know.
Coming again with another question :)
This time I had a requirement to show some progress while Child rows are being loaded. Since there is an Api call which relatively takes little time to return data, I do want to show the some progress unless the user who clicks the parent row is totally unaware whether there is a call done to see its child rows.
What I have done:
I wrote a style sheet class which has a
loader-small.gif
image as this:
tr.loading td.details-control {
background: url('/Images/loader-small.gif') no-repeat center center;
}
and applied like this:
$('#accountManagerEarningsDataTable tbody').on('click', 'td.details-control', function () {
var tr = $(this).closest('tr');
var row = table.row(tr);
try {
if (row.child.isShown()) {
// This row is already open - close it
row.child.hide();
tr.removeClass('shown');
}
else {
//Calling the loading Class ------>
tr.addClass('loading');
// Open this row
var arrForTable1 = [];
var arrForTable2 = [];
totalBrokerage = 0;
totalRetailBrokerage = 0;
totalSelfServiceBrokerage = 0;
console.log('You selected: ' + row.data().AccountManagerID);
var settings = {
"columnDefs": [
{ targets: 1, align: "right", decimals: 0 },
{ targets: 2, align: "right", decimals: 0 },
{ targets: 3, align: "right", decimals: 0 },
{ targets: 4, align: "right", decimals: 2 },
{ targets: 5, align: "right", decimals: 2 }
]
};
//problems with asynchoronus call back
var response = organization_GetAccountManagerDetailEarningsAccountData(row.data(), purl2, pcontext);
if (response.success === "true") {
for (var i = 0; i < response.value.length; i++) {
for (var j = 0; j < response.value[i].Securities.length; j++) {
var itemRow2 = {};
itemRow2["Security ID"] = response.value[i].Securities[j].SecurityId;
itemRow2["Trades"] = response.value[i].Securities[j].Trades;
itemRow2["Buy Qty"] = response.value[i].Securities[j].BuyQuantity;
itemRow2["Sell Qty"] = response.value[i].Securities[j].SellQuantity;
itemRow2["Total Brkg"] = response.value[i].Securities[j].Effective_Brokerage;
itemRow2["Online Brkg"] = response.value[i].Securities[j].Online_Brokerage;
arrForTable2.push(itemRow2);
totalBrokerage = totalBrokerage + parseFloat(response.value[i].Securities[j].Effective_Brokerage);
totalSelfServiceBrokerage = totalSelfServiceBrokerage + parseFloat(response.value[i].Securities[j].Online_Brokerage);
}
totalBrokerage = Math.round(totalBrokerage * 100) / 100;
totalSelfServiceBrokerage = Math.round(totalSelfServiceBrokerage * 100) / 100;
totalRetailBrokerage = Math.round(totalRetailBrokerage * 100) / 100;
var itemRow1 = {};
itemRow1["Account ID"] = response.value[i].AccountId;
itemRow1["Account Name"] = response.value[i].AccountName;
itemRow1["..."] = '<div class="alert alert-info" role="alert">' + buildHtmlTable(arrForTable2, 'table2x' + j, settings) + '<p>Total Brokerage ' + numberWithCommas(totalBrokerage) + '</p></div>';
arrForTable1.push(itemRow1);
arrForTable2 = [];
totalBrokerage = 0;
totalRetailBrokerage = 0;
totalSelfServiceBrokerage = 0;
}
tr.removeClass('loading');
htmlTable1 = buildHtmlTable(arrForTable1, 'table1x' + i);
row.child(htmlTable1).show();
tr.addClass('shown');
}
else {
row.child('<table><tr><td>' + response.value[0].AccountId + '</td></tr></table>').show();
tr.addClass('shown');
};
}
} catch (e) {
console.log(e.message);
}
});
The Problem:
Firefox nicely shows the Progress image after the user clicks it, but Edge and Chrome does not show. Both browsers crossed this piece of code when I was debugging from developer tools of the respective browser.
Its browser compatible problem? Is there a solution for it? Help me please.
In case of chrome there is such an issue while showing the loading bar while making a server call. Please make the following changes where you are making the service call. First add the class loading to the table
tr.addClass('loading');
After that make the service call by giving a timeout function
setTimeout(function(){
var response = organization_GetAccountManagerDetailEarningsAccountData(row.data(), purl2, pcontext);
......
//Your service calls and response call backs
},1);
On providing a timeout (say 1ms), Chrome will get the time to bind the loading bar to DOM, In other case the DOM Object is not available to show the spinner.