programatically scroll *within* a child div in angular - javascript

I'm writing my own directive which controls a child div (widget to be exact) within a larger screen. The view for the directive contains a scroll bar, separate from the scroll bar on the larger webpage.
When a user clicks a button to calculate results I want to jump down to the results part of the view IFF results come back, but not move the screen if we don't get any results back for his query.
I'm having trouble doing this. $anchorScroll doesn't seem to work, it scrolls the entire screen down instead of just the content of my directive's child div, and in fact doesn't scroll at all if the value I want to scroll to doesn't yet show on the child div.
I've seen plenty of examples of a directive that can be added to an HTML element to handle scrolling but they function on-click without the extra programmatic control I want, deciding when to actually scroll from within a controller method. I don't know how to generalize this logic to work within my larger directive unfortunately.
How would I go about scrolling a child div programmatically without scrolling the larger div?

You could use element.scrollTop = x. You can see a basic demo here - it will automatically scroll the child div's content after 2 seconds.
The demo uses $timeout, obviously you'll need to put that logic in your $http calls success part.
Assuming you have everything else done, the relevant part is the following:
var target = angular.element(document.querySelector('#result'));
// #result is your directive's child div
target[0].scrollTop = 200;
// You'll have to calculate the exact number if it's not a fix one.

Related

Vue draggable with elements that change height upon being dragged

I have a Vue3 app with vue-draggable and I have a list of sortable cards which possibly contain long text inside. To make dragging easier, I want to hide the text contained in the cards and only show their title when one is being dragged. This makes it easier to drop the card into the right position.
In order to achieve this, the elements which I want to hide inside of the cards while one is being dragged are given a CSS class hidden-while-dragging and the whole collection receives a class dragging while an item is being dragged. This is achieved by setting a boolean variable to the correct value upon receiving the events start and end and conditionally setting the class on the whole <draggable> element. Then I have this CSS rule:
.dragging .hidden-while-dragging {
display: none;
}
This works fine except for one case: if I drag an element and, upon dragging, the height of the parent container changes (due to the disappearing of the content inside of the cards), I am not able to drag the item: it instantly gets dropped in place, and no end event is emitted, so for example the collection keeps the class dragging.
Afterwards, I am able to drop the element once again: the issue doesn't occur this time, because no change in height occurs, and after I drop the element, everything goes back to "normal".
I made this repo in order to have a reproducible example: https://github.com/samul-1/vue-draggable-bug-demo
Here's a codepen as well: https://codepen.io/samul-11/pen/mdjKvZa try and drag the first or last element and you'll see the issue.
You can observe the height of the #app element changing when dragging an element. An interesting thing is that this only happens if dragging the first or third item in my example, not the second. So apparenly the issue is with elements at the edge of the parent.
Is this a bug with the library or is there a way around it?

Disable Chrome's scroll preserving feature

I have a page containing a list of items:
Load more button should load some more items via ajax and append it to the items container preserving current scroll position. So after I click it the feed I expect it to look like this (green items are new):
But in fact Chrome 56 executes some computations to make the page stay in the same state, and what I see looks like this:
Is there any way to prevent this smart scrolling position setting in Chrome?
Update: I can reproduce the behavior only if parent container ('body' in my case) has 'display: flex' property (I use it to achieve 'sticky footer' feature).
I solved a similar problem by adding overflow-anchor: none; to the scroll container.
https://wicg.github.io/ScrollAnchoring/
Today it seems that this property was excluded? When adding 'overflow-anchor: none;' as style on a div element I get the message: Validation (CSS 3.0): "overflow-anchor" is not a known css property name.
This is simple. Before performing your AJAX call, save the scroll position of the page to a variable, then, after the call, scroll to the position indicated by that variable. Here is what you should write before your AJAX call:
var scrollpos = window.scrollY;
and here is the code after your AJAX call
window.scrollTo(0,scrollpos)
Hope this works
Why chrome makes calculations to preserve the scroll position? Usually the page will only be longer, so the scroll position stay fixed anyway.
I assume you remove the button, so the position cannot be kept, while content was not reloaded. You should reserve the button space in the dom and remove the reserved space when inserting the reloaded items.

Page not scrolling to top in salesforce lightning

