Created
July 1, 2024 10:20
-
-
Save Shtille/e027c5ff4f3874e013c32a22b37fe82c to your computer and use it in GitHub Desktop.
Auto scrolling while dragging (JavaScript)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Drag scroller 0.2.0 | |
* @author Shtille <[email protected]> | |
* @license MIT | |
*/ | |
(function (global, factory) { | |
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : | |
typeof define === 'function' && define.amd ? define(factory) : | |
(global = global || self, global.DragAutoScroller = factory()); | |
}(this, (function() { 'use strict'; | |
/** | |
* A drag scroller. | |
* | |
* @class DragAutoScroller (name) | |
* @param {Object} options The options. Possible options: | |
* - {Object} context The callback context. Could be null. | |
* - {Function} matchFn The function to test draggable target. | |
* The signature is function(HTMLElement). Optional. | |
* - {Function} scrollFn The function to scroll viewport content. | |
* The signature is function(dy). | |
* - {Function} scrollDeltaFn The function to define own scroll delta depending on the draggable position. | |
* The signature is function(pageY). Optional. | |
* - {HTMLElement} viewport The viewport element. | |
* You can either define viewport or scroll delta function. | |
*/ | |
function DragAutoScroller(options) | |
{ | |
// Inner variables | |
var _threshold = 30, | |
_timer = null, | |
_enabled = false, | |
_scrollDelta = 0, | |
_scrollDefault = true, | |
_context, | |
_viewport, | |
_matchFn, | |
_scrollFn, | |
_scrollDeltaFn; | |
const _onInterval = function() { | |
if (_scrollFn) { | |
_scrollFn.call(_context, _scrollDelta); | |
_scrollDelta = 0; | |
} | |
}; | |
const _startTimer = function() { | |
if (_timer === null) { | |
_timer = setInterval(_onInterval, 24); | |
} | |
}; | |
const _stopTimer = function() { | |
if (_timer !== null) { | |
clearInterval(_timer); | |
_timer = null; | |
} | |
}; | |
const _onDragOver = function(e) { | |
e = e || window.event; | |
let context = _scrollDefault ? null : _context; | |
_scrollDelta = _scrollDeltaFn.call(context, e.pageY); | |
}; | |
const _defaultScrollDeltaFn = function(pageY) { | |
let rect = _viewport.getBoundingClientRect(); | |
let top = rect.top + _threshold; | |
if (pageY < top) { | |
// At top | |
return pageY - top; | |
} | |
let bottom = rect.bottom - _threshold; | |
if (pageY > bottom) { | |
// At bottom | |
return pageY - bottom; | |
} | |
return 0; | |
}; | |
/** | |
* Initializes with the given options. | |
* | |
* @param {Object} options The options | |
* @private | |
*/ | |
const init = function(options) { | |
_context = options.context; | |
if (options.matchFn !== undefined && typeof options.matchFn == 'function') | |
_matchFn = options.matchFn; | |
if (options.scrollFn !== undefined && typeof options.scrollFn == 'function') | |
_scrollFn = options.scrollFn; | |
if (options.scrollDeltaFn !== undefined && typeof options.scrollDeltaFn == 'function') { | |
_scrollDeltaFn = options.scrollDeltaFn; | |
_scrollDefault = false; | |
} else { | |
_scrollDeltaFn = _defaultScrollDeltaFn; | |
_scrollDefault = true; | |
} | |
if (options.viewport !== undefined && options.viewport instanceof HTMLElement) | |
_viewport = options.viewport; | |
}; | |
/** | |
* Destroys the object. | |
*/ | |
this.destroy = function() { | |
_stopTimer(); | |
}; | |
/** | |
* Called on start. | |
* | |
* @param {Event} event The event | |
*/ | |
this.onStart = function(event) { | |
if (_matchFn === undefined || _matchFn.call(_context, event.target)) { | |
_enabled = true; | |
document.addEventListener('dragover', _onDragOver, false); | |
_startTimer(); | |
} | |
}; | |
/** | |
* Called on end. | |
* | |
* @param {Event} event The event | |
*/ | |
this.onEnd = function(event) { | |
if (_enabled) { | |
_enabled = false; | |
document.removeEventListener('dragover', _onDragOver, false); | |
_stopTimer(); | |
} | |
}; | |
init(options); | |
} | |
return DragAutoScroller; | |
}))); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment