function _(props) {
_classCallCheck(this, _);
var _this = _possibleConstructorReturn(this, (_.__proto__ || Object.getPrototypeOf(_)).call(this, props));
_this.scrollTo = _this.scrollTo.bind(_this);
_this.handleClick = _this.handleClick.bind(_this);
_this.spyHandler = _this.spyHandler.bind(_this);
return _this;
}n/a
function _(props) {
_classCallCheck(this, _);
var _this2 = _possibleConstructorReturn(this, (_.__proto__ || Object.getPrototypeOf(_)).call(this, props));
_this2.registerElems = _this2.registerElems.bind(_this2);
return _this2;
}...
<div {...this.props}>
{this.props.children}
</div>
);
}
});
module.exports = Helpers.Element(Element);
var Link = React.createClass({
render: function () {
return (
<a {...this.props}>
{this.props.children}
</a>
...function _(props) {
_classCallCheck(this, _);
var _this = _possibleConstructorReturn(this, (_.__proto__ || Object.getPrototypeOf(_)).call(this, props));
_this.scrollTo = _this.scrollTo.bind(_this);
_this.handleClick = _this.handleClick.bind(_this);
_this.spyHandler = _this.spyHandler.bind(_this);
return _this;
}n/a
function Element(Component) {
var _ = function (_React$Component2) {
_inherits(_, _React$Component2);
function _(props) {
_classCallCheck(this, _);
var _this2 = _possibleConstructorReturn(this, (_.__proto__ || Object.getPrototypeOf(_)).call(this, props));
_this2.registerElems = _this2.registerElems.bind(_this2);
return _this2;
}
_createClass(_, [{
key: 'componentDidMount',
value: function componentDidMount() {
this.registerElems(this.props.name);
}
}, {
key: 'componentWillReceiveProps',
value: function componentWillReceiveProps(nextProps) {
if (this.props.name !== nextProps.name) {
this.registerElems(nextProps.name);
}
}
}, {
key: 'componentWillUnmount',
value: function componentWillUnmount() {
defaultScroller.unregister(this.props.name);
}
}, {
key: 'registerElems',
value: function registerElems(name) {
var domNode = ReactDOM.findDOMNode(this);
defaultScroller.register(name, domNode);
}
}, {
key: 'render',
value: function render() {
return React.createElement(Component, this.props);
}
}]);
return _;
}(React.Component);
;
_.propTypes = {
name: PropTypes.string,
id: PropTypes.string
};
return _;
}...
<div {...this.props}>
{this.props.children}
</div>
);
}
});
module.exports = Helpers.Element(Element);
var Link = React.createClass({
render: function () {
return (
<a {...this.props}>
{this.props.children}
</a>
...function Scroll(Component, customScroller) {
var scroller = customScroller || defaultScroller;
var _ = function (_React$Component) {
_inherits(_, _React$Component);
function _(props) {
_classCallCheck(this, _);
var _this = _possibleConstructorReturn(this, (_.__proto__ || Object.getPrototypeOf(_)).call(this, props));
_this.scrollTo = _this.scrollTo.bind(_this);
_this.handleClick = _this.handleClick.bind(_this);
_this.spyHandler = _this.spyHandler.bind(_this);
return _this;
}
_createClass(_, [{
key: 'scrollTo',
value: function scrollTo(to, props) {
scroller.scrollTo(to, props);
}
}, {
key: 'handleClick',
value: function handleClick(event) {
/*
* give the posibility to override onClick
*/
if (this.props.onClick) {
this.props.onClick(event);
}
/*
* dont bubble the navigation
*/
if (event.stopPropagation) event.stopPropagation();
if (event.preventDefault) event.preventDefault();
/*
* do the magic!
*/
this.scrollTo(this.props.to, this.props);
}
}, {
key: 'spyHandler',
value: function spyHandler(y) {
var element = scroller.get(this.props.to);
if (!element) return;
var cords = element.getBoundingClientRect();
var topBound = cords.top + y;
var bottomBound = topBound + cords.height;
var offsetY = y - this.props.offset;
var to = this.props.to;
var isInside = offsetY >= topBound && offsetY <= bottomBound;
var isOutside = offsetY < topBound || offsetY > bottomBound;
var activeLink = scroller.getActiveLink();
if (isOutside && activeLink === to) {
scroller.setActiveLink(void 0);
this.setState({ active: false });
if (this.props.onSetInactive) {
this.props.onSetInactive();
}
} else if (isInside && activeLink != to) {
scroller.setActiveLink(to);
this.setState({ active: true });
if (this.props.onSetActive) {
this.props.onSetActive(to);
}
scrollSpy.updateStates();
}
}
}, {
key: 'componentDidMount',
value: function componentDidMount() {
var containerId = this.props.containerId;
var scrollSpyContainer = containerId ? document.getElementById(containerId) : document;
if (!scrollSpy.isMounted(scrollSpyContainer)) {
scrollSpy.mount(scrollSpyContainer);
}
if (this.props.spy) {
var to = this.props.to;
var element = null;
var elemTopBound = 0;
var elemBottomBound = 0;
this._stateHandler = function () {
if (scroller.getActiveLink() != to) {
if (this.state !== null && this.state.active && this.props.onSetInactive) {
this.props.onSetInactive();
}
this.setState({ active: false });
}
}.bind(this);
scrollSpy.addStateHandler(this._stateHandler);
this._spyHandler = function (y) {
var containerTop = 0;
if (scrollSpyContainer.getBoundingClientRect) {
var containerCords = scrollSpyContainer.getBoundingClientRect();
containerTop = containerCords.top;
}
if (!element || this.props.isDynamic) {
element = scroller.get(to);
if (!element) {
return;
}
var cords = element.getBoundingClientRect();
elemTopBound = cords.top - containerTop + y;
elemBottomBound = elemTopBound + cords.height;
}
var offsetY = y - this.props.offset;
var isInside = offsetY >= Math.floor(elemTopBound) && offsetY <= Math.floor(elemBottomBound);
var isOutside = offsetY < Math.floor(elemTopBound) || offsetY > Math.floor(elemBottomBound);
var active ......
<a {...this.props}>
{this.props.children}
</a>
);
}
});
module.exports = Helpers.Scroll(Link);
```
### Scroll Animations
> Add a custom easing animation to the smooth option. This prop will accept a Boolean if you want the default, or any of the
animations listed below
...function startAnimateTopScroll(y, options, to, target) {
window.clearTimeout(__delayTimeout);
if (!options.ignoreCancelEvents) {
/*
* Sets the cancel trigger
*/
cancelEvents.register(function () {
__cancel = true;
});
}
setContainer(options);
__start = null;
__cancel = false;
__startPositionY = currentPositionY();
__targetPositionY = options.absolute ? y : y + __startPositionY;
__deltaTop = Math.round(__targetPositionY - __startPositionY);
__duration = functionWrapper(options.duration)(__deltaTop);
__duration = isNaN(parseFloat(__duration)) ? 1000 : parseFloat(__duration);
__to = to;
__target = target;
var easing = getAnimationType(options);
var easedAnimate = animateTopScroll.bind(null, easing);
if (options && options.delay > 0) {
__delayTimeout = window.setTimeout(function animate() {
requestAnimationFrameHelper.call(window, easedAnimate);
}, options.delay);
return;
}
requestAnimationFrameHelper.call(window, easedAnimate);
}...
return;
}
/*
* Animate scrolling
*/
animateScroll.animateTopScroll(scrollOffset, props, to, target);
}
};
...function getAnimationType(options) {
if (_typeof(options.smooth) === Boolean && options.smooth === true) {
return smooth.defaultEasing;
} else {
var animationType = options.smooth;
switch (animationType) {
case "linear":
return smooth.linear;
case "easeInQuad":
return smooth.easeInQuad;
case "easeOutQuad":
return smooth.easeOutQuad;
case "easeInOutQuad":
return smooth.easeInOutQuad;
case "easeInCubic":
return smooth.easeInCubic;
case "easeOutCubic":
return smooth.easeOutQuad;
case "easeInOutCubic":
return smooth.easeInQuad;
case "easeInQuart":
return smooth.easeInQuart;
case "easeOutQuart":
return smooth.easeOutQuart;
case "easeInOutQuart":
return smooth.easeInOutQuart;
case "easeInQuint":
return smooth.easeInQuint;
case "easeOutQuint":
return smooth.easeInQuint;
case "easeInOutQuint":
return smooth.easeInOutQuint;
default:
return smooth.defaultEasing;
}
}
}...
var _smooth2 = _interopRequireDefault(_smooth);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
describe('AnimationTypeUnitTests', function () {
it('chooses correct easing function with no smooth options', function () {
var animation = _animateScroll2.default.getAnimationType({});
(0, _expect2.default)(animation).toEqual(_smooth2.default.defaultEasing);
});
it('chooses correct easing function for smooth: true', function () {
var animation = _animateScroll2.default.getAnimationType({ smooth: true });
(0, _expect2.default)(animation).toEqual(_smooth2.default.defaultEasing);
});
...function scrollMore(toY, options) {
setContainer(options);
startAnimateTopScroll(currentPositionY() + toY, assign(options || {}, { absolute: true }));
}...
scrollToBottom: function() {
scroll.scrollToBottom();
},
scrollTo: function() {
scroll.scrollTo(100);
},
scrollMore: function() {
scroll.scrollMore(100);
},
handleSetActive: function(to) {
console.log(to);
},
render: function () {
return (
<div>
...function scrollTo(toY, options) {
startAnimateTopScroll(toY, assign(options || {}, { absolute: true }));
}...
scrollToTop: function() {
scroll.scrollToTop();
},
scrollToBottom: function() {
scroll.scrollToBottom();
},
scrollTo: function() {
scroll.scrollTo(100);
},
scrollMore: function() {
scroll.scrollMore(100);
},
handleSetActive: function(to) {
console.log(to);
},
...function scrollToBottom(options) {
setContainer(options);
startAnimateTopScroll(scrollContainerHeight(), assign(options || {}, { absolute: true }));
}...
Events.scrollEvent.remove('begin');
Events.scrollEvent.remove('end');
},
scrollToTop: function() {
scroll.scrollToTop();
},
scrollToBottom: function() {
scroll.scrollToBottom();
},
scrollTo: function() {
scroll.scrollTo(100);
},
scrollMore: function() {
scroll.scrollMore(100);
},
...function scrollToTop(options) {
startAnimateTopScroll(0, assign(options || {}, { absolute: true }));
}...
},
componentWillUnmount: function() {
Events.scrollEvent.remove('begin');
Events.scrollEvent.remove('end');
},
scrollToTop: function() {
scroll.scrollToTop();
},
scrollToBottom: function() {
scroll.scrollToBottom();
},
scrollTo: function() {
scroll.scrollTo(100);
},
...function addSpyHandler(handler, scrollSpyContainer) {
var container = this.scrollSpyContainers[this.scrollSpyContainers.indexOf(scrollSpyContainer)];
if (!container.spyCallbacks) {
container.spyCallbacks = [];
}
container.spyCallbacks.push(handler);
}...
this.props.onSetActive(to);
}
scrollSpy.updateStates();
}
}.bind(this);
scrollSpy.addSpyHandler(this._spyHandler, scrollSpyContainer);
}
}
}, {
key: 'componentWillUnmount',
value: function componentWillUnmount() {
scrollSpy.unmount(this._stateHandler, this._spyHandler);
}
...function addStateHandler(handler) {
this.spySetState.push(handler);
}...
if (this.state !== null && this.state.active && this.props.onSetInactive) {
this.props.onSetInactive();
}
this.setState({ active: false });
}
}.bind(this);
scrollSpy.addStateHandler(this._stateHandler);
this._spyHandler = function (y) {
var containerTop = 0;
if (scrollSpyContainer.getBoundingClientRect) {
var containerCords = scrollSpyContainer.getBoundingClientRect();
containerTop = containerCords.top;
...function currentPositionY(scrollSpyContainer) {
if (scrollSpyContainer === document) {
var supportPageOffset = window.pageXOffset !== undefined;
var isCSS1Compat = (document.compatMode || "") === "CSS1Compat";
return supportPageOffset ? window.pageYOffset : isCSS1Compat ? document.documentElement.scrollTop : document.body.scrollTop;
} else {
return scrollSpyContainer.scrollTop;
}
}...
}
},
scrollHandler: function scrollHandler(scrollSpyContainer) {
var callbacks = this.scrollSpyContainers[this.scrollSpyContainers.indexOf(scrollSpyContainer)].spyCallbacks;
if (callbacks) {
for (var i = 0; i < callbacks.length; i++) {
var position = this.currentPositionY(scrollSpyContainer);
callbacks[i](this.currentPositionY(scrollSpyContainer));
}
}
},
addStateHandler: function addStateHandler(handler) {
this.spySetState.push(handler);
...function isMounted(scrollSpyContainer) {
return this.scrollSpyContainers.indexOf(scrollSpyContainer) !== -1;
}...
key: 'componentDidMount',
value: function componentDidMount() {
var containerId = this.props.containerId;
var scrollSpyContainer = containerId ? document.getElementById(containerId) : document;
if (!scrollSpy.isMounted(scrollSpyContainer)) {
scrollSpy.mount(scrollSpyContainer);
}
if (this.props.spy) {
var to = this.props.to;
var element = null;
var elemTopBound = 0;
...function mount(scrollSpyContainer) {
var t = this;
if (scrollSpyContainer) {
var eventHandler = eventThrottler(function (event) {
t.scrollHandler(scrollSpyContainer);
});
this.scrollSpyContainers.push(scrollSpyContainer);
addPassiveEventListener(scrollSpyContainer, 'scroll', eventHandler);
}
}...
value: function componentDidMount() {
var containerId = this.props.containerId;
var scrollSpyContainer = containerId ? document.getElementById(containerId) : document;
if (!scrollSpy.isMounted(scrollSpyContainer)) {
scrollSpy.mount(scrollSpyContainer);
}
if (this.props.spy) {
var to = this.props.to;
var element = null;
var elemTopBound = 0;
var elemBottomBound = 0;
...function scrollHandler(scrollSpyContainer) {
var callbacks = this.scrollSpyContainers[this.scrollSpyContainers.indexOf(scrollSpyContainer)].spyCallbacks;
if (callbacks) {
for (var i = 0; i < callbacks.length; i++) {
var position = this.currentPositionY(scrollSpyContainer);
callbacks[i](this.currentPositionY(scrollSpyContainer));
}
}
}...
spySetState: [],
scrollSpyContainers: [],
mount: function mount(scrollSpyContainer) {
var t = this;
if (scrollSpyContainer) {
var eventHandler = eventThrottler(function (event) {
t.scrollHandler(scrollSpyContainer);
});
this.scrollSpyContainers.push(scrollSpyContainer);
addPassiveEventListener(scrollSpyContainer, 'scroll', eventHandler);
}
},
isMounted: function isMounted(scrollSpyContainer) {
...function unmount(stateHandler, spyHandler) {
for (var i = 0; i < this.scrollSpyContainers.length; i++) {
var callbacks = this.scrollSpyContainers[i].spyCallbacks;
if (callbacks && callbacks.length) {
callbacks.splice(callbacks.indexOf(spyHandler), 1);
}
}
if (this.spySetState && this.spySetState.length) {
this.spySetState.splice(this.spySetState.indexOf(stateHandler), 1);
}
document.removeEventListener('scroll', this.scrollHandler);
}...
scrollSpy.addSpyHandler(this._spyHandler, scrollSpyContainer);
}
}
}, {
key: 'componentWillUnmount',
value: function componentWillUnmount() {
scrollSpy.unmount(this._stateHandler, this._spyHandler);
}
}, {
key: 'render',
value: function render() {
var className = "";
if (this.state && this.state.active) {
...function update() {
for (var i = 0; i < this.scrollSpyContainers.length; i++) {
this.scrollHandler(this.scrollSpyContainers[i]);
}
}...
console.log("begin", arguments);
});
Events.scrollEvent.register('end', function(to, element) {
console.log("end", arguments);
});
scrollSpy.update();
},
componentWillUnmount: function() {
Events.scrollEvent.remove('begin');
Events.scrollEvent.remove('end');
},
scrollToTop: function() {
...function updateStates() {
var length = this.spySetState.length;
for (var i = 0; i < length; i++) {
this.spySetState[i]();
}
}...
scroller.setActiveLink(to);
this.setState({ active: true });
if (this.props.onSetActive) {
this.props.onSetActive(to);
}
scrollSpy.updateStates();
}
}
}, {
key: 'componentDidMount',
value: function componentDidMount() {
var containerId = this.props.containerId;
...function get(name) {
return __mapped[name] || document.getElementById(name);
}...
* do the magic!
*/
this.scrollTo(this.props.to, this.props);
}
}, {
key: 'spyHandler',
value: function spyHandler(y) {
var element = scroller.get(this.props.to);
if (!element) return;
var cords = element.getBoundingClientRect();
var topBound = cords.top + y;
var bottomBound = topBound + cords.height;
var offsetY = y - this.props.offset;
var to = this.props.to;
var isInside = offsetY >= topBound && offsetY <= bottomBound;
...function getActiveLink() {
return __activeLink;
}...
var cords = element.getBoundingClientRect();
var topBound = cords.top + y;
var bottomBound = topBound + cords.height;
var offsetY = y - this.props.offset;
var to = this.props.to;
var isInside = offsetY >= topBound && offsetY <= bottomBound;
var isOutside = offsetY < topBound || offsetY > bottomBound;
var activeLink = scroller.getActiveLink();
if (isOutside && activeLink === to) {
scroller.setActiveLink(void 0);
this.setState({ active: false });
if (this.props.onSetInactive) {
this.props.onSetInactive();
...function register(name, element) {
__mapped[name] = element;
}...
var scroll = Scroll.animateScroll;
var scrollSpy = Scroll.scrollSpy;
var Section = React.createClass({
componentDidMount: function() {
Events.scrollEvent.register('begin', function(to, element) {
console.log("begin", arguments);
});
Events.scrollEvent.register('end', function(to, element) {
console.log("end", arguments);
});
...function scrollTo(to, props) {
/*
* get the mapped DOM element
*/
var target = this.get(to);
if (!target) {
console.warn("target Element not found");
return;
}
props = assign({}, props, { absolute: false });
if (events.registered['begin']) {
events.registered['begin'](to, target);
}
var containerId = props.containerId;
var containerElement = containerId ? document.getElementById(containerId) : null;
var scrollOffset;
if (containerId && containerElement) {
props.absolute = true;
if (containerElement !== target.offsetParent) {
if (!containerElement.contains(target)) {
throw new Error('Container with ID ' + containerId + ' is not a parent of target ' + to);
} else {
throw new Error('Container with ID ' + containerId + ' is not a positioned element');
}
}
scrollOffset = target.offsetTop;
} else {
var coordinates = target.getBoundingClientRect();
scrollOffset = coordinates.top;
}
scrollOffset += props.offset || 0;
/*
* if animate is not provided just scroll into the view
*/
if (!props.smooth) {
if (containerId && containerElement) {
containerElement.scrollTop = scrollOffset;
} else {
// window.scrollTo accepts only absolute values so body rectangle needs to be subtracted
var bodyRect = document.body.getBoundingClientRect();
window.scrollTo(0, scrollOffset - bodyRect.top);
}
if (events.registered['end']) {
events.registered['end'](to, target);
}
return;
}
/*
* Animate scrolling
*/
animateScroll.animateTopScroll(scrollOffset, props, to, target);
}...
scrollToTop: function() {
scroll.scrollToTop();
},
scrollToBottom: function() {
scroll.scrollToBottom();
},
scrollTo: function() {
scroll.scrollTo(100);
},
scrollMore: function() {
scroll.scrollMore(100);
},
handleSetActive: function(to) {
console.log(to);
},
...function setActiveLink(link) {
__activeLink = link;
}...
var offsetY = y - this.props.offset;
var to = this.props.to;
var isInside = offsetY >= topBound && offsetY <= bottomBound;
var isOutside = offsetY < topBound || offsetY > bottomBound;
var activeLink = scroller.getActiveLink();
if (isOutside && activeLink === to) {
scroller.setActiveLink(void 0);
this.setState({ active: false });
if (this.props.onSetInactive) {
this.props.onSetInactive();
}
} else if (isInside && activeLink != to) {
scroller.setActiveLink(to);
...function unmount() {
__mapped = {};
}...
scrollSpy.addSpyHandler(this._spyHandler, scrollSpyContainer);
}
}
}, {
key: 'componentWillUnmount',
value: function componentWillUnmount() {
scrollSpy.unmount(this._stateHandler, this._spyHandler);
}
}, {
key: 'render',
value: function render() {
var className = "";
if (this.state && this.state.active) {
...function unregister(name) {
delete __mapped[name];
}...
if (this.props.name !== nextProps.name) {
this.registerElems(nextProps.name);
}
}
}, {
key: 'componentWillUnmount',
value: function componentWillUnmount() {
defaultScroller.unregister(this.props.name);
}
}, {
key: 'registerElems',
value: function registerElems(name) {
var domNode = ReactDOM.findDOMNode(this);
defaultScroller.register(name, domNode);
}
...