React Scrollable and lockable side bars - css

I'm trying to create a scroll implementation similar to Facebook's feed in the way that they conditionally lock the side bars. For example if the content in the side bars is shorter than the viewport then the side bars don't scroll. If it does need to scroll, then it scrolls until the bottom of the side bar and stops at the end(all while allowing the center feed to keep scrolling)
The good part, I have almost all of this done, except for a few small issues and conditionally locking the side bars when they are fully in view.
The side bar contains quite a bit of data, and changes dynamically in height after everything is fetched. So my plan is below:
componentDidUpdate(prevProps) {
const leftSideBar = this.leftSideBar.current;
const scrollableWindow = window.innerHeight;
const sideBarHeight = leftSideBar.scrollHeight;
let offset = sideBarHeight - scrollableWindow;
if (this.state.offset !== offset) {
this.setState({ offset: offset });
if (offset > 0) {
this.setState({ lockScroll: false });
} else {
this.setState({ lockScroll: true });
}
}
}
This seems to be working inconsistently, sometimes the sideBarHeight is incorrect and I think it is because the component is updated and I'm getting that value before it is rendered and the height changes?
Basically I'm wondering if there is a better approach to this?

Related

How to move elements on scroll in React.js?

I am trying to create an E-commerce Store and I'm a beginner in React.JS. What I want is for 5 images to come together on top of eachother when the user scrolls. (so they should move TranslateX on scroll). Previously, on Vanilla Javascript I would have added a window.addEventListener('scroll') and then set a value like value = window.scrollY and then I would have selected the image I wanted to move and simply translateX or Y based on that value.
However, I'm not sure how to do this in React. Where can I set the window event listener? Is there a state needed, or useEffect?
I'm attaching an image so you can clearly see what I am trying to do:
What I have in react is the "Scroll" component which contains 2 divs
-1 div on the left 2/3 flex size containing all the images that should come together
-1 div on the right 1/3 flex size containing the text and the button
inside the left div I have 5 images, and in CSS i've used position absolute to position them on top of eachother (they are all PNGs so they have transparent background).
How would I go about implementing this on my website?
HUGE thanks in advance!
You can save the scrollY in a useState, which you then use to transofrm your images. The window listeners can be loaded inside a useEffect.
It (could) look like this:
const [scrollY, setScrollY] = useState(0);
useEffect(() => {
const handleScroll = () => {
setScrollY(window.scrollY);
};
handleScroll();
window.addEventListener("scroll", handleScroll);
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, []);
(You may have to add some ESLint rules if you use it)

How to move time axis to the right side in Fullcalendar?

If we set a dir property to rtl, then the time axis goes to the right side, I need the same, but the rest of the calendar should be in ltr mode. I tried swapping cells in the grid:
const timeElements = [].slice.call(slats.querySelectorAll('.fc-time'));
timeElements.forEach((item: HTMLElement) => {
const parent = item.parentNode;
if (parent) {
parent.insertBefore(parent.children[1], parent.children[0]);
}
});
But it breaks columns adjustment:
Screenshot
Is there any way to do that without changing the source code?

Sticky navigation element jumps during scroll

In Firefox especially, I've run into an issue I can't figure out how to fix.
On the following page, when scrolling down the page jumps several times - mainly on smaller screens where the page doesn't have its full size displayed. You can replicate this issue by making your browser smaller than the page so you have to scroll.
It's on this page: http://www.nucanoe.com/frontier-accessories/
If I disable the position:fixed on the navigation selector, it fixes the issue - but we need the navigation to be sticky. Is there a solution to fix this? I'm thinking we may need to use jQuery somehow.
Thanks in advance!
After seeing you asking for help on another answer, I will try and explain more clearly for you.
The Problem
Your problem is when you add position:fixed to the navigation bar, it removes it from its place and sticks it at the top of the page. This is why the rest of your content jumps up - because the navigation bar is not where it was anymore.
How To Fix
You can get around this by wrapping your navigation element in a new div - let's call it nav-wrapper - and set its height to the same as your navigation element. These are known as placeholder elements. This new wrapper and your original navigation bar must always be the same height for the 'jump' to disappear.
<div class="nav-wrapper" style="height:80px;"> <-- add this
<div class="your-original-nav" style="height:80px"></div>
</div> <!-- add this
Now, when you set the navigation bar to fixed and it disappears to the top, the new wrapper we created with the same height keeps the page's content the same. When the fixed class has been removed, it sits back in the wrapper again, without pushing the content down.
A Suggestion
From what I can see on your site, there will be a big gap where the navigation bar was until the new fixed navigation reaches that point and covers it. What you want, is a little jQuery to figure out where to make the navigation fixed and where to hide it. I'll explain:
// cache the element
var $navBar = $('.your-original-nav');
// find original navigation bar position
var navPos = $navBar.offset().top;
// on scroll
$(window).scroll(function() {
// get scroll position from top of the page
var scrollPos = $(this).scrollTop();
// check if scroll position is >= the nav position
if (scrollPos >= navPos) {
$navBar.addClass('fixed');
} else {
$navBar.removeClass('fixed');
}
});
You may want to add further functionality to this example, as it is very, very basic. You would probably want to recalculate the offsets on window resize as one addition.
A Demo
This is a little demo which might help you - I was bored and feeling helpful :)
Made it this way now: Added an element before the nav:
<div class="nav-placeholder"></div>
And the jquery:
<script type="text/javascript">
$(document).on("scroll",function(){
if($(document).scrollTop()>150){
$(".nav-placeholder").height($(".nav").outerHeight());
} else {
$(".nav-placeholder").height(0);
}
});
</script>
When I scroll down to 150 the placeholder gets the height of the nav, when i scroll up again I set it's height to 0.
Here is a fiddle: https://jsfiddle.net/herrfischerhamburg/562wu62y/
You need to have a placeholder when your nav goes from relative to fixed.
Therefore you need to make a new div.
jQuery(".nav").wrap('<div class="nav-placeholder"></div>');
jQuery(".nav-placeholder").height(jQuery(".nav").outerHeight());
jQuery(".nav").wrapInner('<div class="nav-inner"></div>');
Remember to change ".nav", "nav-inner" and "nav-placeholder" to your desire.
For a fully functional sticky nav, check my website: http://www.swegre.se/
I solved the problem differently so on firefox as you can see in logs it scroll up itself so to stop this scrolling I made simple statement
$(document).ready(function () {
var header = $('#left-menu');
var offset = header.offset().top;
var up = true;
$(window).scroll(function () {
var scroll = $(window).scrollTop();
console.log(scroll + ' ' + offset )
if (scroll >= offset) {
header.addClass('sidebar-sticky');
if (up){
$(window).scrollTop(offset);
up=false;
}
} else {
up=true;
header.removeClass('sidebar-sticky');
}
});
});
that solution work for me when I can't specify height of div's I use.

