react-smooth-scrollbar programmatically change the scroll position? - smooth-scrolling

I'm using this scroll bar from idiotWu which works great so far:
https://github.com/idiotWu/react-smooth-scrollbar
What I need to do next is in my react project, I need to programatically change the scroll position. In my project, when my fires reactComponent.render() again because of some things I'm doing, I need to scroll back to the top of the <Scrollbar />. I don't see in the documentation any mention of how to do something like a element.scrollTop() or <Scrollbar scrollPosition={0} />.
I tried to manually set the transform translate3d of <div class="scroll-content">, but that didn't work because the scrollbar is saving it's scroll position value somewhere, and I don't know how to access it.
How do I reset the scroll to the beginning? Alternatively, how do I state the scroll position?
EDIT
I also tried each of these but they all did not produce the results I wanted
export default class MyClass extends React.Component {
render() {
document.getElementById('panel').setPosition(0,0); // setPosition is not a defined method
document.getElementById('panel').scrollTop=0; // had no effect
scrollbar.setPosition(0,0); // scrollbar not defined
scrollbar.scrollTop=0; //scrollbar not defined
return (<Scrollbar id="panel">stuff</Scrollbar>);
}
}

Try scrollbar.scrollTop = 0 or scrollbar.setPosition(scrollbar.offset.x, 0).

Related

Kendo ScrollView - Refresh/redraw current page

