Merge pull request #999 from dmitrylyzo/es6_migration
ES6 migration: autoFocuser, dom, scrollManager
This commit is contained in:
commit
a01985c71b
6 changed files with 352 additions and 196 deletions
|
@ -78,11 +78,14 @@
|
||||||
"overrides": [
|
"overrides": [
|
||||||
{
|
{
|
||||||
"test": [
|
"test": [
|
||||||
|
"src/components/autoFocuser.js",
|
||||||
"src/components/cardbuilder/cardBuilder.js",
|
"src/components/cardbuilder/cardBuilder.js",
|
||||||
|
"src/components/dom.js",
|
||||||
"src/components/filedownloader.js",
|
"src/components/filedownloader.js",
|
||||||
"src/components/filesystem.js",
|
"src/components/filesystem.js",
|
||||||
"src/components/input/keyboardnavigation.js",
|
"src/components/input/keyboardnavigation.js",
|
||||||
"src/components/sanatizefilename.js"
|
"src/components/sanatizefilename.js",
|
||||||
|
"src/components/scrollManager.js"
|
||||||
],
|
],
|
||||||
"plugins": [
|
"plugins": [
|
||||||
"@babel/plugin-transform-modules-amd"
|
"@babel/plugin-transform-modules-amd"
|
||||||
|
|
|
@ -1,22 +1,29 @@
|
||||||
define(["focusManager", "layoutManager"], function (focusManager, layoutManager) {
|
/* eslint-disable indent */
|
||||||
"use strict";
|
|
||||||
|
/**
|
||||||
|
* Module for performing auto-focus.
|
||||||
|
* @module components/autoFocuser
|
||||||
|
*/
|
||||||
|
|
||||||
|
import focusManager from "focusManager";
|
||||||
|
import layoutManager from "layoutManager";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Previously selected element.
|
* Previously selected element.
|
||||||
*/
|
*/
|
||||||
var activeElement;
|
let activeElement;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if AutoFocuser is enabled.
|
* Returns _true_ if AutoFocuser is enabled.
|
||||||
*/
|
*/
|
||||||
function isEnabled() {
|
export function isEnabled() {
|
||||||
return layoutManager.tv;
|
return layoutManager.tv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start AutoFocuser
|
* Start AutoFocuser.
|
||||||
*/
|
*/
|
||||||
function enable() {
|
export function enable() {
|
||||||
if (!isEnabled()) {
|
if (!isEnabled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -28,24 +35,19 @@ define(["focusManager", "layoutManager"], function (focusManager, layoutManager)
|
||||||
console.debug("AutoFocuser enabled");
|
console.debug("AutoFocuser enabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an array from some source.
|
|
||||||
*/
|
|
||||||
var arrayFrom = Array.prototype.from || function (src) {
|
|
||||||
return Array.prototype.slice.call(src);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set focus on a suitable element, taking into account the previously selected.
|
* Set focus on a suitable element, taking into account the previously selected.
|
||||||
|
* @param {HTMLElement} [container] - Element to limit scope.
|
||||||
|
* @returns {HTMLElement} Focused element.
|
||||||
*/
|
*/
|
||||||
function autoFocus(container) {
|
export function autoFocus(container) {
|
||||||
if (!isEnabled()) {
|
if (!isEnabled()) {
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
container = container || document.body;
|
container = container || document.body;
|
||||||
|
|
||||||
var candidates = [];
|
let candidates = [];
|
||||||
|
|
||||||
if (activeElement) {
|
if (activeElement) {
|
||||||
// These elements are recreated
|
// These elements are recreated
|
||||||
|
@ -62,10 +64,10 @@ define(["focusManager", "layoutManager"], function (focusManager, layoutManager)
|
||||||
candidates.push(activeElement);
|
candidates.push(activeElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
candidates = candidates.concat(arrayFrom(container.querySelectorAll(".btnResume")));
|
candidates = candidates.concat(Array.from(container.querySelectorAll(".btnResume")));
|
||||||
candidates = candidates.concat(arrayFrom(container.querySelectorAll(".btnPlay")));
|
candidates = candidates.concat(Array.from(container.querySelectorAll(".btnPlay")));
|
||||||
|
|
||||||
var focusedElement;
|
let focusedElement;
|
||||||
|
|
||||||
candidates.every(function (element) {
|
candidates.every(function (element) {
|
||||||
if (focusManager.isCurrentlyFocusable(element)) {
|
if (focusManager.isCurrentlyFocusable(element)) {
|
||||||
|
@ -79,7 +81,7 @@ define(["focusManager", "layoutManager"], function (focusManager, layoutManager)
|
||||||
|
|
||||||
if (!focusedElement) {
|
if (!focusedElement) {
|
||||||
// FIXME: Multiple itemsContainers
|
// FIXME: Multiple itemsContainers
|
||||||
var itemsContainer = container.querySelector(".itemsContainer");
|
const itemsContainer = container.querySelector(".itemsContainer");
|
||||||
|
|
||||||
if (itemsContainer) {
|
if (itemsContainer) {
|
||||||
focusedElement = focusManager.autoFocus(itemsContainer);
|
focusedElement = focusManager.autoFocus(itemsContainer);
|
||||||
|
@ -93,9 +95,8 @@ define(["focusManager", "layoutManager"], function (focusManager, layoutManager)
|
||||||
return focusedElement;
|
return focusedElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
export default {
|
||||||
isEnabled: isEnabled,
|
isEnabled: isEnabled,
|
||||||
enable: enable,
|
enable: enable,
|
||||||
autoFocus: autoFocus
|
autoFocus: autoFocus
|
||||||
};
|
};
|
||||||
});
|
|
||||||
|
|
|
@ -1853,3 +1853,14 @@ import 'programStyles';
|
||||||
cell.removeAttribute('data-seriestimerid');
|
cell.removeAttribute('data-seriestimerid');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
getCardsHtml: getCardsHtml,
|
||||||
|
getDefaultBackgroundClass: getDefaultBackgroundClass,
|
||||||
|
getDefaultText: getDefaultText,
|
||||||
|
buildCards: buildCards,
|
||||||
|
onUserDataChanged: onUserDataChanged,
|
||||||
|
onTimerCreated: onTimerCreated,
|
||||||
|
onTimerCancelled: onTimerCancelled,
|
||||||
|
onSeriesTimerCancelled: onSeriesTimerCancelled
|
||||||
|
};
|
||||||
|
|
|
@ -1,8 +1,18 @@
|
||||||
define([], function () {
|
/* eslint-disable indent */
|
||||||
'use strict';
|
|
||||||
|
|
||||||
function parentWithAttribute(elem, name, value) {
|
/**
|
||||||
|
* Useful DOM utilities.
|
||||||
|
* @module components/dom
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns parent of element with specified attribute value.
|
||||||
|
* @param {HTMLElement} elem - Element whose parent need to find.
|
||||||
|
* @param {string} name - Attribute name.
|
||||||
|
* @param {mixed} value - Attribute value.
|
||||||
|
* @returns {HTMLElement} Parent with specified attribute value.
|
||||||
|
*/
|
||||||
|
export function parentWithAttribute(elem, name, value) {
|
||||||
while ((value ? elem.getAttribute(name) !== value : !elem.getAttribute(name))) {
|
while ((value ? elem.getAttribute(name) !== value : !elem.getAttribute(name))) {
|
||||||
elem = elem.parentNode;
|
elem = elem.parentNode;
|
||||||
|
|
||||||
|
@ -14,8 +24,13 @@ define([], function () {
|
||||||
return elem;
|
return elem;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parentWithTag(elem, tagNames) {
|
/**
|
||||||
|
* Returns parent of element with one of specified tag names.
|
||||||
|
* @param {HTMLElement} elem - Element whose parent need to find.
|
||||||
|
* @param {(string|Array)} tagNames - Tag name or array of tag names.
|
||||||
|
* @returns {HTMLElement} Parent with one of specified tag names.
|
||||||
|
*/
|
||||||
|
export function parentWithTag(elem, tagNames) {
|
||||||
// accept both string and array passed in
|
// accept both string and array passed in
|
||||||
if (!Array.isArray(tagNames)) {
|
if (!Array.isArray(tagNames)) {
|
||||||
tagNames = [tagNames];
|
tagNames = [tagNames];
|
||||||
|
@ -32,9 +47,14 @@ define([], function () {
|
||||||
return elem;
|
return elem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns _true_ if class list contains one of specified names.
|
||||||
|
* @param {DOMTokenList} classList - Class list.
|
||||||
|
* @param {Array} classNames - Array of class names.
|
||||||
|
* @returns {boolean} _true_ if class list contains one of specified names.
|
||||||
|
*/
|
||||||
function containsAnyClass(classList, classNames) {
|
function containsAnyClass(classList, classNames) {
|
||||||
|
for (let i = 0, length = classNames.length; i < length; i++) {
|
||||||
for (var i = 0, length = classNames.length; i < length; i++) {
|
|
||||||
if (classList.contains(classNames[i])) {
|
if (classList.contains(classNames[i])) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -42,8 +62,13 @@ define([], function () {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parentWithClass(elem, classNames) {
|
/**
|
||||||
|
* Returns parent of element with one of specified class names.
|
||||||
|
* @param {HTMLElement} elem - Element whose parent need to find.
|
||||||
|
* @param {(string|Array)} classNames - Class name or array of class names.
|
||||||
|
* @returns {HTMLElement} Parent with one of specified class names.
|
||||||
|
*/
|
||||||
|
export function parentWithClass(elem, classNames) {
|
||||||
// accept both string and array passed in
|
// accept both string and array passed in
|
||||||
if (!Array.isArray(classNames)) {
|
if (!Array.isArray(classNames)) {
|
||||||
classNames = [classNames];
|
classNames = [classNames];
|
||||||
|
@ -60,9 +85,9 @@ define([], function () {
|
||||||
return elem;
|
return elem;
|
||||||
}
|
}
|
||||||
|
|
||||||
var supportsCaptureOption = false;
|
let supportsCaptureOption = false;
|
||||||
try {
|
try {
|
||||||
var opts = Object.defineProperty({}, 'capture', {
|
const opts = Object.defineProperty({}, 'capture', {
|
||||||
// eslint-disable-next-line getter-return
|
// eslint-disable-next-line getter-return
|
||||||
get: function () {
|
get: function () {
|
||||||
supportsCaptureOption = true;
|
supportsCaptureOption = true;
|
||||||
|
@ -73,29 +98,58 @@ define([], function () {
|
||||||
console.debug('error checking capture support');
|
console.debug('error checking capture support');
|
||||||
}
|
}
|
||||||
|
|
||||||
function addEventListenerWithOptions(target, type, handler, options) {
|
/**
|
||||||
var optionsOrCapture = options || {};
|
* Adds event listener to specified target.
|
||||||
|
* @param {EventTarget} target - Event target.
|
||||||
|
* @param {string} type - Event type.
|
||||||
|
* @param {function} handler - Event handler.
|
||||||
|
* @param {Object} [options] - Listener options.
|
||||||
|
*/
|
||||||
|
export function addEventListener(target, type, handler, options) {
|
||||||
|
let optionsOrCapture = options || {};
|
||||||
if (!supportsCaptureOption) {
|
if (!supportsCaptureOption) {
|
||||||
optionsOrCapture = optionsOrCapture.capture;
|
optionsOrCapture = optionsOrCapture.capture;
|
||||||
}
|
}
|
||||||
target.addEventListener(type, handler, optionsOrCapture);
|
target.addEventListener(type, handler, optionsOrCapture);
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeEventListenerWithOptions(target, type, handler, options) {
|
/**
|
||||||
var optionsOrCapture = options || {};
|
* Removes event listener from specified target.
|
||||||
|
* @param {EventTarget} target - Event target.
|
||||||
|
* @param {string} type - Event type.
|
||||||
|
* @param {function} handler - Event handler.
|
||||||
|
* @param {Object} [options] - Listener options.
|
||||||
|
*/
|
||||||
|
export function removeEventListener(target, type, handler, options) {
|
||||||
|
let optionsOrCapture = options || {};
|
||||||
if (!supportsCaptureOption) {
|
if (!supportsCaptureOption) {
|
||||||
optionsOrCapture = optionsOrCapture.capture;
|
optionsOrCapture = optionsOrCapture.capture;
|
||||||
}
|
}
|
||||||
target.removeEventListener(type, handler, optionsOrCapture);
|
target.removeEventListener(type, handler, optionsOrCapture);
|
||||||
}
|
}
|
||||||
|
|
||||||
var windowSize;
|
/**
|
||||||
var windowSizeEventsBound;
|
* Cached window size.
|
||||||
|
*/
|
||||||
|
let windowSize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flag of event listener bound.
|
||||||
|
*/
|
||||||
|
let windowSizeEventsBound;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets cached window size.
|
||||||
|
*/
|
||||||
function clearWindowSize() {
|
function clearWindowSize() {
|
||||||
windowSize = null;
|
windowSize = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getWindowSize() {
|
/**
|
||||||
|
* Returns window size.
|
||||||
|
* @returns {Object} Window size.
|
||||||
|
*/
|
||||||
|
export function getWindowSize() {
|
||||||
if (!windowSize) {
|
if (!windowSize) {
|
||||||
windowSize = {
|
windowSize = {
|
||||||
innerHeight: window.innerHeight,
|
innerHeight: window.innerHeight,
|
||||||
|
@ -104,46 +158,60 @@ define([], function () {
|
||||||
|
|
||||||
if (!windowSizeEventsBound) {
|
if (!windowSizeEventsBound) {
|
||||||
windowSizeEventsBound = true;
|
windowSizeEventsBound = true;
|
||||||
addEventListenerWithOptions(window, "orientationchange", clearWindowSize, { passive: true });
|
addEventListener(window, "orientationchange", clearWindowSize, { passive: true });
|
||||||
addEventListenerWithOptions(window, 'resize', clearWindowSize, { passive: true });
|
addEventListener(window, 'resize', clearWindowSize, { passive: true });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return windowSize;
|
return windowSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
var standardWidths = [480, 720, 1280, 1440, 1920, 2560, 3840, 5120, 7680];
|
/**
|
||||||
function getScreenWidth() {
|
* Standard screen widths.
|
||||||
var width = window.innerWidth;
|
*/
|
||||||
var height = window.innerHeight;
|
const standardWidths = [480, 720, 1280, 1440, 1920, 2560, 3840, 5120, 7680];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns screen width.
|
||||||
|
* @returns {number} Screen width.
|
||||||
|
*/
|
||||||
|
export function getScreenWidth() {
|
||||||
|
let width = window.innerWidth;
|
||||||
|
const height = window.innerHeight;
|
||||||
|
|
||||||
if (height > width) {
|
if (height > width) {
|
||||||
width = height * (16.0 / 9.0);
|
width = height * (16.0 / 9.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
var closest = standardWidths.sort(function (a, b) {
|
const closest = standardWidths.sort(function (a, b) {
|
||||||
return Math.abs(width - a) - Math.abs(width - b);
|
return Math.abs(width - a) - Math.abs(width - b);
|
||||||
})[0];
|
})[0];
|
||||||
|
|
||||||
return closest;
|
return closest;
|
||||||
}
|
}
|
||||||
|
|
||||||
var _animationEvent;
|
/**
|
||||||
function whichAnimationEvent() {
|
* Name of animation end event.
|
||||||
|
*/
|
||||||
|
let _animationEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns name of animation end event.
|
||||||
|
* @returns {string} Name of animation end event.
|
||||||
|
*/
|
||||||
|
export function whichAnimationEvent() {
|
||||||
if (_animationEvent) {
|
if (_animationEvent) {
|
||||||
return _animationEvent;
|
return _animationEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
var t;
|
const el = document.createElement("div");
|
||||||
var el = document.createElement("div");
|
const animations = {
|
||||||
var animations = {
|
|
||||||
"animation": "animationend",
|
"animation": "animationend",
|
||||||
"OAnimation": "oAnimationEnd",
|
"OAnimation": "oAnimationEnd",
|
||||||
"MozAnimation": "animationend",
|
"MozAnimation": "animationend",
|
||||||
"WebkitAnimation": "webkitAnimationEnd"
|
"WebkitAnimation": "webkitAnimationEnd"
|
||||||
};
|
};
|
||||||
for (t in animations) {
|
for (let t in animations) {
|
||||||
if (el.style[t] !== undefined) {
|
if (el.style[t] !== undefined) {
|
||||||
_animationEvent = animations[t];
|
_animationEvent = animations[t];
|
||||||
return animations[t];
|
return animations[t];
|
||||||
|
@ -154,26 +222,36 @@ define([], function () {
|
||||||
return _animationEvent;
|
return _animationEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
function whichAnimationCancelEvent() {
|
/**
|
||||||
|
* Returns name of animation cancel event.
|
||||||
|
* @returns {string} Name of animation cancel event.
|
||||||
|
*/
|
||||||
|
export function whichAnimationCancelEvent() {
|
||||||
return whichAnimationEvent().replace('animationend', 'animationcancel').replace('AnimationEnd', 'AnimationCancel');
|
return whichAnimationEvent().replace('animationend', 'animationcancel').replace('AnimationEnd', 'AnimationCancel');
|
||||||
}
|
}
|
||||||
|
|
||||||
var _transitionEvent;
|
/**
|
||||||
function whichTransitionEvent() {
|
* Name of transition end event.
|
||||||
|
*/
|
||||||
|
let _transitionEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns name of transition end event.
|
||||||
|
* @returns {string} Name of transition end event.
|
||||||
|
*/
|
||||||
|
export function whichTransitionEvent() {
|
||||||
if (_transitionEvent) {
|
if (_transitionEvent) {
|
||||||
return _transitionEvent;
|
return _transitionEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
var t;
|
const el = document.createElement("div");
|
||||||
var el = document.createElement("div");
|
const transitions = {
|
||||||
var transitions = {
|
|
||||||
"transition": "transitionend",
|
"transition": "transitionend",
|
||||||
"OTransition": "oTransitionEnd",
|
"OTransition": "oTransitionEnd",
|
||||||
"MozTransition": "transitionend",
|
"MozTransition": "transitionend",
|
||||||
"WebkitTransition": "webkitTransitionEnd"
|
"WebkitTransition": "webkitTransitionEnd"
|
||||||
};
|
};
|
||||||
for (t in transitions) {
|
for (let t in transitions) {
|
||||||
if (el.style[t] !== undefined) {
|
if (el.style[t] !== undefined) {
|
||||||
_transitionEvent = transitions[t];
|
_transitionEvent = transitions[t];
|
||||||
return transitions[t];
|
return transitions[t];
|
||||||
|
@ -184,16 +262,15 @@ define([], function () {
|
||||||
return _transitionEvent;
|
return _transitionEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
export default {
|
||||||
parentWithAttribute: parentWithAttribute,
|
parentWithAttribute: parentWithAttribute,
|
||||||
parentWithClass: parentWithClass,
|
parentWithClass: parentWithClass,
|
||||||
parentWithTag: parentWithTag,
|
parentWithTag: parentWithTag,
|
||||||
addEventListener: addEventListenerWithOptions,
|
addEventListener: addEventListener,
|
||||||
removeEventListener: removeEventListenerWithOptions,
|
removeEventListener: removeEventListener,
|
||||||
getWindowSize: getWindowSize,
|
getWindowSize: getWindowSize,
|
||||||
getScreenWidth: getScreenWidth,
|
getScreenWidth: getScreenWidth,
|
||||||
whichTransitionEvent: whichTransitionEvent,
|
whichTransitionEvent: whichTransitionEvent,
|
||||||
whichAnimationEvent: whichAnimationEvent,
|
whichAnimationEvent: whichAnimationEvent,
|
||||||
whichAnimationCancelEvent: whichAnimationCancelEvent
|
whichAnimationCancelEvent: whichAnimationCancelEvent
|
||||||
};
|
};
|
||||||
});
|
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/**
|
||||||
|
* Module for performing keyboard navigation.
|
||||||
|
* @module components/input/keyboardnavigation
|
||||||
|
*/
|
||||||
|
|
||||||
import inputManager from "inputManager";
|
import inputManager from "inputManager";
|
||||||
import layoutManager from "layoutManager";
|
import layoutManager from "layoutManager";
|
||||||
|
|
||||||
|
@ -55,8 +60,8 @@ if (!hasFieldKey) {
|
||||||
/**
|
/**
|
||||||
* Returns key name from event.
|
* Returns key name from event.
|
||||||
*
|
*
|
||||||
* @param {KeyboardEvent} event keyboard event
|
* @param {KeyboardEvent} event - Keyboard event.
|
||||||
* @return {string} key name
|
* @return {string} Key name.
|
||||||
*/
|
*/
|
||||||
export function getKeyName(event) {
|
export function getKeyName(event) {
|
||||||
return KeyNames[event.keyCode] || event.key;
|
return KeyNames[event.keyCode] || event.key;
|
||||||
|
@ -65,8 +70,8 @@ export function getKeyName(event) {
|
||||||
/**
|
/**
|
||||||
* Returns _true_ if key is used for navigation.
|
* Returns _true_ if key is used for navigation.
|
||||||
*
|
*
|
||||||
* @param {string} key name
|
* @param {string} key - Key name.
|
||||||
* @return {boolean} _true_ if key is used for navigation
|
* @return {boolean} _true_ if key is used for navigation.
|
||||||
*/
|
*/
|
||||||
export function isNavigationKey(key) {
|
export function isNavigationKey(key) {
|
||||||
return NavigationKeys.indexOf(key) != -1;
|
return NavigationKeys.indexOf(key) != -1;
|
||||||
|
@ -155,3 +160,9 @@ function attachGamepadScript(e) {
|
||||||
|
|
||||||
// No need to check for gamepads manually at load time, the eventhandler will be fired for that
|
// No need to check for gamepads manually at load time, the eventhandler will be fired for that
|
||||||
window.addEventListener("gamepadconnected", attachGamepadScript);
|
window.addEventListener("gamepadconnected", attachGamepadScript);
|
||||||
|
|
||||||
|
export default {
|
||||||
|
enable: enable,
|
||||||
|
getKeyName: getKeyName,
|
||||||
|
isNavigationKey: isNavigationKey
|
||||||
|
};
|
||||||
|
|
|
@ -1,38 +1,46 @@
|
||||||
define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManager) {
|
/* eslint-disable indent */
|
||||||
"use strict";
|
|
||||||
|
/**
|
||||||
|
* Module for controlling scroll behavior.
|
||||||
|
* @module components/scrollManager
|
||||||
|
*/
|
||||||
|
|
||||||
|
import dom from "dom";
|
||||||
|
import browser from "browser";
|
||||||
|
import layoutManager from "layoutManager";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scroll time in ms.
|
* Scroll time in ms.
|
||||||
*/
|
*/
|
||||||
var ScrollTime = 270;
|
const ScrollTime = 270;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Epsilon for comparing values.
|
* Epsilon for comparing values.
|
||||||
*/
|
*/
|
||||||
var Epsilon = 1e-6;
|
const Epsilon = 1e-6;
|
||||||
|
|
||||||
// FIXME: Need to scroll to top of page to fully show the top menu. This can be solved by some marker of top most elements or their containers
|
// FIXME: Need to scroll to top of page to fully show the top menu. This can be solved by some marker of top most elements or their containers
|
||||||
/**
|
/**
|
||||||
* Returns minimum vertical scroll.
|
* Returns minimum vertical scroll.
|
||||||
* Scroll less than that value will be zeroed.
|
* Scroll less than that value will be zeroed.
|
||||||
*
|
*
|
||||||
* @return {number} minimum vertical scroll
|
* @return {number} Minimum vertical scroll.
|
||||||
*/
|
*/
|
||||||
function minimumScrollY() {
|
function minimumScrollY() {
|
||||||
var topMenu = document.querySelector(".headerTop");
|
const topMenu = document.querySelector(".headerTop");
|
||||||
if (topMenu) {
|
if (topMenu) {
|
||||||
return topMenu.clientHeight;
|
return topMenu.clientHeight;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
var supportsSmoothScroll = "scrollBehavior" in document.documentElement.style;
|
const supportsSmoothScroll = "scrollBehavior" in document.documentElement.style;
|
||||||
|
|
||||||
var supportsScrollToOptions = false;
|
let supportsScrollToOptions = false;
|
||||||
try {
|
try {
|
||||||
var elem = document.createElement("div");
|
const elem = document.createElement("div");
|
||||||
|
|
||||||
var opts = Object.defineProperty({}, "behavior", {
|
const opts = Object.defineProperty({}, "behavior", {
|
||||||
// eslint-disable-next-line getter-return
|
// eslint-disable-next-line getter-return
|
||||||
get: function () {
|
get: function () {
|
||||||
supportsScrollToOptions = true;
|
supportsScrollToOptions = true;
|
||||||
|
@ -47,10 +55,10 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage
|
||||||
/**
|
/**
|
||||||
* Returns value clamped by range [min, max].
|
* Returns value clamped by range [min, max].
|
||||||
*
|
*
|
||||||
* @param {number} value clamped value
|
* @param {number} value - Clamped value.
|
||||||
* @param {number} min begining of range
|
* @param {number} min - Begining of range.
|
||||||
* @param {number} max ending of range
|
* @param {number} max - Ending of range.
|
||||||
* @return {number} clamped value
|
* @return {number} Clamped value.
|
||||||
*/
|
*/
|
||||||
function clamp(value, min, max) {
|
function clamp(value, min, max) {
|
||||||
return value <= min ? min : value >= max ? max : value;
|
return value <= min ? min : value >= max ? max : value;
|
||||||
|
@ -60,15 +68,15 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage
|
||||||
* Returns the required delta to fit range 1 into range 2.
|
* Returns the required delta to fit range 1 into range 2.
|
||||||
* In case of range 1 is bigger than range 2 returns delta to fit most out of range part.
|
* In case of range 1 is bigger than range 2 returns delta to fit most out of range part.
|
||||||
*
|
*
|
||||||
* @param {number} begin1 begining of range 1
|
* @param {number} begin1 - Begining of range 1.
|
||||||
* @param {number} end1 ending of range 1
|
* @param {number} end1 - Ending of range 1.
|
||||||
* @param {number} begin2 begining of range 2
|
* @param {number} begin2 - Begining of range 2.
|
||||||
* @param {number} end2 ending of range 2
|
* @param {number} end2 - Ending of range 2.
|
||||||
* @return {number} delta: <0 move range1 to the left, >0 - to the right
|
* @return {number} Delta: <0 move range1 to the left, >0 - to the right.
|
||||||
*/
|
*/
|
||||||
function fitRange(begin1, end1, begin2, end2) {
|
function fitRange(begin1, end1, begin2, end2) {
|
||||||
var delta1 = begin1 - begin2;
|
const delta1 = begin1 - begin2;
|
||||||
var delta2 = end2 - end1;
|
const delta2 = end2 - end1;
|
||||||
if (delta1 < 0 && delta1 < delta2) {
|
if (delta1 < 0 && delta1 < delta2) {
|
||||||
return -delta1;
|
return -delta1;
|
||||||
} else if (delta2 < 0) {
|
} else if (delta2 < 0) {
|
||||||
|
@ -80,13 +88,21 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage
|
||||||
/**
|
/**
|
||||||
* Ease value.
|
* Ease value.
|
||||||
*
|
*
|
||||||
* @param {number} t value in range [0, 1]
|
* @param {number} t - Value in range [0, 1].
|
||||||
* @return {number} eased value in range [0, 1]
|
* @return {number} Eased value in range [0, 1].
|
||||||
*/
|
*/
|
||||||
function ease(t) {
|
function ease(t) {
|
||||||
return t*(2 - t); // easeOutQuad === ease-out
|
return t*(2 - t); // easeOutQuad === ease-out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} Rect
|
||||||
|
* @property {number} left - X coordinate of top-left corner.
|
||||||
|
* @property {number} top - Y coordinate of top-left corner.
|
||||||
|
* @property {number} width - Width.
|
||||||
|
* @property {number} height - Height.
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Document scroll wrapper helps to unify scrolling and fix issues of some browsers.
|
* Document scroll wrapper helps to unify scrolling and fix issues of some browsers.
|
||||||
*
|
*
|
||||||
|
@ -100,41 +116,68 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage
|
||||||
*
|
*
|
||||||
* Tizen 5 Browser/Native: scrolls documentElement (and window); has a document.scrollingElement
|
* Tizen 5 Browser/Native: scrolls documentElement (and window); has a document.scrollingElement
|
||||||
*/
|
*/
|
||||||
function DocumentScroller() {
|
class DocumentScroller {
|
||||||
}
|
/**
|
||||||
|
* Horizontal scroll position.
|
||||||
DocumentScroller.prototype = {
|
* @type {number}
|
||||||
|
*/
|
||||||
get scrollLeft() {
|
get scrollLeft() {
|
||||||
return window.pageXOffset;
|
return window.pageXOffset;
|
||||||
},
|
}
|
||||||
|
|
||||||
set scrollLeft(val) {
|
set scrollLeft(val) {
|
||||||
window.scroll(val, window.pageYOffset);
|
window.scroll(val, window.pageYOffset);
|
||||||
},
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vertical scroll position.
|
||||||
|
* @type {number}
|
||||||
|
*/
|
||||||
get scrollTop() {
|
get scrollTop() {
|
||||||
return window.pageYOffset;
|
return window.pageYOffset;
|
||||||
},
|
}
|
||||||
|
|
||||||
set scrollTop(val) {
|
set scrollTop(val) {
|
||||||
window.scroll(window.pageXOffset, val);
|
window.scroll(window.pageXOffset, val);
|
||||||
},
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Horizontal scroll size (scroll width).
|
||||||
|
* @type {number}
|
||||||
|
*/
|
||||||
get scrollWidth() {
|
get scrollWidth() {
|
||||||
return Math.max(document.documentElement.scrollWidth, document.body.scrollWidth);
|
return Math.max(document.documentElement.scrollWidth, document.body.scrollWidth);
|
||||||
},
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vertical scroll size (scroll height).
|
||||||
|
* @type {number}
|
||||||
|
*/
|
||||||
get scrollHeight() {
|
get scrollHeight() {
|
||||||
return Math.max(document.documentElement.scrollHeight, document.body.scrollHeight);
|
return Math.max(document.documentElement.scrollHeight, document.body.scrollHeight);
|
||||||
},
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Horizontal client size (client width).
|
||||||
|
* @type {number}
|
||||||
|
*/
|
||||||
get clientWidth() {
|
get clientWidth() {
|
||||||
return Math.min(document.documentElement.clientWidth, document.body.clientWidth);
|
return Math.min(document.documentElement.clientWidth, document.body.clientWidth);
|
||||||
},
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vertical client size (client height).
|
||||||
|
* @type {number}
|
||||||
|
*/
|
||||||
get clientHeight() {
|
get clientHeight() {
|
||||||
return Math.min(document.documentElement.clientHeight, document.body.clientHeight);
|
return Math.min(document.documentElement.clientHeight, document.body.clientHeight);
|
||||||
},
|
}
|
||||||
|
|
||||||
getBoundingClientRect: function() {
|
/**
|
||||||
|
* Returns bounding client rect.
|
||||||
|
* @return {Rect} Bounding client rect.
|
||||||
|
*/
|
||||||
|
getBoundingClientRect() {
|
||||||
// Make valid viewport coordinates: documentElement.getBoundingClientRect returns rect of entire document relative to viewport
|
// Make valid viewport coordinates: documentElement.getBoundingClientRect returns rect of entire document relative to viewport
|
||||||
return {
|
return {
|
||||||
left: 0,
|
left: 0,
|
||||||
|
@ -142,26 +185,34 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage
|
||||||
width: this.clientWidth,
|
width: this.clientWidth,
|
||||||
height: this.clientHeight
|
height: this.clientHeight
|
||||||
};
|
};
|
||||||
},
|
}
|
||||||
|
|
||||||
scrollTo: function() {
|
/**
|
||||||
|
* Scrolls window.
|
||||||
|
* @param {...mixed} args See window.scrollTo.
|
||||||
|
*/
|
||||||
|
scrollTo() {
|
||||||
window.scrollTo.apply(window, arguments);
|
window.scrollTo.apply(window, arguments);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
var documentScroller = new DocumentScroller();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns parent element that can be scrolled. If no such, returns documentElement.
|
* Default (document) scroller.
|
||||||
|
*/
|
||||||
|
const documentScroller = new DocumentScroller();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns parent element that can be scrolled. If no such, returns document scroller.
|
||||||
*
|
*
|
||||||
* @param {HTMLElement} element element for which parent is being searched
|
* @param {HTMLElement} element - Element for which parent is being searched.
|
||||||
* @param {boolean} vertical search for vertical scrollable parent
|
* @param {boolean} vertical - Search for vertical scrollable parent.
|
||||||
|
* @param {HTMLElement|DocumentScroller} Parent element that can be scrolled or document scroller.
|
||||||
*/
|
*/
|
||||||
function getScrollableParent(element, vertical) {
|
function getScrollableParent(element, vertical) {
|
||||||
if (element) {
|
if (element) {
|
||||||
var nameScroll = "scrollWidth";
|
let nameScroll = "scrollWidth";
|
||||||
var nameClient = "clientWidth";
|
let nameClient = "clientWidth";
|
||||||
var nameClass = "scrollX";
|
let nameClass = "scrollX";
|
||||||
|
|
||||||
if (vertical) {
|
if (vertical) {
|
||||||
nameScroll = "scrollHeight";
|
nameScroll = "scrollHeight";
|
||||||
|
@ -169,7 +220,7 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage
|
||||||
nameClass = "scrollY";
|
nameClass = "scrollY";
|
||||||
}
|
}
|
||||||
|
|
||||||
var parent = element.parentElement;
|
let parent = element.parentElement;
|
||||||
|
|
||||||
while (parent) {
|
while (parent) {
|
||||||
// Skip 'emby-scroller' because it scrolls by itself
|
// Skip 'emby-scroller' because it scrolls by itself
|
||||||
|
@ -187,20 +238,20 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {Object} ScrollerData
|
* @typedef {Object} ScrollerData
|
||||||
* @property {number} scrollPos current scroll position
|
* @property {number} scrollPos - Current scroll position.
|
||||||
* @property {number} scrollSize scroll size
|
* @property {number} scrollSize - Scroll size.
|
||||||
* @property {number} clientSize client size
|
* @property {number} clientSize - Client size.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns scroll data for specified orientation.
|
* Returns scroller data for specified orientation.
|
||||||
*
|
*
|
||||||
* @param {HTMLElement} scroller scroller
|
* @param {HTMLElement} scroller - Scroller.
|
||||||
* @param {boolean} vertical vertical scroll data
|
* @param {boolean} vertical - Vertical scroller data.
|
||||||
* @return {ScrollerData} scroll data
|
* @return {ScrollerData} Scroller data.
|
||||||
*/
|
*/
|
||||||
function getScrollerData(scroller, vertical) {
|
function getScrollerData(scroller, vertical) {
|
||||||
var data = {};
|
let data = {};
|
||||||
|
|
||||||
if (!vertical) {
|
if (!vertical) {
|
||||||
data.scrollPos = scroller.scrollLeft;
|
data.scrollPos = scroller.scrollLeft;
|
||||||
|
@ -218,14 +269,14 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage
|
||||||
/**
|
/**
|
||||||
* Returns position of child of scroller for specified orientation.
|
* Returns position of child of scroller for specified orientation.
|
||||||
*
|
*
|
||||||
* @param {HTMLElement} scroller scroller
|
* @param {HTMLElement} scroller - Scroller.
|
||||||
* @param {HTMLElement} element child of scroller
|
* @param {HTMLElement} element - Child of scroller.
|
||||||
* @param {boolean} vertical vertical scroll
|
* @param {boolean} vertical - Vertical scroll.
|
||||||
* @return {number} child position
|
* @return {number} Child position.
|
||||||
*/
|
*/
|
||||||
function getScrollerChildPos(scroller, element, vertical) {
|
function getScrollerChildPos(scroller, element, vertical) {
|
||||||
var elementRect = element.getBoundingClientRect();
|
const elementRect = element.getBoundingClientRect();
|
||||||
var scrollerRect = scroller.getBoundingClientRect();
|
const scrollerRect = scroller.getBoundingClientRect();
|
||||||
|
|
||||||
if (!vertical) {
|
if (!vertical) {
|
||||||
return scroller.scrollLeft + elementRect.left - scrollerRect.left;
|
return scroller.scrollLeft + elementRect.left - scrollerRect.left;
|
||||||
|
@ -237,21 +288,21 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage
|
||||||
/**
|
/**
|
||||||
* Returns scroll position for element.
|
* Returns scroll position for element.
|
||||||
*
|
*
|
||||||
* @param {ScrollerData} scrollerData scroller data
|
* @param {ScrollerData} scrollerData - Scroller data.
|
||||||
* @param {number} elementPos child element position
|
* @param {number} elementPos - Child element position.
|
||||||
* @param {number} elementSize child element size
|
* @param {number} elementSize - Child element size.
|
||||||
* @param {boolean} centered scroll to center
|
* @param {boolean} centered - Scroll to center.
|
||||||
* @return {number} scroll position
|
* @return {number} Scroll position.
|
||||||
*/
|
*/
|
||||||
function calcScroll(scrollerData, elementPos, elementSize, centered) {
|
function calcScroll(scrollerData, elementPos, elementSize, centered) {
|
||||||
var maxScroll = scrollerData.scrollSize - scrollerData.clientSize;
|
const maxScroll = scrollerData.scrollSize - scrollerData.clientSize;
|
||||||
|
|
||||||
var scroll;
|
let scroll;
|
||||||
|
|
||||||
if (centered) {
|
if (centered) {
|
||||||
scroll = elementPos + (elementSize - scrollerData.clientSize) / 2;
|
scroll = elementPos + (elementSize - scrollerData.clientSize) / 2;
|
||||||
} else {
|
} else {
|
||||||
var delta = fitRange(elementPos, elementPos + elementSize - 1, scrollerData.scrollPos, scrollerData.scrollPos + scrollerData.clientSize - 1);
|
const delta = fitRange(elementPos, elementPos + elementSize - 1, scrollerData.scrollPos, scrollerData.scrollPos + scrollerData.clientSize - 1);
|
||||||
scroll = scrollerData.scrollPos - delta;
|
scroll = scrollerData.scrollPos - delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,14 +312,14 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage
|
||||||
/**
|
/**
|
||||||
* Calls scrollTo function in proper way.
|
* Calls scrollTo function in proper way.
|
||||||
*
|
*
|
||||||
* @param {HTMLElement} scroller scroller
|
* @param {HTMLElement} scroller - Scroller.
|
||||||
* @param {ScrollToOptions} options scroll options
|
* @param {ScrollToOptions} options - Scroll options.
|
||||||
*/
|
*/
|
||||||
function scrollToHelper(scroller, options) {
|
function scrollToHelper(scroller, options) {
|
||||||
if ("scrollTo" in scroller) {
|
if ("scrollTo" in scroller) {
|
||||||
if (!supportsScrollToOptions) {
|
if (!supportsScrollToOptions) {
|
||||||
var scrollX = (options.left !== undefined ? options.left : scroller.scrollLeft);
|
const scrollX = (options.left !== undefined ? options.left : scroller.scrollLeft);
|
||||||
var scrollY = (options.top !== undefined ? options.top : scroller.scrollTop);
|
const scrollY = (options.top !== undefined ? options.top : scroller.scrollTop);
|
||||||
scroller.scrollTo(scrollX, scrollY);
|
scroller.scrollTo(scrollX, scrollY);
|
||||||
} else {
|
} else {
|
||||||
scroller.scrollTo(options);
|
scroller.scrollTo(options);
|
||||||
|
@ -286,14 +337,14 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage
|
||||||
/**
|
/**
|
||||||
* Performs built-in scroll.
|
* Performs built-in scroll.
|
||||||
*
|
*
|
||||||
* @param {HTMLElement} xScroller horizontal scroller
|
* @param {HTMLElement} xScroller - Horizontal scroller.
|
||||||
* @param {number} scrollX horizontal coordinate
|
* @param {number} scrollX - Horizontal coordinate.
|
||||||
* @param {HTMLElement} yScroller vertical scroller
|
* @param {HTMLElement} yScroller - Vertical scroller.
|
||||||
* @param {number} scrollY vertical coordinate
|
* @param {number} scrollY - Vertical coordinate.
|
||||||
* @param {boolean} smooth smooth scrolling
|
* @param {boolean} smooth - Smooth scrolling.
|
||||||
*/
|
*/
|
||||||
function builtinScroll(xScroller, scrollX, yScroller, scrollY, smooth) {
|
function builtinScroll(xScroller, scrollX, yScroller, scrollY, smooth) {
|
||||||
var scrollBehavior = smooth ? "smooth" : "instant";
|
const scrollBehavior = smooth ? "smooth" : "instant";
|
||||||
|
|
||||||
if (xScroller !== yScroller) {
|
if (xScroller !== yScroller) {
|
||||||
scrollToHelper(xScroller, {left: scrollX, behavior: scrollBehavior});
|
scrollToHelper(xScroller, {left: scrollX, behavior: scrollBehavior});
|
||||||
|
@ -303,7 +354,10 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var scrollTimer;
|
/**
|
||||||
|
* Requested frame for animated scroll.
|
||||||
|
*/
|
||||||
|
let scrollTimer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets scroll timer to stop scrolling.
|
* Resets scroll timer to stop scrolling.
|
||||||
|
@ -316,29 +370,29 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage
|
||||||
/**
|
/**
|
||||||
* Performs animated scroll.
|
* Performs animated scroll.
|
||||||
*
|
*
|
||||||
* @param {HTMLElement} xScroller horizontal scroller
|
* @param {HTMLElement} xScroller - Horizontal scroller.
|
||||||
* @param {number} scrollX horizontal coordinate
|
* @param {number} scrollX - Horizontal coordinate.
|
||||||
* @param {HTMLElement} yScroller vertical scroller
|
* @param {HTMLElement} yScroller - Vertical scroller.
|
||||||
* @param {number} scrollY vertical coordinate
|
* @param {number} scrollY - Vertical coordinate.
|
||||||
*/
|
*/
|
||||||
function animateScroll(xScroller, scrollX, yScroller, scrollY) {
|
function animateScroll(xScroller, scrollX, yScroller, scrollY) {
|
||||||
|
|
||||||
var ox = xScroller.scrollLeft;
|
const ox = xScroller.scrollLeft;
|
||||||
var oy = yScroller.scrollTop;
|
const oy = yScroller.scrollTop;
|
||||||
var dx = scrollX - ox;
|
const dx = scrollX - ox;
|
||||||
var dy = scrollY - oy;
|
const dy = scrollY - oy;
|
||||||
|
|
||||||
if (Math.abs(dx) < Epsilon && Math.abs(dy) < Epsilon) {
|
if (Math.abs(dx) < Epsilon && Math.abs(dy) < Epsilon) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var start;
|
let start;
|
||||||
|
|
||||||
function scrollAnim(currentTimestamp) {
|
function scrollAnim(currentTimestamp) {
|
||||||
|
|
||||||
start = start || currentTimestamp;
|
start = start || currentTimestamp;
|
||||||
|
|
||||||
var k = Math.min(1, (currentTimestamp - start) / ScrollTime);
|
let k = Math.min(1, (currentTimestamp - start) / ScrollTime);
|
||||||
|
|
||||||
if (k === 1) {
|
if (k === 1) {
|
||||||
resetScrollTimer();
|
resetScrollTimer();
|
||||||
|
@ -348,8 +402,8 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage
|
||||||
|
|
||||||
k = ease(k);
|
k = ease(k);
|
||||||
|
|
||||||
var x = ox + dx*k;
|
const x = ox + dx*k;
|
||||||
var y = oy + dy*k;
|
const y = oy + dy*k;
|
||||||
|
|
||||||
builtinScroll(xScroller, x, yScroller, y, false);
|
builtinScroll(xScroller, x, yScroller, y, false);
|
||||||
|
|
||||||
|
@ -362,11 +416,11 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage
|
||||||
/**
|
/**
|
||||||
* Performs scroll.
|
* Performs scroll.
|
||||||
*
|
*
|
||||||
* @param {HTMLElement} xScroller horizontal scroller
|
* @param {HTMLElement} xScroller - Horizontal scroller.
|
||||||
* @param {number} scrollX horizontal coordinate
|
* @param {number} scrollX - Horizontal coordinate.
|
||||||
* @param {HTMLElement} yScroller vertical scroller
|
* @param {HTMLElement} yScroller - Vertical scroller.
|
||||||
* @param {number} scrollY vertical coordinate
|
* @param {number} scrollY - Vertical coordinate.
|
||||||
* @param {boolean} smooth smooth scrolling
|
* @param {boolean} smooth - Smooth scrolling.
|
||||||
*/
|
*/
|
||||||
function doScroll(xScroller, scrollX, yScroller, scrollY, smooth) {
|
function doScroll(xScroller, scrollX, yScroller, scrollY, smooth) {
|
||||||
|
|
||||||
|
@ -403,26 +457,26 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage
|
||||||
/**
|
/**
|
||||||
* Returns true if scroll manager is enabled.
|
* Returns true if scroll manager is enabled.
|
||||||
*/
|
*/
|
||||||
var isEnabled = function() {
|
export function isEnabled() {
|
||||||
return layoutManager.tv;
|
return layoutManager.tv;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scrolls the document to a given position.
|
* Scrolls the document to a given position.
|
||||||
*
|
*
|
||||||
* @param {number} scrollX horizontal coordinate
|
* @param {number} scrollX - Horizontal coordinate.
|
||||||
* @param {number} scrollY vertical coordinate
|
* @param {number} scrollY - Vertical coordinate.
|
||||||
* @param {boolean} [smooth=false] smooth scrolling
|
* @param {boolean} [smooth=false] - Smooth scrolling.
|
||||||
*/
|
*/
|
||||||
var scrollTo = function(scrollX, scrollY, smooth) {
|
export function scrollTo(scrollX, scrollY, smooth) {
|
||||||
|
|
||||||
smooth = !!smooth;
|
smooth = !!smooth;
|
||||||
|
|
||||||
// Scroller is document itself by default
|
// Scroller is document itself by default
|
||||||
var scroller = getScrollableParent(null, false);
|
const scroller = getScrollableParent(null, false);
|
||||||
|
|
||||||
var xScrollerData = getScrollerData(scroller, false);
|
const xScrollerData = getScrollerData(scroller, false);
|
||||||
var yScrollerData = getScrollerData(scroller, true);
|
const yScrollerData = getScrollerData(scroller, true);
|
||||||
|
|
||||||
scrollX = clamp(Math.round(scrollX), 0, xScrollerData.scrollSize - xScrollerData.clientSize);
|
scrollX = clamp(Math.round(scrollX), 0, xScrollerData.scrollSize - xScrollerData.clientSize);
|
||||||
scrollY = clamp(Math.round(scrollY), 0, yScrollerData.scrollSize - yScrollerData.clientSize);
|
scrollY = clamp(Math.round(scrollY), 0, yScrollerData.scrollSize - yScrollerData.clientSize);
|
||||||
|
@ -433,39 +487,39 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage
|
||||||
/**
|
/**
|
||||||
* Scrolls the document to a given element.
|
* Scrolls the document to a given element.
|
||||||
*
|
*
|
||||||
* @param {HTMLElement} element target element of scroll task
|
* @param {HTMLElement} element - Target element of scroll task.
|
||||||
* @param {boolean} [smooth=false] smooth scrolling
|
* @param {boolean} [smooth=false] - Smooth scrolling.
|
||||||
*/
|
*/
|
||||||
var scrollToElement = function(element, smooth) {
|
export function scrollToElement(element, smooth) {
|
||||||
|
|
||||||
smooth = !!smooth;
|
smooth = !!smooth;
|
||||||
|
|
||||||
var scrollCenterX = true;
|
let scrollCenterX = true;
|
||||||
var scrollCenterY = true;
|
let scrollCenterY = true;
|
||||||
|
|
||||||
var offsetParent = element.offsetParent;
|
const offsetParent = element.offsetParent;
|
||||||
|
|
||||||
// In Firefox offsetParent.offsetParent is BODY
|
// In Firefox offsetParent.offsetParent is BODY
|
||||||
var isFixed = offsetParent && (!offsetParent.offsetParent || window.getComputedStyle(offsetParent).position === "fixed");
|
const isFixed = offsetParent && (!offsetParent.offsetParent || window.getComputedStyle(offsetParent).position === "fixed");
|
||||||
|
|
||||||
// Scroll fixed elements to nearest edge (or do not scroll at all)
|
// Scroll fixed elements to nearest edge (or do not scroll at all)
|
||||||
if (isFixed) {
|
if (isFixed) {
|
||||||
scrollCenterX = scrollCenterY = false;
|
scrollCenterX = scrollCenterY = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var xScroller = getScrollableParent(element, false);
|
const xScroller = getScrollableParent(element, false);
|
||||||
var yScroller = getScrollableParent(element, true);
|
const yScroller = getScrollableParent(element, true);
|
||||||
|
|
||||||
var elementRect = element.getBoundingClientRect();
|
const elementRect = element.getBoundingClientRect();
|
||||||
|
|
||||||
var xScrollerData = getScrollerData(xScroller, false);
|
const xScrollerData = getScrollerData(xScroller, false);
|
||||||
var yScrollerData = getScrollerData(yScroller, true);
|
const yScrollerData = getScrollerData(yScroller, true);
|
||||||
|
|
||||||
var xPos = getScrollerChildPos(xScroller, element, false);
|
const xPos = getScrollerChildPos(xScroller, element, false);
|
||||||
var yPos = getScrollerChildPos(yScroller, element, true);
|
const yPos = getScrollerChildPos(yScroller, element, true);
|
||||||
|
|
||||||
var scrollX = calcScroll(xScrollerData, xPos, elementRect.width, scrollCenterX);
|
const scrollX = calcScroll(xScrollerData, xPos, elementRect.width, scrollCenterX);
|
||||||
var scrollY = calcScroll(yScrollerData, yPos, elementRect.height, scrollCenterY);
|
let scrollY = calcScroll(yScrollerData, yPos, elementRect.height, scrollCenterY);
|
||||||
|
|
||||||
// HACK: Scroll to top for top menu because it is hidden
|
// HACK: Scroll to top for top menu because it is hidden
|
||||||
// FIXME: Need a marker to scroll top/bottom
|
// FIXME: Need a marker to scroll top/bottom
|
||||||
|
@ -490,9 +544,8 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage
|
||||||
}, {capture: true});
|
}, {capture: true});
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
export default {
|
||||||
isEnabled: isEnabled,
|
isEnabled: isEnabled,
|
||||||
scrollTo: scrollTo,
|
scrollTo: scrollTo,
|
||||||
scrollToElement: scrollToElement
|
scrollToElement: scrollToElement
|
||||||
};
|
};
|
||||||
});
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue