Pārlūkot izejas kodu

fix: scroll element block (#1507)

Ahmad Kholid 1 gadu atpakaļ
vecāks
revīzija
8955de573e
1 mainītis faili ar 55 papildinājumiem un 1 dzēšanām
  1. 55 1
      src/content/blocksHandler/handlerElementScroll.js

+ 55 - 1
src/content/blocksHandler/handlerElementScroll.js

@@ -1,5 +1,54 @@
 import handleSelector from '../handleSelector';
 
+function isElScrollable(element) {
+  const excludedTags = ['SCRIPT', 'STYLE', 'SVG', 'HEAD'];
+
+  const isOverflow = /scroll|auto/.test(getComputedStyle(element).overflow);
+  const isScrollable =
+    element.scrollHeight > element.clientHeight ||
+    element.scrollWidth > element.clientWidth;
+  const isExcluded =
+    element.tagName.includes('-') || excludedTags.includes(element.tagName);
+
+  return isOverflow && isScrollable && !isExcluded;
+}
+
+function findScrollableElement(
+  element = document.documentElement,
+  dir = 'down',
+  maxDepth = 5
+) {
+  if (maxDepth === 0) return null;
+
+  const isScrollable = isElScrollable(element);
+  if (isScrollable) return element;
+
+  if (dir === 'up') {
+    const parentEl = element.parentElement;
+    if (!parentEl) return null;
+
+    const scrollableElement = findScrollableElement(
+      parentEl,
+      dir,
+      maxDepth - 1
+    );
+    if (scrollableElement) return scrollableElement;
+  } else {
+    for (let index = 0; index < element.childElementCount; index += 1) {
+      const currentChild = element.children.item(index);
+      const scrollableElement = findScrollableElement(
+        currentChild,
+        dir,
+        maxDepth - 1
+      );
+
+      if (scrollableElement) return scrollableElement;
+    }
+  }
+
+  return null;
+}
+
 function elementScroll(block) {
   function incScrollPos(element, data, vertical = true) {
     let currentPos = vertical ? element.scrollTop : element.scrollLeft;
@@ -22,7 +71,12 @@ function elementScroll(block) {
         if (data.scrollIntoView) {
           element.scrollIntoView({ behavior, block: 'center' });
         } else {
-          element.scroll({
+          const scrollableEl =
+            findScrollableElement(element, 'up', 3) ||
+            findScrollableElement(element, 'down', 3) ||
+            element;
+
+          scrollableEl.scroll({
             behavior,
             top: data.incY ? incScrollPos(element, data) : data.scrollY,
             left: data.incX ? incScrollPos(element, data, false) : data.scrollX,