Code coverage report for src/components/scroll-to.cjsx

Statements: 77.14% (54 / 70)      Branches: 35% (14 / 40)      Functions: 80% (12 / 15)      Lines: 77.14% (54 / 70)      Ignored: none     

All files » src/components/ » scroll-to.cjsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126                                           19× 19× 19× 19×   19×     19× 19×                                                                                                
var DEFAULT_DURATION, DEFAULT_TOP_OFFSET, EASE_IN_OUT, GetPositionMixin, MAXIMUM_SCROLL_ATTEMPTS, POSITION, React, ScrollTo, _;
 
React = require('react');
 
_ = require('underscore');
 
GetPositionMixin = require('openstax-react-components').GetPositionMixin;
 
DEFAULT_DURATION = 750;
 
DEFAULT_TOP_OFFSET = 80;
 
MAXIMUM_SCROLL_ATTEMPTS = 3;
 
EASE_IN_OUT = function(t) {
  Eif (t < .5) {
    return 4 * t * t * t;
  } else {
    return (t - 1) * (2 * t - 2) * (2 * t - 2) + 1;
  }
};
 
POSITION = function(start, end, elapsed, duration) {
  Iif (elapsed > duration) {
    return end;
  }
  return start + (end - start) * EASE_IN_OUT(elapsed / duration);
};
 
ScrollTo = {
  getDefaultProps: function() {
    return {
      windowImpl: window
    };
  },
  componentDidMount: function() {
    var hash;
    React.findDOMNode(this).addEventListener('click', this._onScrollClick, false);
    hash = this.props.windowImpl.location.hash;
    if (hash) {
      this.props.windowImpl.location.hash = "";
      (typeof this.waitToScrollToSelector === "function" ? this.waitToScrollToSelector(hash) : void 0) || this.scrollToSelector(hash);
    }
    return this.props.windowImpl.addEventListener('hashchange', this._onHashChange, false);
  },
  componentWillUnmount: function() {
    React.findDOMNode(this).removeEventListener('click', this._onScrollClick, false);
    return this.props.windowImpl.removeEventListener('hashchange', this._onHashChange, false);
  },
  scrollToSelector: function(selector) {
    var el, root;
    Iif (_.isEmpty(selector)) {
      return;
    }
    root = React.findDOMNode(this);
    el = root.querySelector(selector);
    Eif (el) {
      return this.scrollToElement(el);
    }
  },
  _onHashChange: function() {
    Eif (this.props.windowImpl.location.hash) {
      return this.scrollToSelector(this.props.windowImpl.location.hash);
    }
  },
  _onScrollClick: function(ev) {
    if (ev.target.tagName !== 'A') {
      return;
    }
    if (this.scrollToSelector(ev.target.hash)) {
      return ev.preventDefault();
    }
  },
  _desiredTopPosition: function(el) {
    return GetPositionMixin.getTopPosition(el) - _.result(this, 'getScrollTopOffset', DEFAULT_TOP_OFFSET);
  },
  _onBeforeScroll: function(el) {
    el.classList.add('target-scroll');
    return typeof this.onBeforeScroll === "function" ? this.onBeforeScroll(el) : void 0;
  },
  _onAfterScroll: function(el) {
    var ref;
    if (el != null ? (ref = el.classList) != null ? ref.contains('target-scroll') : void 0 : void 0) {
      _.delay(el.classList.remove.bind(el.classList, 'target-scroll'), 150);
    }
    this.props.windowImpl.history.pushState(null, null, "#" + el.id);
    return typeof this.onAfterScroll === "function" ? this.onAfterScroll(el) : void 0;
  },
  _onScrollStep: function(el, attemptNumber) {
    if (attemptNumber < MAXIMUM_SCROLL_ATTEMPTS && this.props.windowImpl.pageYOffset !== this._desiredTopPosition(el)) {
      return this.scrollToElement(el, attemptNumber + 1);
    } else {
      return this._onAfterScroll(el);
    }
  },
  scrollToElement: function(el, attemptNumber) {
    var duration, endPos, requestAnimationFrame, startPos, startTime, step, win;
    Eif (attemptNumber == null) {
      attemptNumber = 0;
    }
    win = this.props.windowImpl;
    startPos = win.pageYOffset;
    endPos = this._desiredTopPosition(el);
    startTime = Date.now();
    duration = _.result(this, 'getScrollDuration', DEFAULT_DURATION);
    requestAnimationFrame = win.requestAnimationFrame || _.defer;
    step = (function(_this) {
      return function() {
        var elapsed;
        elapsed = Date.now() - startTime;
        win.scroll(0, POSITION(startPos, endPos, elapsed, duration));
        Eif (elapsed < duration) {
          return requestAnimationFrame(step);
        } else {
          return _this._onScrollStep(el, attemptNumber);
        }
      };
    })(this);
    this._onBeforeScroll(el);
    return step();
  }
};
 
module.exports = ScrollTo;