tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

scroll-markers-updated-by-programmatic-scroll.html (4778B)


      1 <!DOCTYPE html>
      2 <meta charset="utf-8">
      3 <title>CSS Test: scroll tracking for ::scroll-marker </title>
      4 <link rel="help" href="https://drafts.csswg.org/css-overflow-5/#scroll-container-scroll">
      5 <script src="/resources/testharness.js"></script>
      6 <script src="/resources/testharnessreport.js"></script>
      7 <script src="/css/css-transitions/support/helper.js"></script>
      8 <script src="/dom/events/scrolling/scroll_support.js"></script>
      9 <style>
     10  #scroller {
     11    overflow: scroll;
     12    scroll-marker-group: before;
     13    height: 100px;
     14    scroll-behavior: smooth;
     15    background-color: purple;
     16    border: solid 1px black;
     17  }
     18 
     19  #scroller::scroll-marker-group {
     20    border: 3px solid black;
     21    display: flex;
     22    width: 100px;
     23    height: 20px;
     24  }
     25 
     26  #scroller div {
     27    width: 100px;
     28    height: 100px;
     29  }
     30 
     31  #scroller div::scroll-marker {
     32    content: '';
     33    background-color: red;
     34    display: inline-flex;
     35    width: 10px;
     36    height: 10px;
     37    border-radius: 50%;
     38  }
     39 
     40  #scroller div::scroll-marker:target-current {
     41    background-color: green;
     42  }
     43 </style>
     44 <div id='scroller'>
     45  <div id="initial"></div>
     46  <div class="inbetween"></div>
     47  <div class="inbetween"></div>
     48  <div class="inbetween"></div>
     49  <div id='target'></div>
     50 </div>
     51 <script>
     52  const inbetweens = scroller.querySelectorAll(".inbetween");
     53  const GREEN = "rgb(0, 128, 0)";
     54  const RED = "rgb(255, 0, 0)";
     55 
     56  function assertPseudoElementProperty(originatingElement, pseudoType, backgroundColor) {
     57    const pseudoStyle = getComputedStyle(originatingElement, pseudoType);
     58    const pseudoBackgroundColor = pseudoStyle.getPropertyValue('background-color');
     59    assert_equals(pseudoBackgroundColor, backgroundColor, pseudoType +
     60      " background-color should be " + backgroundColor.toString() +
     61      " but was " + pseudoBackgroundColor.toString());
     62  }
     63 
     64  let marker_change_observed = false;
     65  function watchFrames() {
     66    const initialPseudoStyle = getComputedStyle(initial, "::scroll-marker");
     67    const initialPseudoBackgroundColor =
     68      initialPseudoStyle.getPropertyValue('background-color');
     69 
     70    if (initialPseudoBackgroundColor === RED) {
     71      marker_change_observed = true;
     72    } else {
     73      assert_false(marker_change_observed);
     74      assert_equals(initialPseudoBackgroundColor, GREEN,
     75        "initial scroll-marker is initially green");
     76    }
     77 
     78    // All the markers in between should always be red.
     79    for (const inbetween of inbetweens) {
     80      assertPseudoElementProperty(inbetween, "::scroll-marker", RED);
     81    }
     82 
     83    // target should become and stay the selected scroll-marker.
     84    assertPseudoElementProperty(target, "::scroll-marker",
     85      marker_change_observed ? GREEN : RED);
     86 
     87    requestAnimationFrame(watchFrames);
     88  }
     89 
     90  function scrollPromise() {
     91    return new Promise((resolve) => {
     92      // For browsers that don't support the scrollend event, just wait till
     93      // at least half the expected scroll is done.
     94      if (document.scrollingElement.onscrollend === undefined) {
     95        function scrollListener() {
     96          const max_scroll_offset =
     97            scroller.scrollHeight - scroller.ClientHeight;
     98          if (scroller.scrollTop >= max_scroll_offset / 2) {
     99            scroller.removeEventListener(scrollListener);
    100            resolve();
    101          }
    102        }
    103        scroller.addEventListener("scroll", scrollListener);
    104      } else {
    105        function scrollEndListener() {
    106          scroller.removeEventListener("scrollend", scrollEndListener);
    107          resolve();
    108        }
    109        scroller.addEventListener("scrollend", scrollEndListener);
    110      }
    111    });
    112  };
    113 
    114  promise_test(async (t) => {
    115    await waitForAnimationFrames(2);
    116    assertPseudoElementProperty(initial, "::scroll-marker", GREEN);
    117    assertPseudoElementProperty(target, "::scroll-marker", RED);
    118 
    119    function changeDivWidths() {
    120      const WIDTH1 = "100px";
    121      const WIDTH2 = "200px";
    122      const divs = scroller.querySelectorAll("div");
    123      const current_width = divs[0].style.width;
    124      const target_width = current_width === WIDTH1 ? WIDTH2 : WIDTH1;
    125      divs.forEach(div => { div.style.width = target_width; });
    126    }
    127 
    128    // Add a scroll listener which will trigger a layout change.
    129    // Despite the layout change, the user agent should only select
    130    // the eventual scroll position of the ongoing smooth scrollIntoView.
    131    scroller.addEventListener("scroll", changeDivWidths);
    132 
    133    const scroll_promise = scrollPromise();
    134    watchFrames();
    135    target.scrollIntoView({ behavior: "smooth" });
    136    await scroll_promise;
    137 
    138    assertPseudoElementProperty(initial, "::scroll-marker", RED);
    139    assertPseudoElementProperty(target, "::scroll-marker", GREEN);
    140  }, "The selected ::scroll-marker is updated using the eventual scroll " +
    141  "position for a programmatic scroll");
    142 </script>