PhantomJS: Webkit-Transform scale causes page to flow outside viewport

I'm trying to generate large png screenshots of web pages using PhantomJS, which is built on webkit. I have the application generating screenshots just fine (using their raster.js example.) But, I want the text to be larger (rather than 12-16px) - I don't care about the images becoming grainy. I thought that I could simply scale/zoom the webpage doing something like:
document.documentElement.style.webkitTransform = "scale(2.0)";
But that causes the content of the page to escape the viewport. You can see this if you evaluate that line of code in Chrome. Is it possible to scale a whole web page (duplicating "Ctrl +" functionality of the browser) in JavaScript/Phantom.js?
My current phantom.js script looks like:
var page = new WebPage(),
address, output, size;
if (phantom.args.length < 2 || phantom.args.length > 3) {
console.log('Usage: rasterize.js URL filename');
phantom.exit();
} else {
address = phantom.args[0];
output = phantom.args[1];
page.viewportSize = { width: 1280, height: 1024 };
page.open(address, function (status) {
if (status !== 'success') {
console.log('Unable to load the address!');
} else {
page.evaluate(function () {
document.body.style.webkitTransform = "scale(2.0)";
});
window.setTimeout(function () {
page.render(output);
phantom.exit();
}, 200);
}
});
}
Try
page.zoomFactor=2.0;
The webkitTransform CSS property is not going to do what you want, with or without setting the origin. For one thing, it does not change the dimensions of elements (ie, no relayout occurs, the element(s) are zoomed within their current bounding boxes).
Update
You forgot to set the CSS transform-origin property, so your content expands half up and half down (the default is 50% 50%) and the upper part escapes.
So set it to 0% 0% to get the transform happen only down and right:
document.body.style.webkitTransformOrigin = "0% 0%";
You will also have to set the body width to 50% to avoid it ending twice as large as your viewport:
document.body.style.width = "50%";
Old answer - disregard
This resolves only vertical alignment
Ok, the scaling goes up and down, but the viewport extends only down. The fix fortunately is easy: move your content down of half its height.
Use this as your doubling function and you'll be fine:
page.evaluate(function() {
var h = $('body').height();
$('body').css('position', 'relative');
$('body').css('top', h/2 + 'px');
$('body').css('-webkit-transform', 'scale(2.0)');
});
Be aware anyway that getBoundingClientRect() and page.clipRect behaves weirdly when dealing with this transform.

Algorithm to determine if a component is fully visible in Flex?

Is there a built in way to determine if a component is fully visible in a Flex application (i.e. not offscreen one way or the other). If not how would I go about figurin it out?
I want to show or hide additional 'next' and 'previous' buttons if my primary 'next' and 'previous' buttons are off screen.
What event would be best to listen to to 'recalculate' ? stage.resize?
thanks!
here is a method for calculating if the component is within the bounds of the stage, it will not however tell you if the component is being hidden by another component, or if the component is being hidden because it is outside the bounds of another container.
public function isComponentWithinStage(c:UIComponent):Boolean {
var tl:Point = c.localToGlobal(new Point(0, 0));
var br:Point = c.localToGlobal(new Point(c.width, c.height));
//are we off the left or top of stage?
if ( tl.x < 0 || tl.y < 0 ) {
return false;
}
var stage:Stage = Application.application.stage;
//off the right or bottom of stage?
if ( br.x > stage.width || br.y > stage.height ) {
return false;
}
return true;
}
Could you give the specifics of the visible item and the container(s) it's in? Is it a matter of having to scroll some container to get to the buttons? Or is it a matter of someone has dragged a child window of a flexlib:MDICanvas partially off screen?
I think it's going to come down to if the x,y position of the component is beyond the width and height of its container, (and so on up through the parent containers until you reach your top level Application.)

Resources