text: Polymer.AppLayout = Polymer.AppLayout || {};
  
    Polymer.AppLayout._scrollEffects = Polymer.AppLayout._scrollEffects || {};
  
    Polymer.AppLayout.scrollTimingFunction = function easeOutQuad(t, b, c, d) {
      t /= d;
      return -c * t*(t-2) + b;
    };
  
    /**
     * Registers a scroll effect to be used in elements that implement the
     * `Polymer.AppScrollEffectsBehavior` behavior.
     *
     * @param {string} effectName The effect name.
     * @param {Object} effectDef The effect definition.
     */
    Polymer.AppLayout.registerEffect = function registerEffect(effectName, effectDef) {
      if (Polymer.AppLayout._scrollEffects[effectName] != null) {
        throw new Error('effect `'+ effectName + '` is already registered.');
      }
      Polymer.AppLayout._scrollEffects[effectName] = effectDef;
    };
  
    /**
     * Scrolls to a particular set of coordinates in a scroll target.
     * If the scroll target is not defined, then it would use the main document as the target.
     *
     * To scroll in a smooth fashion, you can set the option `behavior: 'smooth'`. e.g.
     *
     * ```js
     * Polymer.AppLayout.scroll({top: 0, behavior: 'smooth'});
     * ```
     *
     * To scroll in a silent mode, without notifying scroll changes to any app-layout elements,
     * you can set the option `behavior: 'silent'`. This is particularly useful we you are using
     * `app-header` and you desire to scroll to the top of a scrolling region without running
     * scroll effects. e.g.
     *
     * ```js
     * Polymer.AppLayout.scroll({top: 0, behavior: 'silent'});
     * ```
     *
     * @param {Object} options {top: Number, left: Number, behavior: String(smooth | silent)}
     */
    Polymer.AppLayout.scroll = function scroll(options) {
      options = options || {};
  
      var docEl = document.documentElement;
      var target = options.target || docEl;
      var hasNativeScrollBehavior = 'scrollBehavior' in target.style && target.scroll;
      var scrollClassName = 'app-layout-silent-scroll';
      var scrollTop = options.top || 0;
      var scrollLeft = options.left || 0;
      var scrollTo = target === docEl ? window.scrollTo :
        function scrollTo(scrollLeft, scrollTop) {
          target.scrollLeft = scrollLeft;
          target.scrollTop = scrollTop;
        };
  
      if (options.behavior === 'smooth') {
  
        if (hasNativeScrollBehavior) {
  
          target.scroll(options);
  
        } else {
  
          var timingFn = Polymer.AppLayout.scrollTimingFunction;
          var startTime = Date.now();
          var currentScrollTop = target === docEl ? window.pageYOffset : target.scrollTop;
          var currentScrollLeft = target === docEl ? window.pageXOffset : target.scrollLeft;
          var deltaScrollTop = scrollTop - currentScrollTop;
          var deltaScrollLeft = scrollLeft - currentScrollLeft;
          var duration = 300;
          var updateFrame = (function updateFrame() {
            var now = Date.now();
            var elapsedTime = now - startTime;
  
            if (elapsedTime < duration) {
              scrollTo(timingFn(elapsedTime, currentScrollLeft, deltaScrollLeft, duration),
                  timingFn(elapsedTime, currentScrollTop, deltaScrollTop, duration));
              requestAnimationFrame(updateFrame);
            } else {
              scrollTo(scrollLeft, scrollTop);
            }
          }).bind(this);
          
          updateFrame();
        }
  
      } else if (options.behavior === 'silent') {
  
        docEl.classList.add(scrollClassName);
  
        // Browsers keep the scroll momentum even if the bottom of the scrolling content
        // was reached. This means that calling scroll({top: 0, behavior: 'silent'}) when
        // the momentum is still going will result in more scroll events and thus scroll effects.
        // This seems to only apply when using document scrolling.
        // Therefore, when should we remove the class from the document element?
  
        clearInterval(Polymer.AppLayout._scrollTimer);
  
        Polymer.AppLayout._scrollTimer = setTimeout(function() {
          docEl.classList.remove(scrollClassName);
          Polymer.AppLayout._scrollTimer = null;
        }, 100);
  
        scrollTo(scrollLeft, scrollTop);
  
      } else {
  
        scrollTo(scrollLeft, scrollTop);
  
      }
    };