angular ui-grid auto height if rows have non-constant height - angular-ui-grid

I'm trying to make angular ui-grid automatically resize the height so that all rows are shown without the need of its scrollbar, but without wasting space if there are only a couple rows in the grid. Someone has asked a similar question (Angular ui-grid dynamically calculate height of the grid), but the question presupposes that the row heights are constant. If the row heights are different (for example, because you have word-wrap enabled), then the accepted solution to the problem (https://stackoverflow.com/a/28706349/877570) won't work, because the solution as does the question assumes constant row height. If I have a cell with a large amount of text in it, and the text wraps to the next line, then that rows height is different.
I found a possible solution by the user anhkind here: (https://github.com/angular-ui/ui-grid/issues/1735)
.ui-grid, .ui-grid-viewport {
height: auto !important;
}
"And of course minRowsToShow and virtualizationThreshold should be set to the size of the list."
However, when I deploy his solution, it takes a much longer time for the grid to render.
Does anyone know how to address this or have an alternative solution?

$scope._minRows = 10;
$scope._maxRows = 10;
// Lots of Grid Options, plus data setting going on here.
$scope.agendaItemsGridOptions.onRegisterApi = function(gridApi) {
//set gridApi on scope
$scope.gridApi = gridApi;
});
var setMinRowsLogic = function() {
$scope.gridApi.grid.options.minRowsToShow = $scope._minRows;
if (!_.isUndefined($scope.agendaItemsGridOptions.data)) {
var len = $scope.agendaItemsGridOptions.data.length;
if (len > $scope._maxRows) {
$scope.gridApi.grid.options.minRowsToShow = $scope._maxRows;
} else
if (len < $scope._minRows) {
$scope.gridApi.grid.options.minRowsToShow = $scope._minRows;
} else {
$scope.gridApi.grid.options.minRowsToShow = len;
}
}
};

Related

HighCharts-XRange Series: how to restrict data labels width to stay within corresponding data point width

I am working with XRange charts in High Charts where I have custom data labels for my data points. I face a similar problem in 2 scenarios:
When data label text is longer than width of corresponding data point range, it overflows outside and onto adjacent data points and hides their label, like this:
When scrolling across the x-axis, the data labels slide across and overflow even when the data point range isn't wide enough to show. This looks quite confusing;
.
You would notice it looks even worse here;
.
How do I fix this so that the data labels never flow outside the extent of the data point?
I have tried tweaking the "inside" parameter but it only ensures that the label doesn't flow into an adjacent row. Similarly, I looked at the crop and overflow options in the API but couldn't get it to work for me as needed.
I understand the width option in style might let me address the first problem, but I can't have a common absolute value in pixels for all labels as the width of each is dynamic. Also, the second problem still wouldn't be solved.
You can find both issues re-created here : https://jsfiddle.net/td0bsxg1/4/ . I need to handle both of them as gracefully as possible.
Do I need to change some parameter for the data labels?
dataLabels: {
enabled: true,
defer: false,
inside: true,
formatter: function () {
return 'Too Long Data Label';
}
}
You can dynamically set individual width style for each data label and define rules for them:
events: {
render: function() {
if (redrawEnabled) {
var points = this.series[0].points,
chart = this,
dataLabelWidth,
width;
redrawEnabled = false;
Highcharts.each(points, function(point) {
width = point.shapeArgs.width;
if (width < 20) {
point.dataLabel.hide();
} else {
point.dataLabel.show();
}
point.dataLabel.css({
width: width
});
});
chart.series[0].isDirty = true;
chart.redraw();
redrawEnabled = true;
}
}
}
Live demo: https://jsfiddle.net/BlackLabel/wo0q9nzr/

Adding a scrollbar to ui-grid overlays the bottom row

An application that I'm working on has a ui-grid on the page. Recently, we added a horizontal scrollbar to the grid and also enabled "pinning" so that some of the columns could be frozen while the grid was scrolled horizontally.
One odd behavior that I've noticed is that the newly added scrollbar overlays the last row in the table. Has anyone else ever experienced this and, if so, figured out how to stop it from happening? I've tried everything I could think of (i.e. changing row height, dynamic sizing of the grid, etc) but nothing is working. I'm hoping someone else has overcome this issue and can tell me how they did it.
Well, I found a way to resolve this, but it's particular to how our grids are created.
All of our grids that have horizontal scrolling have the first three columns pinned. I used the code below to see if the grid in question has the grid option for pinning. If the grid is scrollable, I simply add 15 to the grid's height. This makes the grid bigger so that there's plenty of room for the scrollbar without it overlaying the bottom row.
var scrollbarOffset = 15;
var buffer = 5;
var gridHeight = ((rowCount > 0 ? rowCount : 1) * rowHeight) + footer + header + filter + buffer;
var scrollable= $.grep(element[0].attributes,
function (rn) {
return rn.nodeName === "ui-grid-pinning";
}).length > 0;
if (scrollable) {
gridHeight = gridHeight + scrollbarOffset;
}

Scroll To Top button that only appears when you reached the end of the page

