Closed ornic closed 4 years ago
Ooook, I was able to remove "recreate" by adding Search'n'Scroll function of my own.
@ornic datasource.minIndex
and datasource.maxIndex
should be enough. Also, autoscroll can be used instead of reload
, but min/max indexes are still might be required. I created simple demo on stackblitz showing both approaches. Hope this helps.
Thanks a lot :) I simplified my component a bit using this.
But my items all have different heights, so .load(index) is unable to place the viewport to needed position. https://stackblitz.com/edit/angular-ui-scroll-v1-7-6-limited-datasource-and-scroll-t-vufzng this is modified example to show that.
I ended up with that function (it may contain some "never happens" if
branches and some project-related stuff about editInGroups
):
$ctrl.scrollTo = function (index) {
function scrollToElement(element, localIndex, coarseMode) {
return $timeout(function (element, localIndex) {
let elem = $(element);
let parent = elem.parent();
let scrollTop = elem.position().top - $(parent.children()[0]).position().top + 1; //+1 for border, apparently
let pixelsToScroll = scrollTop - parent.scrollTop();
if (pixelsToScroll < 1 && pixelsToScroll > -1) {
if ($rootScope.debug) { $rootScope.$window.console.log('ui.scroll not trying to scroll to', index, 'scrolling to', localIndex, 'by', pixelsToScroll, 'pixels'); }
return $q.when(true);
}
if ($rootScope.debug) { $rootScope.$window.console.log('ui.scroll trying to scroll to', index, 'scrolling to', localIndex, 'by', pixelsToScroll, 'pixels'); }
let animationPromise = parent.animate({ scrollTop: scrollTop }, 10).promise();
if (coarseMode) {
return animationPromise;
}
return animationPromise.then(function () { return scrollToElement(element, localIndex, coarseMode); });
}, 0, true, element, localIndex);
}
if ($ctrl.scroll.isLoading) {
if ($rootScope.debug) { $rootScope.$window.console.log('ui.scroll trying to scroll to:', index, 'wait for loading'); }
return $timeout($ctrl.scrollTo, 50, 0, index);
}
let firstVisibleIndex = $ctrl.settings.editInGroups ? $ctrl.scroll.topVisible._groupIndex : $ctrl.scroll.topVisible._index;
let firstBufferIndex = $ctrl.settings.editInGroups ? $ctrl.scroll.bufferFirst._groupIndex : $ctrl.scroll.bufferFirst._index;
let lastBufferIndex = $ctrl.settings.editInGroups ? $ctrl.scroll.bufferLast._groupIndex : $ctrl.scroll.bufferLast._index;
if ($rootScope.debug) {
$rootScope.$window.console.log('ui.scroll trying to scroll from:', firstVisibleIndex, 'to:', index);
}
if (firstBufferIndex <= index && lastBufferIndex >= index) {
return scrollToElement($rootScope.$window.document.getElementById('ui.scroll.element.' + index), index);
} else if (index > lastBufferIndex) {
return scrollToElement($rootScope.$window.document.getElementById('ui.scroll.element.' + lastBufferIndex), lastBufferIndex, true).then(function () { return $timeout($ctrl.scrollTo, 30, 0, index); });
} else if (index < firstBufferIndex) {
return scrollToElement($rootScope.$window.document.getElementById('ui.scroll.element.' + firstBufferIndex), firstBufferIndex, true).then(function () { return $timeout($ctrl.scrollTo, 30, 0, index); });
}
};
BTW, is it possible to mark item as visible only if more than 50% of its height is visible?
@ornic No, currently no. Here's the place where this feature might be implemented:
Something like (top > this.viewport.topVisiblePos() + itemHeight * coef)
where coef
is 0.5 if you want 50%. If you like, you may implement it, add few tests, update doc, open PR and I will accept it.
PS coef
must be an attr option with default value 0 and allowed range [0; 1)
What information (apart from min/max indexes) I should provide to datasource (or adapter?) for ui.router to be able to calculate the same top/bottom offsets as at start?
Situation: I have a toggle of grouping of list of elements by on of the fields. After changing the mode, I restore the position as in example, but the scrollbar is resetting to some "default" one-third middle position.
UPD: I had to recreate* ui-scroll elements, since just reload() can't restore the position (~may be I should insert more delay in .get function, but this is not the normal way of working~ - not helping anyway). And recreating viewport element just hung the browser.
In fact, all my problems will get away if I will be able just to "scroll to element with index #" :) But I wasn't able to find anything except some... not the very easy-to-use hach with starting index from the example mentioned above.