In salesforce lightning component, we have three different divs which we are hiding and showing as needed using display none css property. Fist div has more contents and we have to scroll the page till the end to submit the form and on submit next page is visible which has few lines of content but we have to scroll up to see those contents. Is there any way that I can avoid scrolling. Second div is taking first div height.
You could try this in your doInit controller method:
window.scroll(0, 0);
Use below code. As Salesforce lightning use 'transform' CSS property to scroll.
Just apply 'scroller' class to the div you want to put on top.
var cssScrolltoTop = $(".scroller"); // css class to find scroll position
if (cssScrolltoTop) {
var cssScrolltoTopTransform = cssScrolltoTop.css("transform");
if (cssScrolltoTopTransform) {
cssScrolltoTop.css("transform", "translate3d(0px, 0px, 0px)"); //set 'transform' since lighntning architecture uses css 'transfrom' property to scroll
}
}
I faced similar issues , then we used this event in the controller to resize the div:
$A.get("e.ui:updateSize").fire();
This was later deprecated by salesforce then we wrapped the div which is expanding / collapsing:
<ui:scrollerWrapper >
// Add your <div>
</ui:scrollerWrapper>
To make the scrollTop = 0 to work the container div has to have an internal scroll. Which we can get by either giving a height via px or via vh.
Try that out it should work. I was facing a similar issue while adding LWC inside Flexi Page. The Flexi page has its own scroller but for that, the scrollTop doesn't work. But if we create a separate scroller at the top-level div then the scrollTop starts to work.
Check this out. I have created this and it works perfectly fine for me: https://webcomponents.dev/edit/3vpWJ46hxykfPSACfuNN

Using offset.left and width() in backbone view

I have one backbone view (view 1) that renders another (view 2). View 1 also adds a click event to category links in view 1 that triggers an event in view 2 (view2.trigger("elementAdded")). The event function in view 2 checks for the width and offset left of image elements to display them in a carousel. View 1 passes the image links to view 2, which displays them in a carousel. I have trouble retrieving the width and offset left (left position on the page) of these images in view 2 event function because they have not yet been added to the DOM (using $('.image').offset().left and $('.image').width() gives me the wrong information sometimes). How do you handle situations like that when you're using Backbone to render HTML elements? How can I trigger the event once I know that the elements have been added to the DOM? How can I make sure the elements were added to the DOM so that I get the right info?
You can't reliably get the width before it's in the DOM. It may be affected by CSS, etc. that aren't applied until the element is in the DOM.

jQuery offset, position element under another, where the right borders touch of the aligned elements

Ok, the subject is not super specific to the overall need I am looking to address. So I have this function that is called on a given element, which is a hidden submenu next to a triggering element. The way the page renders, and to keep the styling optimized I can't just style the position in via css. So I need javascript/jquerys help.
With that I have come up with a function that I can reuse as needed, and works fine all around. However my key problem is, that I have a couple cases where the submenu will overlap the edge of the <section> element it resides in. Which that elements overflow is set to hidden, that and its also about 30 pixels from the bottom of the page anyway. All in all the submenu element gets hidden a bit by either falling completely out of the pages view half way through the element, or it gets hidden by the section tags overflow state.
With that. In a case where this happens I am wanting to instead of have the element align to the bottom of the trigger element, have it align to the top instead so that way the menu in that case is above the trigger element and not below.
Problem is Im not sure how to compensate for that.
Here is the function I came up with to do what I need, now I just need some help in a sense catching when the menu element falls off the page so to speak, so I can adjust for it when it does.
function openSubOrgMenu(triggerID, elem)
{
orgSubOpenID = triggerID;
orgSubShowing = true;
elemOffset = elem.offset(); //trigger element
elemWidth = elem.width();
elemHeight = elem.height();
elemWrap = elem.siblings('.org_group_wrapper');//menu element
elemWrapWidth = elemWrap.width();
elemWrapHeight = elemWrap.height();
moveTop = elemHeight + elemOffset.top + 4;
moveLeft = elemOffset.left - (elemWrapWidth-elemWidth-15);
elemWrap.show().offset({top:moveTop, left:moveLeft});
}
Well here is a JS Fiddle, not necessarily showing a working logic of what I want, but demonstrating the desired effect when its an element that at the bottom of the page/section:
http://jsfiddle.net/4zwEr/

Categories

Resources