// The MIT License (MIT) // Copyright (c) 2016 Quentin Engles // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. (function() { // more_events function MoreEvents(context){ this.listeners = {}; this.__context = context || this; } MoreEvents.prototype = { constructor: MoreEvents, on: function(event, listener){ this.listeners[event] = this.listeners[event] || []; this.listeners[event].push(listener); return this; }, one: function(event, listener){ function onceListener(){ listener.apply(this, arguments); this.off(event, onceListener); return this; } return this.on(event, onceListener); }, emit: function(event){ if(typeof this.listeners[event] === 'undefined' || !this.listeners[event].length) return this; var args = Array.prototype.slice.call(arguments, 1), canRun = this.listeners[event].length; do{ this.listeners[event][--canRun].apply(this.__context, args); }while(canRun); return this; }, off: function(event, listener){ if(this.listeners[event] === undefined || !this.listeners[event].length) return this; this.listeners[event] = this.listeners[event].filter(function(item){ return item !== listener; }); return this; }, dispose: function(){ for(var n in this){ this[n] = null; } } }; // pointer_point var Emitter = MoreEvents; if(!Date.now){ Date.now = function(){ return new Date().getTime() } } function LocalDimensions(point, rect){ for(var n in rect) setProp(this, n, rect[n]); setProp(this, 'x', point.x - rect.left+1); setProp(this, 'y', point.y - rect.top+1); setProp(this, 'north', (((rect.bottom - rect.top) / 2)-this.y)); setProp(this, 'south', ((-(rect.bottom - rect.top) / 2)+this.y)); setProp(this, 'east', (((rect.right - rect.left) / 2)-this.x)); setProp(this, 'west', ((-(rect.right - rect.left) / 2)+this.x)); function setProp(self, name, value){ Object.defineProperty(self, name, { value: value, configurable: true, writable: false }); } } function Point(elements){ var self = this, el = []; if(typeof elements.length === 'undefined'){ elements = [elements]; } for(var i=0; i (startY - buf) && self.y < (startY + buf) && self.x > (startX - buf) && self.x < (startX + buf))){ //If there is scrolling there was a touch flick. if(!scrolling){ //No touch flick so self.previous = null; self.origin = null; e.preventDefault(); return false; } } } scrolling = false; self.previous = null; self.origin = null; } function toPoint(event){ var dot, eventDoc, doc, body, pageX, pageY; var target, newTarget = null, leaving = null; event = event || window.event; // IE-ism target = event.target || event.srcElement; //Supporting touch //http://www.creativebloq.com/javascript/make-your-site-work-touch-devices-51411644 if(event.targetTouches) { event.pageX = event.targetTouches[0].clientX; event.pageY = event.targetTouches[0].clientY; event.clientX = event.targetTouches[0].clientX; event.clientY = event.targetTouches[0].clientY; }else // If pageX/Y aren't available and clientX/Y are, // calculate pageX/Y - logic taken from jQuery. // (This is to support old IE) if (event.pageX === null && event.clientX !== null) { eventDoc = (event.target && event.target.ownerDocument) || document; doc = eventDoc.documentElement; body = eventDoc.body; event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0); event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0 ); } if(self.x && self.y){ if(event.pageX < self.x) direction.h = 'left'; else if(event.pageX > self.x) direction.h = 'right'; if(event.pageY < self.y) direction.v = 'up'; else if(event.pageY > self.y) direction.v = 'down'; lastmousex = self.x; lastmousey = self.y; } pos = {}; //Prefer the viewport with clientX, and clientY. //pageX, and pageY change too often. pos.x = event.clientX;//event.pageX; pos.y = event.clientY;//event.pageY; if(self.current === null || self.outside(self.current)){ for(var i=0; i downTime + (special.hold[i].data || 2000)){ special.hold[i].callback.call(this, el, rect); } } } downTime = 0; }); function removeSpecial(event, cb){ for(var i=0; i rect.top && this.y < rect.bottom && this.x > rect.left && this.x < rect.right); }, outside: function(el){ if(!el) throw new TypeError('Cannot be outside '+el); return !this.inside(el); } }; function elementFromPoint(x, y){ if(document.getElementFromPoint) return document.getElementFromPoint(x, y); else return document.elementFromPoint(x, y); return null; } function safeObject(src){ var obj = {}; for(var n in src) obj[n] = src[n]; return obj; } function getRect(el){ if(el === window){ return { top: 0, left: 0, right: window.innerWidth, bottom: window.innerHeight, width: window.innerWidth, height: window.innerHeight }; }else{ return el.getBoundingClientRect(); } } var pointer = function(element){ return new Point(element); }; // Autscroller function AutoScrollerFactory(element, options){ return new AutoScroller(element, options); } function AutoScroller(elements, options){ var self = this, pixels = 2; options = options || {}; this.margin = options.margin || -1; this.scrolling = false; this.scrollWhenOutside = options.scrollWhenOutside || false; this.point = pointer(elements); if(!isNaN(options.pixels)){ pixels = options.pixels; } if(typeof options.autoScroll === 'boolean'){ this.autoScroll = options.autoScroll ? function(){return true;} : function(){return false;}; }else if(typeof options.autoScroll === 'undefined'){ this.autoScroll = function(){return false;}; }else if(typeof options.autoScroll === 'function'){ this.autoScroll = options.autoScroll; } this.destroy = function() { this.point.destroy(); }; Object.defineProperties(this, { down: { get: function(){ return self.point.down; } }, interval: { get: function(){ return 1/pixels * 1000; } }, pixels: { set: function(i){ pixels = i; }, get: function(){ return pixels; } } }); this.point.on('move', function(el, rect){ if(!el) return; if(!self.autoScroll()) return; if(!self.scrollWhenOutside && this.outside(el)) return; if(self.point.y < rect.top + self.margin){ autoScrollV(el, -1, rect); }else if(self.point.y > rect.bottom - self.margin){ autoScrollV(el, 1, rect); } if(self.point.x < rect.left + self.margin){ autoScrollH(el, -1, rect); }else if(self.point.x > rect.right - self.margin){ autoScrollH(el, 1, rect); } }); function autoScrollV(el, amount, rect){ //if(!self.down) return; if(!self.autoScroll()) return; if(!self.scrollWhenOutside && self.point.outside(el)) return; if(el === window){ window.scrollTo(el.pageXOffset, el.pageYOffset + amount); }else{ el.scrollTop = el.scrollTop + amount; } setTimeout(function(){ if(self.point.y < rect.top + self.margin){ autoScrollV(el, amount, rect); }else if(self.point.y > rect.bottom - self.margin){ autoScrollV(el, amount, rect); } }, self.interval); } function autoScrollH(el, amount, rect){ //if(!self.down) return; if(!self.autoScroll()) return; if(!self.scrollWhenOutside && self.point.outside(el)) return; if(el === window){ window.scrollTo(el.pageXOffset + amount, el.pageYOffset); }else{ el.scrollLeft = el.scrollLeft + amount; } setTimeout(function(){ if(self.point.x < rect.left + self.margin){ autoScrollH(el, amount, rect); }else if(self.point.x > rect.right - self.margin){ autoScrollH(el, amount, rect); } }, self.interval); } } window.autoScroll = AutoScrollerFactory; }());