The scrollX option in Datatables allows the user to scroll the grid horizontally - however, in my table, I am needing to keep the first two columns in place, but allow the next x columns scroll horizontally. I'm not seeing any good examples of how to do this.
Example:
https://datatables.net/examples/basic_init/scroll_x.html
You could achieve this by changing the relative position of each cell based on the scrollLeft value.
$('.dataTables_scrollBody').scroll(function (){
var cols = 2 // how many columns should be fixed
var container = $(this)
var offset = container.scrollLeft()
container.add(container.prev()).find('tr').each(function (index,row){ // .add(container.prev()) to include the header
$(row).find('td, th').each(function (index,cell){
if(index>=cols) return
$(cell).css({position:'relative',left:offset+'px'})
})
})
})
Related
My question is similar to what was asked here regarding keeping a table header fixed to the top of the viewport when scrolled over/past -- except I'm more concerned about the effect it has on the columns (th) within the table header.
In the comments on Andrew Whitaker's answer, there are some interesting suggestions to using jQuery to "fetch" the current width of the table header's columns and setting the fixed table header's columns to those widths.
However, this seems like a lot of heavy lifting especially when I'm already rendering a table within a React application (avoiding jQuery within React). It's a long shot, but has anyone come up with a better implementation?
I suppose I can just fall back to doing what is being done in this fiddle with vanilla JS.
Small snippet of jQuery logic from fiddle^
var tableOffset = $("#table-1").offset().top;
var $header = $("#table-1 > thead");
var $fixedHeader = $("#header-fixed").append($header.clone());
$(window).bind("scroll", function() {
var offset = $(this).scrollTop();
if (offset >= tableOffset && $fixedHeader.is(":hidden")) {
$fixedHeader.show();
$.each($header.find('tr > th'), function(ind,val){
var original_width = $(val).width(); // get width value from each
var original_padding = $(val).css("padding"); // get padding from each
$($fixedHeader.find('tr > th')[ind])
.width(original_width)
.css("padding",original_padding);
});
}
else if (offset < tableOffset) {
$fixedHeader.hide();
}
});
I want to see if I can optimize the code for checking which row is at the top of the viewport at a given moment. This function runs on the scroll event, and the page is dynamically loading new cells (max four on each row). The layout consists of a list of list items, positioned absolutely in a grid (most of the time 4x4).
The code as it is today (scrollPosition is fetcher earlier and is something like $(window).scrollTop()):
var topMostRow = _.min(this.container.find("li").toArray(), function(row) {
var offset = $(row).offset().top,
diff = scrollPosition - offset;
return Math.abs(diff);
})
As you might guess this takes longer and longer time the more cells are added
Is kind a hard of explain, but I think that you could store in a var the last topMostRow when you did the last scroll, and then, you could use find it in an loop with
$(lastTopMostRow).next();
or
$(lastTopMostRow).prev();
regarding the direcition of the scroll (up or down)
and check the one which is ratio positive and the next is negative on your diff
This way you will only check a few rows instead of all of them.
var elementMoveWithScroll = $('.thing_to_scroll');
$('.container_overflow').scroll(function() {
var scrollElementPosition = elementMoveWithScroll.position();
console.log(scrollElementPosition);
elementMoveWithScroll.css('margin-left', scrollElementPosition+'px');
});
When a I use a hardcoded value in the place of scrollElementPosition for example 50 this seem add the margin-left:50px on scrolling the container.
I want to be able to update the value of the elementMoveWithScroll so that it moves with the horizontal scroll, how can I do this?
Use scrollElementPosition.left for horizontal and scrollElementPosition.top for vertical corresponding values.
I would like to scroll horizontally the given element. The only way I find is using ScrollIntoView DOM method, which allows either align the element's bottom with the view bottom or the top - with the view top.
But what if the element is OK with respect to the Y axis, and I only want to scroll it horizontally? How can I align its left with the view left or its right with the view right?
EDIT
Here is more context. I have a YUI table with a horizontal scrollbar. I wish to scroll it programmatically to a certain TD node. I do not think window.scrollTo is of any help to me, since the scrollbar is on a div element, not on the whole page.
EDIT2
Turns out there is a duplicate SO question with the right answer - How can I scroll programmatically a div with its own scrollbars?
Voting to close mine.
I've recently had a problem with a table header that had inputs as filters for each column. Tabbing through the filters would move the focus, but if one of the inputs wasn't visible or if it was partly visible, it would only JUST bring the input into view, and I was asked to bring the full input and column into view. And then I was asked to do the same if tabbing backwards to the left.
This link helped to get me started: http://www.webdeveloper.com/forum/showthread.php?197612-scrollIntoView-horizontal
The short answer is that you want to use:
document.getElementById('myElement').scrollLeft = 50;
or:
$('#myElement')[0].scrollLeft = 50;
Here's my solution (which may be overkill for this question, but maybe it'll help someone):
// I used $.on() because the table was re-created every time the data was refreshed
// #tableWrapper is the div that limits the size of the viewable table
// don't ask me why I had to move the head head AND the body, they were in 2 different tables & divs, I didn't make the page
$('#someParentDiv').on('focus', '#tableWrapper input', function () {
var tableWidth = $('#tableWrapper')[0].offsetWidth;
var cellOffset = $(this).parent()[0].offsetLeft;
var cellWidth = $(this).parent()[0].offsetWidth;
var cellTotalOffset = cellOffset + cellWidth;
// if cell is cut off on the right
if (cellTotalOffset > tableWidth) {
var difference = cellTotalOffset - tableWidth;
$('#tableWrapper').find('.dataTables_scrollHead')[0].scrollLeft = difference;
$('#tableWrapper').find('.dataTables_scrollBody')[0].scrollLeft = difference;
}
// if cell is cut off on the left
else if ($('#tableWrapper').find('.dataTables_scrollHead')[0].scrollLeft > cellOffset) {
$('#tableWrapper').find('.dataTables_scrollHead')[0].scrollLeft = cellOffset;
$('#tableWrapper').find('.dataTables_scrollBody')[0].scrollLeft = cellOffset;
}
});
This is something I used a while back. There might be better and more efficient way of doing it but this gets the work done:
$(".item").click(function(event){
event.preventDefault();
// I broke it down into variable to make it easier to read
var tgt_full = this.href,
parts = tgt_full.split("#"),
tgt_clean = parts[1],
tgt_offset = $("#"+tgt_clean).offset(),
tgt_left = tgt_offset.left;
$('html, body').animate({scrollLeft:tgt_left}, 1000, "easeInOutExpo");
})
You just need to make sure that the item is an a tag with an href that corresponds to the target id element:
HTML:
go to section 1
...
<section id="one"> Section 1</section>
Hope this helps!
I want my jqGrid to shrink and expand based on the number of rows it has. Let say it currently has 10 rows, the height of the jqGrid will shrink to 10 rows (so that no gaping empty rows is exposed).
If however there are too many rows, the height of the grid will expand to a maximum 'height' value and a scroll bar will appear.
That's built into the grid. You set height to 100%. There's a demo on this page if you go "Advanced -> Resizing.
Try:
jQuery(".ui-jqgrid-bdiv").css('height', jQuery("#bigset").css('height'));
In the jQGrid callback function loadComplete. #bigset is the id for the table I used. This worked perfectly for me.
I have faced the similar problem and none of the solutions worked perfectly for me.
Some work but then there is no scrollbar.
So here is what I have done:
jQuery("#grid").jqGrid('setGridHeight', Math.min(300,parseInt(jQuery(".ui-jqgrid-btable").css('height'))));
This code has to be placed in the loadComplete handler and then it works fine.
The first parameter of the Math.min is the desired height when there is enough data to fill in the list. NOTE that this same value has to be set as height for the grid.
This script choses the minimum of the actual height and the desired height of the grid.
So if there are not enough rows the grid height is shrinked, otherwise we always have the same height!
call the below function from afterInsertRow and when deleting a row:
function adjustHeight(grid, maxHeight){
var height = grid.height();
if (height>maxHeight)height = maxHeight;
grid.setGridHeight(height);
}
Though the height 100% worked fine in the demo, it didn't work for me. The grid became much bigger, maybe it tried to occupy the parent div's height. Amit's solution worked perfectly for me, thanks! (I'm new as a contributor here, and so need a higher 'reputation' to mark any votes up :) )
Here is a generic method I came up with based on Amit's solution. It will allow you to specify the max number of rows to display. It uses the grid's header height to calculate max height. It may need tweeking if your rows aren't the same height as your header. Hope it helps.
function resizeGridHeight(grid, maxRows) {
// this method will resize a grid's height based on the number of elements in the grid
// example method call: resizeGridHeight($("#XYZ"), 5)
// where XYZ is the id of the grid's table element
// DISCLAIMER: this method is not heavily tested, YMMV
// gview_XYZ is a div that contains the header and body divs
var gviewSelector = '#gview_' + grid.attr('id');
var headerSelector = gviewSelector + ' .ui-jqgrid-hdiv';
var bodySelector = gviewSelector + ' .ui-jqgrid-bdiv';
// use the header's height as a base for calculating the max height of the body
var headerHeight = parseInt($(headerSelector).css('height'));
var maxHeight = maxRows * headerHeight;
// grid.css('height') is updated by jqGrid whenever rows are added to the grid
var gridHeight = parseInt(grid.css('height'));
var height = Math.min(gridHeight, maxHeight);
$(bodySelector).css('height', height);
}
Add below code inside loadComplete function
var ids = grid.jqGrid('getDataIDs');
//setting height for grid to display 15 rows at a time
if (ids.length > 15) {
var rowHeight = $("#"+gridId +" tr").eq(1).height();
$("#"+gridId).jqGrid('setGridHeight', rowHeight * 15 , true);
} else {
//if rows are less than 15 then setting height to 100%
$("#"+gridId).jqGrid('setGridHeight', "100%", true);
}