tor-browser

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

scroll-behavior.js (3121B)


      1 // TODO(crbug.com/888443): It would be better to listen to the scrollend event
      2 // instead of polling the scroll position.
      3 function observeScrolling(elements, callback) {
      4  if (!Array.isArray(elements))
      5      elements = [elements];
      6  var lastChangedFrame = 0;
      7  var lastLeft = new Map();
      8  var lastTop = new Map();
      9  elements.forEach((element) => {
     10    lastLeft.set(element, element.scrollLeft);
     11    lastTop.set(element, element.scrollTop);
     12  });
     13  function tick(frames) {
     14    // We requestAnimationFrame either for 5000 frames or until 20 frames with
     15    // no change have been observed. (In Chromium, frames may run as frequently
     16    // as once per millisecond when threaded compositing is disabled. The limit
     17    // of 5000 frames is chosen to be high enough to reasonably ensure any
     18    // scroll animation will run to completion.)
     19    if (frames >= 5000 || frames - lastChangedFrame > 20) {
     20      callback(true);
     21    } else {
     22      var scrollHappened = elements.some((element) => {
     23        return element.scrollLeft != lastLeft.get(element) || element.scrollTop != lastTop.get(element);
     24      });
     25      if (scrollHappened) {
     26        lastChangedFrame = frames;
     27        elements.forEach((element) => {
     28          lastLeft.set(element, element.scrollLeft);
     29          lastTop.set(element, element.scrollTop);
     30        });
     31        callback(false);
     32      }
     33      requestAnimationFrame(tick.bind(null, frames + 1));
     34    }
     35  }
     36  tick(0);
     37 }
     38 
     39 function waitForScrollEnd(elements) {
     40  return new Promise((resolve) => {
     41    observeScrolling(elements, (done) => {
     42      if (done)
     43        resolve();
     44    });
     45  });
     46 }
     47 
     48 function resetScroll(scrollingElement) {
     49  // Try various methods to ensure the element position is reset immediately.
     50  scrollingElement.scrollLeft = 0;
     51  scrollingElement.scrollTop = 0;
     52  scrollingElement.scroll({left: 0, top: 0, behavior: "instant"});
     53 }
     54 
     55 function resetScrollForWindow(scrollingWindow) {
     56  // Try various methods to ensure the element position is reset immediately.
     57  scrollingWindow.document.scrollingElement.scrollLeft = 0;
     58  scrollingWindow.document.scrollingElement.scrollTop = 0;
     59  scrollingWindow.scroll({left: 0, top: 0, behavior: "instant"});
     60 }
     61 
     62 function setScrollBehavior(styledElement, className) {
     63  styledElement.classList.remove("autoBehavior", "smoothBehavior");
     64  styledElement.classList.add(className);
     65 }
     66 
     67 function scrollNode(scrollingElement, scrollFunction, behavior, elementToRevealLeft, elementToRevealTop) {
     68  var args = {};
     69  if (behavior)
     70    args.behavior = behavior;
     71  switch (scrollFunction) {
     72    case "scrollIntoView":
     73      args.inline = "start";
     74      args.block = "start";
     75      elementToReveal.scrollIntoView(args);
     76      break;
     77    default:
     78      args.left = elementToRevealLeft;
     79      args.top = elementToRevealTop;
     80      scrollingElement[scrollFunction](args);
     81      break;
     82  }
     83 }
     84 
     85 function scrollWindow(scrollingWindow, scrollFunction, behavior, elementToRevealLeft, elementToRevealTop) {
     86  var args = {};
     87  if (behavior)
     88    args.behavior = behavior;
     89  args.left = elementToRevealLeft;
     90  args.top = elementToRevealTop;
     91  scrollingWindow[scrollFunction](args);
     92 }