I think this is rather easy achieved, but I couldn't find out how to- and couldn't find much documentary about it.
I hate those 'scroll to top' buttons that appear after you already scrolled just 300px. Like I'm that lazy to scroll to top on myself. Therefor I would like to have a scroll to top button that only appears when you reached the bottom of the page (minus 100vh (100% viewport height).
Let's take in account the button is called .scrollTopButton and it's CSS is opacity: 0 and it's position: fixed on default.
How would I make the button appear when you reached the bottom of the page, minus 100vh and scroll along?
I was thinking of comparing the body height minus 100vh with (window).scrollTop().
var vH = $(window).height(),
bodyMinus100vh = ($('body').height() - vH);
if (bodyMinus100VH < $(window).scrollTop) {
$('.scrollTopButton').toggle();
};
Fixed it myself. Quite easy, honestly.
$(window).scroll(function () {
var vH = $(window).height(),
bodyHeight = ($(document).height() - (vH * 2)),
// When you open a page, you already see the website as big
// as your own screen (viewport). Therefor you need to reduce
// the page by two times the viewport
scrolledPX = $(window).scrollTop();
if (scrolledPX > bodyHeight) {
$('.scrollTopButton').css('opacity', '1');
} else {
$('.scrollTopButton').css('opacity', '0')
};
});

Set z-index to dynamically generated image label to prevent overlapped label hidden from image

I am implementing drag and drop, user can drag few images and drop them in a div, and I dynamically append a p tag as label to each image once user click on a button.
Currently I meet problem when I have 2 images which is very close to each other (one is on top of another). The appended p tag for the top images will be hidden by the bottom image. I tried to alert the z-index for each dropped image, and found out it is 'auto'. I guess I need to assign a new z-index for each div, but I tried in the function which i append the label, and it dint work as expect:
function generateLabel() {
var current = 5000;
$('#rightframe img').each(function () {
var cImgName = $(this).attr('id');
var width = $(this).width();
// To select the respective div
var temp = "div#" + cImgName;
$.ajax({
url: '/kitchen/generatelabel',
type: 'GET',
data: { containerImgName: cImgName },
async: false,
success: function (result) {
$(temp).append(result);
// I guess the each function loop through each div according to the time it is created, so I try to assign a decreasing z-index
$(temp).css('z-index', current);
current -= 100;
// To select the label for the image
temp += " p";
// Set label width based on image width
$(temp).width(width);
}
});
});
However, what I get is, bottom image which dropped later do NOT hide the label of the image above, but if the above image is dropped after than the bottom image, above image's label is hide by the bottom image.
It's a very specific situation and I hope I do make myself clear...
Hope can get some help here... Appreciate any feedback...
I am so glad that I able to work out a solution for this kinda weird problem. I get to one useful plugin, the jquery-overlaps which check 2 dom whether they are overlapped with each other or not. Then i assign a z-index to the label accordingly.
Just to show my solution here, in case anyone jump into this bottleneck :)
// To assign an increasing z-index to the label
var count = 100;
$('#rightdiv p').each(function () {
// If any label overlaps with the image (used overlaps plugin)
if ($(this).overlaps($('#rightdiv img'))) {
// Increase count (the z-index)
count += 10;
// Set the parent div z-index 1st, if not the label z-index do not have effect
$(this).parent().css('z-index', count);
$(this).css('z-index', count);
}
});
Thanks! :D

How to avoid JQuery UI accordion with a long table inside from scrolling to the beginning when new rows are appended?

I have a table of many rows in a JQuery UI accordion.
I dynamically append the table this way:
var resJson = JSON.parse(connector.process(JSON.stringify(reqJson)));
for ( var i in resJson.entryArrayM) {
// test if entry has already been displayed
if ($("#resultTr_" + resJson.entryArrayM[i].id) == null)
continue;
$("#resultTable > tbody:last").append(listEntry.buildEntryRow(resJson.entryArrayM[i]));
}
Firstly I check if a row of the same tr id already exists. If not, I would append to the last row of the table.
It works. But the problem is: every time a row is appended, the accordion would scroll to the first row of the table. Since the table is remarkably long, it makes users inconvenient to scroll down again and again to watch newly-added rows. So how to avoid this?
First of all, just do one append rather than appending every time through the loop:
var resJson = JSON.parse(connector.process(JSON.stringify(reqJson)));
var seen = { };
var rows = [ ];
var trId = null;
for(var i in resJson.entryArrayM) {
// test if entry has already been displayed
var trId = 'resultTr_' + resJson.entryArrayM[i].id;
if($('#' + trId).length != 0
|| seen[trId])
continue;
rows.push(listEntry.buildEntryRow(resJson.entryArrayM[i]));
seen[trId] = true;
}
$("#resultTable > tbody:last").append(rows.join(''));
Also note that I corrected your existence test, $(x) returns an empty object when x doesn't match anything, not null. Not only is this a lot more efficient but you'll only have one scroll position change to deal with.
Solving your scrolling issue is fairly simple: find out what element is scrolling, store its scrollTop before your append, and reset its scrollTop after the append:
var $el = $('#whatever-is-scrolling');
var scrollTop = $el[0].scrollTop;
$("#resultTable > tbody:last").append(rows.join('')); // As above.
$el[0].scrollTop = scrollTop;
There might be a slight visible flicker but hopefully that will be lost in the noise of altering the table.
You could also try setting the table-layout CSS property of the <table> to fixed. That will keep the table from trying to resize its width or the width of its columns and that might stop the scrolling behavior that you're seeing. The downside is that you'll have to handle the column sizing yourself. But, you could try setting table-layout:fixed immediately before your append operation to minimize the hassle.

Resources