cinera.web: Prevent auto-scroll to hidden elements

The search page could auto-scroll to the top when the grid is not
displayed. This commit fixes that problem by ensuring that the grid
element has a width and height before seeking to auto-scroll to it.

Thanks to Leonardo Serafim Eid for the report
This commit is contained in:
Matt Mascarenhas 2021-02-16 02:52:27 +00:00
parent 8283e2a9e5
commit 828fff7a7a
3 changed files with 54 additions and 63 deletions

View File

@ -23,7 +23,7 @@ typedef struct
version CINERA_APP_VERSION = { version CINERA_APP_VERSION = {
.Major = 0, .Major = 0,
.Minor = 8, .Minor = 8,
.Patch = 9 .Patch = 10
}; };
#include <stdarg.h> // NOTE(matt): varargs #include <stdarg.h> // NOTE(matt): varargs

View File

@ -63,6 +63,16 @@ GetWindowDim(IsMobile)
return Result; return Result;
} }
function IsVisible(Element, WindowDim) {
var BoundingRect = Element.getBoundingClientRect();
return ((BoundingRect.top >= 0 && BoundingRect.top <= WindowDim.Y) ||
(BoundingRect.bottom >= 0 && BoundingRect.bottom <= WindowDim.Y) ||
(BoundingRect.top < 0 && BoundingRect.bottom > WindowDim.Y))
&& ((BoundingRect.left >= 0 && BoundingRect.left <= WindowDim.X) ||
(BoundingRect.right >= 0 && BoundingRect.right <= WindowDim.X) ||
(BoundingRect.left < 0 && BoundingRect.right > WindowDim.X));
}
function function
GetRealOrientation(PreferredLandscape, IsMobile) GetRealOrientation(PreferredLandscape, IsMobile)
{ {
@ -306,55 +316,58 @@ var ScrollerFunction;
var ScrollCondition; var ScrollCondition;
function ScrollTo(Element, ScrollPos, IsMobile, StickyObscuringElement) { function ScrollTo(Element, ScrollPos, IsMobile, StickyObscuringElement) {
var ScrolledToTop = ScrollPos == 0; if(Element.offsetWidth && Element.offsetHeight)
var ScrolledToBottom = (window.innerHeight + Math.ceil(window.pageYOffset)) >= document.body.scrollHeight;
if(!ScrolledToTop || !ScrolledToBottom)
{ {
var Ceiling = StickyObscuringElement ? StickyObscuringElement.offsetHeight : 0; var ScrolledToTop = ScrollPos == 0;
var VisibleArea = GetWindowDim(IsMobile); var ScrolledToBottom = (window.innerHeight + Math.ceil(window.pageYOffset)) >= document.body.scrollHeight;
VisibleArea.Y -= Ceiling; if(!ScrolledToTop || !ScrolledToBottom)
var PercentageOfVisibleHeightToGather = 5;
var GatherableHeight = VisibleArea.Y * PercentageOfVisibleHeightToGather / 100;
var BoundingRect = Element.getBoundingClientRect();
var ElementTop = BoundingRect.top - Ceiling;
var ElementBottom = ElementTop + BoundingRect.height;
var UpperProtrusion = -ElementTop;
var LowerProtrusion = ElementBottom - VisibleArea.Y;
var DesiredScroll = null;
var YOffsetFromPage = getElementYOffsetFromPage(Element);
if(IsInRangeEx(0, UpperProtrusion, GatherableHeight))
{ {
if(!ScrolledToBottom) var Ceiling = StickyObscuringElement ? StickyObscuringElement.offsetHeight : 0;
var VisibleArea = GetWindowDim(IsMobile);
VisibleArea.Y -= Ceiling;
var PercentageOfVisibleHeightToGather = 5;
var GatherableHeight = VisibleArea.Y * PercentageOfVisibleHeightToGather / 100;
var BoundingRect = Element.getBoundingClientRect();
var ElementTop = BoundingRect.top - Ceiling;
var ElementBottom = ElementTop + BoundingRect.height;
var UpperProtrusion = -ElementTop;
var LowerProtrusion = ElementBottom - VisibleArea.Y;
var DesiredScroll = null;
var YOffsetFromPage = getElementYOffsetFromPage(Element);
if(IsInRangeEx(0, UpperProtrusion, GatherableHeight))
{ {
DesiredScroll = YOffsetFromPage - Ceiling; if(!ScrolledToBottom)
}
}
else if(IsInRangeEx(0, LowerProtrusion, GatherableHeight))
{
if(!ScrolledToTop)
{
if(IsInRangeEx(0, UpperProtrusion + LowerProtrusion, GatherableHeight))
{ {
DesiredScroll = YOffsetFromPage - Ceiling; DesiredScroll = YOffsetFromPage - Ceiling;
} }
else }
else if(IsInRangeEx(0, LowerProtrusion, GatherableHeight))
{
if(!ScrolledToTop)
{ {
DesiredScroll = ScrollPos + LowerProtrusion; if(IsInRangeEx(0, UpperProtrusion + LowerProtrusion, GatherableHeight))
{
DesiredScroll = YOffsetFromPage - Ceiling;
}
else
{
DesiredScroll = ScrollPos + LowerProtrusion;
}
} }
} }
}
if(DesiredScroll !== null && DesiredScroll != ScrollPos) if(DesiredScroll !== null && DesiredScroll != ScrollPos)
{ {
window.scrollTo({ window.scrollTo({
top: DesiredScroll, top: DesiredScroll,
behavior: "smooth" behavior: "smooth"
}); });
}
} }
} }
} }

View File

@ -553,28 +553,6 @@ function renderResults() {
} }
} }
function IsVisible(el) {
var xPos = 0;
var yPos = 0;
var Height = parseInt(getComputedStyle(el).height);
while (el) {
if (el.tagName == "BODY") {
var xScroll = el.scrollLeft || document.documentElement.scrollLeft;
var yScroll = el.scrollTop || document.documentElement.scrollTop;
xPos += (el.offsetLeft - xScroll + el.clientLeft)
yPos += (el.offsetTop - yScroll + el.clientTop)
} else {
xPos += (el.offsetLeft - el.scrollLeft + el.clientLeft);
yPos += (el.offsetTop - el.scrollTop + el.clientTop);
}
el = el.offsetParent;
}
return ((xPos > 0 && xPos < window.innerWidth) && (yPos > 0 && yPos + Height < window.innerHeight));
}
function function
InitQuery(QueryElement) InitQuery(QueryElement)
{ {
@ -588,7 +566,7 @@ InitQuery(QueryElement)
QueryElement.value = decodeURIComponent(initialQuery); QueryElement.value = decodeURIComponent(initialQuery);
} }
if(document.hasFocus() && IsVisible(QueryElement)) { QueryElement.focus(); } if(document.hasFocus() && IsVisible(QueryElement, GetWindowDim(CineraProps.IsMobile))) { QueryElement.focus(); }
} }
function function