proklim/public/assets/libs/dom-autoscroller/bundle.js

348 lines
9.5 KiB
JavaScript

'use strict';
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var typeFunc = require('type-func');
var animationFramePolyfill = require('animation-frame-polyfill');
var domSet = require('dom-set');
var domPlane = require('dom-plane');
var mousemoveDispatcher = _interopDefault(require('dom-mousemove-dispatcher'));
function AutoScroller(elements, options){
if ( options === void 0 ) options = {};
var self = this;
var maxSpeed = 4, scrolling = false;
this.margin = options.margin || -1;
//this.scrolling = false;
this.scrollWhenOutside = options.scrollWhenOutside || false;
var point = {},
pointCB = domPlane.createPointCB(point),
dispatcher = mousemoveDispatcher(),
down = false;
window.addEventListener('mousemove', pointCB, false);
window.addEventListener('touchmove', pointCB, false);
if(!isNaN(options.maxSpeed)){
maxSpeed = options.maxSpeed;
}
this.autoScroll = typeFunc.boolean(options.autoScroll);
this.syncMove = typeFunc.boolean(options.syncMove, false);
this.destroy = function(forceCleanAnimation) {
window.removeEventListener('mousemove', pointCB, false);
window.removeEventListener('touchmove', pointCB, false);
window.removeEventListener('mousedown', onDown, false);
window.removeEventListener('touchstart', onDown, false);
window.removeEventListener('mouseup', onUp, false);
window.removeEventListener('touchend', onUp, false);
window.removeEventListener('pointerup', onUp, false);
window.removeEventListener('mouseleave', onMouseOut, false);
window.removeEventListener('mousemove', onMove, false);
window.removeEventListener('touchmove', onMove, false);
window.removeEventListener('scroll', setScroll, true);
elements = [];
if(forceCleanAnimation){
cleanAnimation();
}
};
this.add = function(){
var element = [], len = arguments.length;
while ( len-- ) element[ len ] = arguments[ len ];
domSet.addElements.apply(void 0, [ elements ].concat( element ));
return this;
};
this.remove = function(){
var element = [], len = arguments.length;
while ( len-- ) element[ len ] = arguments[ len ];
return domSet.removeElements.apply(void 0, [ elements ].concat( element ));
};
var hasWindow = null, windowAnimationFrame;
if(Object.prototype.toString.call(elements) !== '[object Array]'){
elements = [elements];
}
(function(temp){
elements = [];
temp.forEach(function(element){
if(element === window){
hasWindow = window;
}else{
self.add(element);
}
});
}(elements));
Object.defineProperties(this, {
down: {
get: function(){ return down; }
},
maxSpeed: {
get: function(){ return maxSpeed; }
},
point: {
get: function(){ return point; }
},
scrolling: {
get: function(){ return scrolling; }
}
});
var n = 0, current = null, animationFrame;
window.addEventListener('mousedown', onDown, false);
window.addEventListener('touchstart', onDown, false);
window.addEventListener('mouseup', onUp, false);
window.addEventListener('touchend', onUp, false);
/*
IE does not trigger mouseup event when scrolling.
It is a known issue that Microsoft won't fix.
https://connect.microsoft.com/IE/feedback/details/783058/scrollbar-trigger-mousedown-but-not-mouseup
IE supports pointer events instead
*/
window.addEventListener('pointerup', onUp, false);
window.addEventListener('mousemove', onMove, false);
window.addEventListener('touchmove', onMove, false);
window.addEventListener('mouseleave', onMouseOut, false);
window.addEventListener('scroll', setScroll, true);
function setScroll(e){
for(var i=0; i<elements.length; i++){
if(elements[i] === e.target){
scrolling = true;
break;
}
}
if(scrolling){
animationFramePolyfill.requestAnimationFrame(function (){ return scrolling = false; });
}
}
function onDown(){
down = true;
}
function onUp(){
down = false;
cleanAnimation();
}
function cleanAnimation(){
animationFramePolyfill.cancelAnimationFrame(animationFrame);
animationFramePolyfill.cancelAnimationFrame(windowAnimationFrame);
}
function onMouseOut(){
down = false;
}
function getTarget(target){
if(!target){
return null;
}
if(current === target){
return target;
}
if(domSet.hasElement(elements, target)){
return target;
}
while(target = target.parentNode){
if(domSet.hasElement(elements, target)){
return target;
}
}
return null;
}
function getElementUnderPoint(){
var underPoint = null;
for(var i=0; i<elements.length; i++){
if(inside(point, elements[i])){
underPoint = elements[i];
}
}
return underPoint;
}
function onMove(event){
if(!self.autoScroll()) { return; }
if(event['dispatched']){ return; }
var target = event.target, body = document.body;
if(current && !inside(point, current)){
if(!self.scrollWhenOutside){
current = null;
}
}
if(target && target.parentNode === body){
//The special condition to improve speed.
target = getElementUnderPoint();
}else{
target = getTarget(target);
if(!target){
target = getElementUnderPoint();
}
}
if(target && target !== current){
current = target;
}
if(hasWindow){
animationFramePolyfill.cancelAnimationFrame(windowAnimationFrame);
windowAnimationFrame = animationFramePolyfill.requestAnimationFrame(scrollWindow);
}
if(!current){
return;
}
animationFramePolyfill.cancelAnimationFrame(animationFrame);
animationFrame = animationFramePolyfill.requestAnimationFrame(scrollTick);
}
function scrollWindow(){
autoScroll(hasWindow);
animationFramePolyfill.cancelAnimationFrame(windowAnimationFrame);
windowAnimationFrame = animationFramePolyfill.requestAnimationFrame(scrollWindow);
}
function scrollTick(){
if(!current){
return;
}
autoScroll(current);
animationFramePolyfill.cancelAnimationFrame(animationFrame);
animationFrame = animationFramePolyfill.requestAnimationFrame(scrollTick);
}
function autoScroll(el){
var rect = domPlane.getClientRect(el), scrollx, scrolly;
if(point.x < rect.left + self.margin){
scrollx = Math.floor(
Math.max(-1, (point.x - rect.left) / self.margin - 1) * self.maxSpeed
);
}else if(point.x > rect.right - self.margin){
scrollx = Math.ceil(
Math.min(1, (point.x - rect.right) / self.margin + 1) * self.maxSpeed
);
}else{
scrollx = 0;
}
if(point.y < rect.top + self.margin){
scrolly = Math.floor(
Math.max(-1, (point.y - rect.top) / self.margin - 1) * self.maxSpeed
);
}else if(point.y > rect.bottom - self.margin){
scrolly = Math.ceil(
Math.min(1, (point.y - rect.bottom) / self.margin + 1) * self.maxSpeed
);
}else{
scrolly = 0;
}
if(self.syncMove()){
/*
Notes about mousemove event dispatch.
screen(X/Y) should need to be updated.
Some other properties might need to be set.
Keep the syncMove option default false until all inconsistencies are taken care of.
*/
dispatcher.dispatch(el, {
pageX: point.pageX + scrollx,
pageY: point.pageY + scrolly,
clientX: point.x + scrollx,
clientY: point.y + scrolly
});
}
setTimeout(function (){
if(scrolly){
scrollY(el, scrolly);
}
if(scrollx){
scrollX(el, scrollx);
}
});
}
function scrollY(el, amount){
if(el === window){
window.scrollTo(el.pageXOffset, el.pageYOffset + amount);
}else{
el.scrollTop += amount;
}
}
function scrollX(el, amount){
if(el === window){
window.scrollTo(el.pageXOffset + amount, el.pageYOffset);
}else{
el.scrollLeft += amount;
}
}
}
function AutoScrollerFactory(element, options){
return new AutoScroller(element, options);
}
function inside(point, el, rect){
if(!rect){
return domPlane.pointInside(point, el);
}else{
return (point.y > rect.top && point.y < rect.bottom &&
point.x > rect.left && point.x < rect.right);
}
}
/*
git remote add origin https://github.com/hollowdoor/dom_autoscroller.git
git push -u origin master
*/
module.exports = AutoScrollerFactory;
//# sourceMappingURL=bundle.js.map