I'm using a Kendo ScrollView to display person images on a form.
Separate from the ScrollView, users can change the display order of the images. After they save their changes to the display order, the ScrollView is reloaded, scrolls to the first item, and should display the images in their new order.
However, I've noticed that when the ScrollView is currently on the first page, that page does not get refreshed/redrawn.
My ScrollView looks something like this:
#(Html.Kendo().ScrollView()
.Name("personImage")
.TemplateId("personImageTemplate")
.DataSource(d => d
.Custom()
.Type("aspnetmvc-ajax")
.Transport(t => t
.Read(r => r.Action("PersonImages_Read", "Person", new { personID = Model.ID } ))
)
.Schema(s => s.Data("Data").Total("Total"))
.ServerPaging(false)
.PageSize(1)
)
)
The template looks like this:
<script type="text/x-kendo-tmpl" id="personImageTemplate">
<img class="personImage"
src="#(Url.Action("ImageRender", "Person"))?imageID=#= data.ID #"
title="#= data.Filename #" />
</script>
And here is my refresh function:
function refreshPersonImageScrollView() {
var scrollView = $("#personImage").data("kendoScrollView");
if (scrollView) {
scrollView.dataSource.read();
// https://docs.telerik.com/kendo-ui/api/javascript/ui/scrollview/methods/refresh
// redraws, doesn't re-read from datasource
scrollView.refresh();
// scroll to first image
scrollView.scrollTo(0);
}
}
When I watch the requests being made when I call this function, I see this:
A. When a page other than the first page is selected:
PersonImages_Read (the ScrollView's dataSource read)
The ScrollView scrolls to the first image
3x ImageRender, as it renders the first 3 items in the ScrollView
B. When the first page is selected:
PersonImages_Read (the ScrollView's dataSource read)
Nothing else
I tried switching the order of scrollView.refresh() and scrollView.scrollTo(0), but the result does not change.
Is there any way to get Kendo to refresh/redraw the current page? I thought refresh would do it, based on the documentation, but it does not.
Edit
I've been able to replicate this issue in REPL. To see the behavior in action:
Note the "Rendered" time under the first image.
Scroll to the second image in the ScrollView.
Wait several seconds, then click the "Refresh" button.
The ScrollView should scroll back to the first image.
Observe that the "Rendered" time under the first image matches the "Last clicked" time reported below the "Refresh" button, and is no longer what it was in step #1. (This is the correct behavior.)
Remain on the first image for several seconds. Note the "Rendered" time listed before continuing.
Click the "Refresh" button.
Note that the "Last clicked" time has updated, and in the "Log" section, there is an entry that reads "dataSource read complete" at approx. the same time. However, the "Rendered" time under the image has not changed, and there is no log entry that says "image for product #X loaded".
I am using Kendo version 2021.3.1109 in my project. The Kendo version in the REPL above is 2022.3.913 and it still occurs in that version.
I have found a way to resolve the issue, but this may be worth opening a possible bug ticket with Telerik, because you would think that scrollView.refresh call would work.
What I changed in your refreshPersonImageScrollview function was to call setDataSource on the scrollview rather than calling the refresh method. Like so:
function refreshPersonImageScrollView() {
$("#refresh-last-clicked").text("Last clicked: " + getCurrentTime());
addToLog("refresh button clicked");
var scrollView = $("#personImage").data("kendoScrollView");
if (scrollView) {
scrollView.dataSource.read();
scrollView.setDataSource(scrollView.dataSource);
// scroll to first image
scrollView.scrollTo(0);
}
}
This appears to force the scrollView to re-evaluate its life choices and properly refresh :) However, it does seem to trigger additional dataSource reads, so it's not ideal.
One other thing I tried that didn't resolve the problem, but may be a good thing to change to anyway, would be to utilize the promise returned by the dataSource.read call. Meaning, do your scrollView setDataSource and scrollTo calls after the dataSource read promise is settled, like so:
scrollView.dataSource.read().then(function() {
scrollView.setDataSource(scrollView.dataSource);
// scroll to first image
scrollView.scrollTo(0);
});
REPL link here

Showing overflow of a static Flatpicker in a scrollable grid column parent

I used a grid display on the body with some control elements in column 1, and a fullpage view in the second column. The first column may contain a lot of elements and requires vertical scroll (overflow-x:auto).
I have an input element within the other elements in the grid column to which I assign flatpicker.
https://codepen.io/dbauszus-glx/pen/wvpamZr
flatpickr("#date-input", {
static: true,
//appendTo: "scroll-parent"
});
My issue is that without the static property the flatpickr control displays but doesn't scroll.
With the static property the flatpickr control scrolls together with the input element but the display overflows the parent container with scroll.
I'd like the control to show as seen without static but be linked to the input element when scrolled.
I tried to work with the appendTo property which doesn't seem to have any effect.
Trawling the flatpickr issues I found an issue related to the positioning of the flatpickr instance inside a scrollparent.
I put together a small util method which takes the flatpickr instance and a scrollParent element and attached a scroll event listener to the parent when the flatpickr instance opens.
The scroll event method will reposition the absolute flatpickr container.
The onClose event will remove the scroll eventlistener from the scrollParent element.
function appendFlatpickrToScroll(fp, scrollParent) {
fp.config.onOpen.push(() => {
scrollParent.addEventListener("scroll", scrollEvent, { passive: true });
});
fp.config.onClose.push(() => {
scrollParent.removeEventListener("scroll", scrollEvent);
});
function scrollEvent() {
fp._positionCalendar();
}
}

LibGdx How to fix a ScrollPane scroll bar position at a specific position?

How to fix a ScrollPane scroll bar position at a specific position so that it displays for example the last item of it's child Table instead of the first item Table(default)? I try setScrollX and setScrollY but it doesn't work.
I have a game level menu(with many levels) and i would like to display the last unlocked level to the user when opening that menu.
You might have to call layout() on the ScrollPane yourself manually before trying to call setScrollX or setScrollY
When you want to avoid the ScrollPanes fling effect, use the following code in your show() method, so the ScrollPane immediately shows the exact position you specified.
scrollPane.layout();
scrollPane.setScrollPercentY(.5f);
scrollPane.updateVisualScroll();
Instead of setting the scrollPercent, you could also use
scrollPane.scrollTo(x, y, width, height);
or
scrollPane.setScrollY(y);
This works for me if you've got a vertically stacked pane:
setScrollPercentY(100);
This worked for me:
scrollPane.layout();
scrollPane.setScrollPercentY(100);
For me, all the previous answers did not work:
Even after calling scrollPane.layout() multiple times, the scroll pane still had an areaHeight (scrollHeight) of -2, 0, or sth else. Only later during subsequent layout calls the correct height would be set, causing an animation where the content would slide in from the top.
The only option that fixed it for my use case (scrolling to bottom initially after adding all the initial content) was to override the ScrollPane.layout() and scroll to bottom after each layout change:
open class BottomScrollingScrollPane(actor: Actor?, skin: Skin, style: String): ScrollPane(actor, skin, style) {
override fun layout() {
super.layout()
scrollTo(0f, 0f, 0f, 0f)
updateVisualScroll()
}
}
... and optionally, if you use libktx:
#Scene2dDsl
#OptIn(ExperimentalContracts::class)
inline fun <S> KWidget<S>.bottomScrollingScrollPane(
style: String = defaultStyle,
skin: Skin = Scene2DSkin.defaultSkin,
init: KBottomScrollingScrollPane.(S) -> Unit = {}
): KBottomScrollingScrollPane {
contract { callsInPlace(init, InvocationKind.EXACTLY_ONCE) }
return actor(KBottomScrollingScrollPane(skin, style), init)
}
class KBottomScrollingScrollPane(skin: Skin, style: String) : BottomScrollingScrollPane(null, skin, style), KGroup {
override fun addActor(actor: Actor?) {
this.actor == null || throw IllegalStateException("ScrollPane may store only a single child.")
this.actor = actor
}
}
One side effect is scrolling down again after each layout change, resize etc., but that's fine for me as the layout is very short-lived anyway.
this code is set the position, width and height of ScrollPane.
scroll.setBounds(0, 60, Gdx.graphics.getWidth(), 200);

how to make a phonegap selectable scrollable div list

As the title says. I want to make a list of div elements inside a div. I want to be able to scroll the list up and down, and when the list is not scrolling anymore, i want to be able to click the listed elements do to something. I cant figure out how to do this.
the touchmove event executes whenever the user touches the div, even if the div its scrolling. THen i cant figure out how to make let the program know that the div isnt scrolling anymore, so the next touch on the elements will trigger a non scrollable event.....
EDIT:
what i have so far is this... However this is a quick "fix" and its not working as intended. For example if you scroll quickly up and down, then the div will think you pressed on one of the elements..
exerciseWrapper is the elements inside the scrolling div. Each element is wrapped around exerciseWrapper.
$('.exerciseWrapper').on('touchstart',function(){
touchstart=true;
setTimeout(function(){
touchstart=false;
}, 100);
});
$('.exerciseWrapper').on('touchend',function(){
if(touchstart)
{
$('.exerciseWrapper').not(this).css('border-color','black');
$(this).css('border-color','orange');
}
});
Ok so i finally figured this one out.. Reason why i couldnt wrap my minds around the solution on this, was because i couldnt get other events then eventstart and event end to work... At the time of writing i still cant get the other events like eventcancel and eventleave to work. However eventmove works and i solved the problem using this event. eventmove keeps updating the element its linked when you move your finger. Then i had a variable of touchmove to constantly be true if i am scrolling my div (with touchmove event). WHen i stop moving i can clik on selected element again and use a normal eventstart event.. This is my working code:
var touchmove=false;
function AddExercisesEvents()
{
$('#exerciseMenu').on('touchmove',function(){
touchstart=true;
$('h1').text("move");
});
$('.exerciseWrapper').on('touchend mouseup',function(event){
event.stopPropagation();
event.preventDefault();
// $('.exerciseWrapper').off();
if(event.handled !== true)
{
touchstart=false;
//ENTERING editExercise Menu..!
if(!touchstart)
{
//insert magic here
alert($(this).attr('id'));
}
}
return false;
});
}

Safari - updating a link's title via XMLHTTPRequest on mouse hover?

I'm doing some Mac development in a WebView. I want to expand URLs that have been shortened by a url shortener, and display that expanded URL to the user. So, given a link whose src attribute is set to http://is.gd/xizMsr, when the user hovers over the link I want the title tooltip to display http://google.com
My link tag looks like this:
Here's a shortened link to google
And here's the relevant javascript, which will use XMLHttpRequest to fetch the expanded URL and then update the title
var myRequest;
var mousedOverElement;
var isLoading = false;
function myFunction(anObject) {
if (isLoading == false) {
isLoading = true;
mousedOverElement = anObject;
var link = anObject.getAttribute('href');
var encodedURL = encodeURI(link);
var url = 'http://is.gd/forward.php?format=simple&shorturl=' + encodedURL;
myRequest = new XMLHttpRequest();
myRequest.open("GET", url);
myRequest.onreadystatechange = onStateChange;
myRequest.send();
}
}
function onStateChange() {
if (myRequest.readyState==4) {
if (myRequest.status==200) {
mousedOverElement.setAttribute('title',myRequest.responseText);
}
isLoading = false;
}
}
The problem is, when I hover over the link, and then stop moving the cursor, the title attribute is set properly, but the tooltip is not shown. I have to move the mouse again to make the tooltip show up. I don't necessarily have to move the cursor off of the link and then back over it, but simply moving a few pixels while remaining hovered over the link will do the trick.
I know that the title is being set properly from a combination of using the Web Inspector and the Javascript debugger in Safari. In fact, pretty much as soon as I hover over the link, I see the Web Inspector's view of the DOM in the "elements" tab update with the new title. But, if I take my hand off of the mouse, the tooltip never shows.
My assumption here is that WebKit only shows a tooltip when the user is moving the mouse. Is there a way to sort of "wake up" webkit, even if the cursor is not moving? Or am I better off implementing this with some of my own DHTML-ish magic instead of relying on the title attribute?
What about an element (move it over the anchor) or a wrapper (positive z-index) with a transparent background which will (onmouseover):
first add the anchor's title (you will have to modify your function)
and then change its (negative for the covering element) z-index (effectively putting the anchor in the foreground)
This way the title will be readily available. If necessary you can add a setTimeout() between step 1 and 2.
Or you could simply use setAttributeNode to modify the title attribute value.
You said
"The problem is, when I hover over the
link, and then stop moving the cursor,
the title attribute is set properly,
but the tooltip is not shown."
Its likely that because the title did not exist when you started the mouse hover, it could not display any tooltip (there was nothing to display). So no tooltip will appear. When you move the mouse again, this time it does have a title attribute, so it can display a tooltip. Theres not much you can do about that, its just how the browser works.
Instead your could try using a jQuery tooltip: http://www.reynoldsftw.com/2009/03/10-excellent-tooltip-plugins-with-jquery/
With jQuery you should be able control it so that a tooltip appears as soon as the title is set.

Resources