From cc66fb672c199270919cac651027eb1fabebabf5 Mon Sep 17 00:00:00 2001 From: Dmitry Lyzo Date: Sat, 28 Mar 2020 19:42:18 +0300 Subject: [PATCH 1/6] Migrate ScrollManger to ES6 --- package.json | 3 +- src/components/scrollManager.js | 239 +++++++++++++++++--------------- 2 files changed, 126 insertions(+), 116 deletions(-) diff --git a/package.json b/package.json index 81dd250ab5..5672ab6d2e 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,8 @@ "src/components/filedownloader.js", "src/components/filesystem.js", "src/components/input/keyboardnavigation.js", - "src/components/sanatizefilename.js" + "src/components/sanatizefilename.js", + "src/components/scrollManager.js" ], "plugins": ["@babel/plugin-transform-modules-amd"] }] diff --git a/src/components/scrollManager.js b/src/components/scrollManager.js index 5fc3729bac..96317fa998 100644 --- a/src/components/scrollManager.js +++ b/src/components/scrollManager.js @@ -1,15 +1,23 @@ -define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManager) { - "use strict"; +/* eslint-disable indent */ + +/** + * Module for controlling scroll behavior. + * @module components/scrollManager + */ + +import dom from "dom"; +import browser from "browser"; +import layoutManager from "layoutManager"; /** * Scroll time in ms. */ - var ScrollTime = 270; + const ScrollTime = 270; /** * 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 /** @@ -19,20 +27,20 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage * @return {number} minimum vertical scroll */ function minimumScrollY() { - var topMenu = document.querySelector(".headerTop"); + const topMenu = document.querySelector(".headerTop"); if (topMenu) { return topMenu.clientHeight; } return 0; } - var supportsSmoothScroll = "scrollBehavior" in document.documentElement.style; + const supportsSmoothScroll = "scrollBehavior" in document.documentElement.style; - var supportsScrollToOptions = false; + let supportsScrollToOptions = false; 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 get: function () { supportsScrollToOptions = true; @@ -47,9 +55,9 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage /** * Returns value clamped by range [min, max]. * - * @param {number} value clamped value - * @param {number} min begining of range - * @param {number} max ending of range + * @param {number} value - clamped value + * @param {number} min - begining of range + * @param {number} max - ending of range * @return {number} clamped value */ function clamp(value, min, max) { @@ -60,15 +68,15 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage * 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. * - * @param {number} begin1 begining of range 1 - * @param {number} end1 ending of range 1 - * @param {number} begin2 begining of range 2 - * @param {number} end2 ending of range 2 + * @param {number} begin1 - begining of range 1 + * @param {number} end1 - ending of range 1 + * @param {number} begin2 - begining of range 2 + * @param {number} end2 - ending of range 2 * @return {number} delta: <0 move range1 to the left, >0 - to the right */ function fitRange(begin1, end1, begin2, end2) { - var delta1 = begin1 - begin2; - var delta2 = end2 - end1; + const delta1 = begin1 - begin2; + const delta2 = end2 - end1; if (delta1 < 0 && delta1 < delta2) { return -delta1; } else if (delta2 < 0) { @@ -80,7 +88,7 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage /** * 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] */ function ease(t) { @@ -100,41 +108,40 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage * * Tizen 5 Browser/Native: scrolls documentElement (and window); has a document.scrollingElement */ - function DocumentScroller() { - } - - DocumentScroller.prototype = { + class DocumentScroller { get scrollLeft() { return window.pageXOffset; - }, + } + set scrollLeft(val) { window.scroll(val, window.pageYOffset); - }, + } get scrollTop() { return window.pageYOffset; - }, + } + set scrollTop(val) { window.scroll(window.pageXOffset, val); - }, + } get scrollWidth() { return Math.max(document.documentElement.scrollWidth, document.body.scrollWidth); - }, + } get scrollHeight() { return Math.max(document.documentElement.scrollHeight, document.body.scrollHeight); - }, + } get clientWidth() { return Math.min(document.documentElement.clientWidth, document.body.clientWidth); - }, + } get clientHeight() { return Math.min(document.documentElement.clientHeight, document.body.clientHeight); - }, + } - getBoundingClientRect: function() { + getBoundingClientRect() { // Make valid viewport coordinates: documentElement.getBoundingClientRect returns rect of entire document relative to viewport return { left: 0, @@ -142,26 +149,29 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage width: this.clientWidth, height: this.clientHeight }; - }, + } - scrollTo: function() { + scrollTo() { window.scrollTo.apply(window, arguments); } - }; + } - var documentScroller = new DocumentScroller(); + /** + * Default (document) scroller. + */ + const documentScroller = new DocumentScroller(); /** * Returns parent element that can be scrolled. If no such, returns documentElement. * - * @param {HTMLElement} element element for which parent is being searched - * @param {boolean} vertical search for vertical scrollable parent + * @param {HTMLElement} element - element for which parent is being searched + * @param {boolean} vertical - search for vertical scrollable parent */ function getScrollableParent(element, vertical) { if (element) { - var nameScroll = "scrollWidth"; - var nameClient = "clientWidth"; - var nameClass = "scrollX"; + let nameScroll = "scrollWidth"; + let nameClient = "clientWidth"; + let nameClass = "scrollX"; if (vertical) { nameScroll = "scrollHeight"; @@ -169,7 +179,7 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage nameClass = "scrollY"; } - var parent = element.parentElement; + let parent = element.parentElement; while (parent) { // Skip 'emby-scroller' because it scrolls by itself @@ -187,20 +197,20 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage /** * @typedef {Object} ScrollerData - * @property {number} scrollPos current scroll position - * @property {number} scrollSize scroll size - * @property {number} clientSize client size + * @property {number} scrollPos - current scroll position + * @property {number} scrollSize - scroll size + * @property {number} clientSize - client size */ /** * Returns scroll data for specified orientation. * - * @param {HTMLElement} scroller scroller - * @param {boolean} vertical vertical scroll data + * @param {HTMLElement} scroller - scroller + * @param {boolean} vertical - vertical scroll data * @return {ScrollerData} scroll data */ function getScrollerData(scroller, vertical) { - var data = {}; + let data = {}; if (!vertical) { data.scrollPos = scroller.scrollLeft; @@ -218,14 +228,14 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage /** * Returns position of child of scroller for specified orientation. * - * @param {HTMLElement} scroller scroller - * @param {HTMLElement} element child of scroller - * @param {boolean} vertical vertical scroll + * @param {HTMLElement} scroller - scroller + * @param {HTMLElement} element - child of scroller + * @param {boolean} vertical - vertical scroll * @return {number} child position */ function getScrollerChildPos(scroller, element, vertical) { - var elementRect = element.getBoundingClientRect(); - var scrollerRect = scroller.getBoundingClientRect(); + const elementRect = element.getBoundingClientRect(); + const scrollerRect = scroller.getBoundingClientRect(); if (!vertical) { return scroller.scrollLeft + elementRect.left - scrollerRect.left; @@ -237,21 +247,21 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage /** * Returns scroll position for element. * - * @param {ScrollerData} scrollerData scroller data - * @param {number} elementPos child element position - * @param {number} elementSize child element size - * @param {boolean} centered scroll to center + * @param {ScrollerData} scrollerData - scroller data + * @param {number} elementPos - child element position + * @param {number} elementSize - child element size + * @param {boolean} centered - scroll to center * @return {number} scroll position */ function calcScroll(scrollerData, elementPos, elementSize, centered) { - var maxScroll = scrollerData.scrollSize - scrollerData.clientSize; + const maxScroll = scrollerData.scrollSize - scrollerData.clientSize; - var scroll; + let scroll; if (centered) { scroll = elementPos + (elementSize - scrollerData.clientSize) / 2; } 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; } @@ -261,14 +271,14 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage /** * Calls scrollTo function in proper way. * - * @param {HTMLElement} scroller scroller - * @param {ScrollToOptions} options scroll options + * @param {HTMLElement} scroller - scroller + * @param {ScrollToOptions} options - scroll options */ function scrollToHelper(scroller, options) { if ("scrollTo" in scroller) { if (!supportsScrollToOptions) { - var scrollX = (options.left !== undefined ? options.left : scroller.scrollLeft); - var scrollY = (options.top !== undefined ? options.top : scroller.scrollTop); + const scrollX = (options.left !== undefined ? options.left : scroller.scrollLeft); + const scrollY = (options.top !== undefined ? options.top : scroller.scrollTop); scroller.scrollTo(scrollX, scrollY); } else { scroller.scrollTo(options); @@ -286,14 +296,14 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage /** * Performs built-in scroll. * - * @param {HTMLElement} xScroller horizontal scroller - * @param {number} scrollX horizontal coordinate - * @param {HTMLElement} yScroller vertical scroller - * @param {number} scrollY vertical coordinate - * @param {boolean} smooth smooth scrolling + * @param {HTMLElement} xScroller - horizontal scroller + * @param {number} scrollX - horizontal coordinate + * @param {HTMLElement} yScroller - vertical scroller + * @param {number} scrollY - vertical coordinate + * @param {boolean} smooth - smooth scrolling */ function builtinScroll(xScroller, scrollX, yScroller, scrollY, smooth) { - var scrollBehavior = smooth ? "smooth" : "instant"; + const scrollBehavior = smooth ? "smooth" : "instant"; if (xScroller !== yScroller) { scrollToHelper(xScroller, {left: scrollX, behavior: scrollBehavior}); @@ -303,7 +313,7 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage } } - var scrollTimer; + let scrollTimer; /** * Resets scroll timer to stop scrolling. @@ -316,29 +326,29 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage /** * Performs animated scroll. * - * @param {HTMLElement} xScroller horizontal scroller - * @param {number} scrollX horizontal coordinate - * @param {HTMLElement} yScroller vertical scroller - * @param {number} scrollY vertical coordinate + * @param {HTMLElement} xScroller - horizontal scroller + * @param {number} scrollX - horizontal coordinate + * @param {HTMLElement} yScroller - vertical scroller + * @param {number} scrollY - vertical coordinate */ function animateScroll(xScroller, scrollX, yScroller, scrollY) { - var ox = xScroller.scrollLeft; - var oy = yScroller.scrollTop; - var dx = scrollX - ox; - var dy = scrollY - oy; + const ox = xScroller.scrollLeft; + const oy = yScroller.scrollTop; + const dx = scrollX - ox; + const dy = scrollY - oy; if (Math.abs(dx) < Epsilon && Math.abs(dy) < Epsilon) { return; } - var start; + let start; function scrollAnim(currentTimestamp) { start = start || currentTimestamp; - var k = Math.min(1, (currentTimestamp - start) / ScrollTime); + let k = Math.min(1, (currentTimestamp - start) / ScrollTime); if (k === 1) { resetScrollTimer(); @@ -348,8 +358,8 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage k = ease(k); - var x = ox + dx*k; - var y = oy + dy*k; + const x = ox + dx*k; + const y = oy + dy*k; builtinScroll(xScroller, x, yScroller, y, false); @@ -362,11 +372,11 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage /** * Performs scroll. * - * @param {HTMLElement} xScroller horizontal scroller - * @param {number} scrollX horizontal coordinate - * @param {HTMLElement} yScroller vertical scroller - * @param {number} scrollY vertical coordinate - * @param {boolean} smooth smooth scrolling + * @param {HTMLElement} xScroller - horizontal scroller + * @param {number} scrollX - horizontal coordinate + * @param {HTMLElement} yScroller - vertical scroller + * @param {number} scrollY - vertical coordinate + * @param {boolean} smooth - smooth scrolling */ function doScroll(xScroller, scrollX, yScroller, scrollY, smooth) { @@ -403,26 +413,26 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage /** * Returns true if scroll manager is enabled. */ - var isEnabled = function() { + export function isEnabled() { return layoutManager.tv; - }; + } /** * Scrolls the document to a given position. * - * @param {number} scrollX horizontal coordinate - * @param {number} scrollY vertical coordinate - * @param {boolean} [smooth=false] smooth scrolling + * @param {number} scrollX - horizontal coordinate + * @param {number} scrollY - vertical coordinate + * @param {boolean} [smooth=false] - smooth scrolling */ - var scrollTo = function(scrollX, scrollY, smooth) { + export function scrollTo(scrollX, scrollY, smooth) { smooth = !!smooth; // Scroller is document itself by default - var scroller = getScrollableParent(null, false); + const scroller = getScrollableParent(null, false); - var xScrollerData = getScrollerData(scroller, false); - var yScrollerData = getScrollerData(scroller, true); + const xScrollerData = getScrollerData(scroller, false); + const yScrollerData = getScrollerData(scroller, true); scrollX = clamp(Math.round(scrollX), 0, xScrollerData.scrollSize - xScrollerData.clientSize); scrollY = clamp(Math.round(scrollY), 0, yScrollerData.scrollSize - yScrollerData.clientSize); @@ -433,39 +443,39 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage /** * Scrolls the document to a given element. * - * @param {HTMLElement} element target element of scroll task - * @param {boolean} [smooth=false] smooth scrolling + * @param {HTMLElement} element - target element of scroll task + * @param {boolean} [smooth=false] - smooth scrolling */ - var scrollToElement = function(element, smooth) { + export function scrollToElement(element, smooth) { smooth = !!smooth; - var scrollCenterX = true; - var scrollCenterY = true; + let scrollCenterX = true; + let scrollCenterY = true; - var offsetParent = element.offsetParent; + const offsetParent = element.offsetParent; // 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) if (isFixed) { scrollCenterX = scrollCenterY = false; } - var xScroller = getScrollableParent(element, false); - var yScroller = getScrollableParent(element, true); + const xScroller = getScrollableParent(element, false); + const yScroller = getScrollableParent(element, true); - var elementRect = element.getBoundingClientRect(); + const elementRect = element.getBoundingClientRect(); - var xScrollerData = getScrollerData(xScroller, false); - var yScrollerData = getScrollerData(yScroller, true); + const xScrollerData = getScrollerData(xScroller, false); + const yScrollerData = getScrollerData(yScroller, true); - var xPos = getScrollerChildPos(xScroller, element, false); - var yPos = getScrollerChildPos(yScroller, element, true); + const xPos = getScrollerChildPos(xScroller, element, false); + const yPos = getScrollerChildPos(yScroller, element, true); - var scrollX = calcScroll(xScrollerData, xPos, elementRect.width, scrollCenterX); - var scrollY = calcScroll(yScrollerData, yPos, elementRect.height, scrollCenterY); + const scrollX = calcScroll(xScrollerData, xPos, elementRect.width, scrollCenterX); + let scrollY = calcScroll(yScrollerData, yPos, elementRect.height, scrollCenterY); // HACK: Scroll to top for top menu because it is hidden // FIXME: Need a marker to scroll top/bottom @@ -490,9 +500,8 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage }, {capture: true}); } - return { + export default { isEnabled: isEnabled, scrollTo: scrollTo, scrollToElement: scrollToElement }; -}); From 460717c7ef8e3c59cc2530842077f45fee81fd0b Mon Sep 17 00:00:00 2001 From: Dmitry Lyzo Date: Sat, 28 Mar 2020 20:02:22 +0300 Subject: [PATCH 2/6] Migrate AutoFocuser to ES6 --- package.json | 1 + src/components/autoFocuser.js | 45 ++++++++++++++++++----------------- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/package.json b/package.json index 5672ab6d2e..3af6fabbb9 100644 --- a/package.json +++ b/package.json @@ -73,6 +73,7 @@ "presets": ["@babel/preset-env"], "overrides": [{ "test": [ + "src/components/autoFocuser.js", "src/components/cardbuilder/cardBuilder.js", "src/components/filedownloader.js", "src/components/filesystem.js", diff --git a/src/components/autoFocuser.js b/src/components/autoFocuser.js index 6d99009e67..93ebb4b3be 100644 --- a/src/components/autoFocuser.js +++ b/src/components/autoFocuser.js @@ -1,22 +1,29 @@ -define(["focusManager", "layoutManager"], function (focusManager, layoutManager) { - "use strict"; +/* eslint-disable indent */ + +/** + * Module for performing auto-focus. + * @module components/autoFocuser + */ + +import focusManager from "focusManager"; +import layoutManager from "layoutManager"; /** * 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; } /** * Start AutoFocuser */ - function enable() { + export function enable() { if (!isEnabled()) { return; } @@ -28,24 +35,19 @@ define(["focusManager", "layoutManager"], function (focusManager, layoutManager) 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. + * @param {HTMLElement} [container] - element to limit scope + * @returns {HTMLElement} focused element */ - function autoFocus(container) { + export function autoFocus(container) { if (!isEnabled()) { - return; + return null; } container = container || document.body; - var candidates = []; + let candidates = []; if (activeElement) { // These elements are recreated @@ -62,10 +64,10 @@ define(["focusManager", "layoutManager"], function (focusManager, layoutManager) candidates.push(activeElement); } - candidates = candidates.concat(arrayFrom(container.querySelectorAll(".btnResume"))); - candidates = candidates.concat(arrayFrom(container.querySelectorAll(".btnPlay"))); + candidates = candidates.concat(Array.from(container.querySelectorAll(".btnResume"))); + candidates = candidates.concat(Array.from(container.querySelectorAll(".btnPlay"))); - var focusedElement; + let focusedElement; candidates.every(function (element) { if (focusManager.isCurrentlyFocusable(element)) { @@ -79,7 +81,7 @@ define(["focusManager", "layoutManager"], function (focusManager, layoutManager) if (!focusedElement) { // FIXME: Multiple itemsContainers - var itemsContainer = container.querySelector(".itemsContainer"); + const itemsContainer = container.querySelector(".itemsContainer"); if (itemsContainer) { focusedElement = focusManager.autoFocus(itemsContainer); @@ -93,9 +95,8 @@ define(["focusManager", "layoutManager"], function (focusManager, layoutManager) return focusedElement; } - return { + export default { isEnabled: isEnabled, enable: enable, autoFocus: autoFocus }; -}); From 5efc95fd097c7bdcc3139e9fd39bfa305353d0fb Mon Sep 17 00:00:00 2001 From: Dmitry Lyzo Date: Sun, 29 Mar 2020 00:03:15 +0300 Subject: [PATCH 3/6] Migrate DOM-module to ES6 --- package.json | 1 + src/components/dom.js | 163 +++++++++++++++++++++++++++++++----------- 2 files changed, 121 insertions(+), 43 deletions(-) diff --git a/package.json b/package.json index 3af6fabbb9..f6f2436b2a 100644 --- a/package.json +++ b/package.json @@ -75,6 +75,7 @@ "test": [ "src/components/autoFocuser.js", "src/components/cardbuilder/cardBuilder.js", + "src/components/dom.js", "src/components/filedownloader.js", "src/components/filesystem.js", "src/components/input/keyboardnavigation.js", diff --git a/src/components/dom.js b/src/components/dom.js index b91e5b1687..fdc5e607eb 100644 --- a/src/components/dom.js +++ b/src/components/dom.js @@ -1,8 +1,18 @@ -define([], function () { - 'use strict'; +/* eslint-disable indent */ - 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))) { elem = elem.parentNode; @@ -14,8 +24,13 @@ define([], function () { 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 if (!Array.isArray(tagNames)) { tagNames = [tagNames]; @@ -32,9 +47,14 @@ define([], function () { 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) { - - for (var i = 0, length = classNames.length; i < length; i++) { + for (let i = 0, length = classNames.length; i < length; i++) { if (classList.contains(classNames[i])) { return true; } @@ -42,8 +62,13 @@ define([], function () { 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 if (!Array.isArray(classNames)) { classNames = [classNames]; @@ -60,9 +85,9 @@ define([], function () { return elem; } - var supportsCaptureOption = false; + let supportsCaptureOption = false; try { - var opts = Object.defineProperty({}, 'capture', { + const opts = Object.defineProperty({}, 'capture', { // eslint-disable-next-line getter-return get: function () { supportsCaptureOption = true; @@ -73,29 +98,58 @@ define([], function () { 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) { optionsOrCapture = optionsOrCapture.capture; } 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) { optionsOrCapture = optionsOrCapture.capture; } 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() { windowSize = null; } - function getWindowSize() { + /** + * Returns window size. + * @returns {Object} Window size + */ + export function getWindowSize() { if (!windowSize) { windowSize = { innerHeight: window.innerHeight, @@ -104,46 +158,60 @@ define([], function () { if (!windowSizeEventsBound) { windowSizeEventsBound = true; - addEventListenerWithOptions(window, "orientationchange", clearWindowSize, { passive: true }); - addEventListenerWithOptions(window, 'resize', clearWindowSize, { passive: true }); + addEventListener(window, "orientationchange", clearWindowSize, { passive: true }); + addEventListener(window, 'resize', clearWindowSize, { passive: true }); } } return windowSize; } - var standardWidths = [480, 720, 1280, 1440, 1920, 2560, 3840, 5120, 7680]; - function getScreenWidth() { - var width = window.innerWidth; - var height = window.innerHeight; + /** + * Standard screen widths. + */ + 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) { 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); })[0]; 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) { return _animationEvent; } - var t; - var el = document.createElement("div"); - var animations = { + const el = document.createElement("div"); + const animations = { "animation": "animationend", "OAnimation": "oAnimationEnd", "MozAnimation": "animationend", "WebkitAnimation": "webkitAnimationEnd" }; - for (t in animations) { + for (let t in animations) { if (el.style[t] !== undefined) { _animationEvent = animations[t]; return animations[t]; @@ -154,26 +222,36 @@ define([], function () { 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'); } - 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) { return _transitionEvent; } - var t; - var el = document.createElement("div"); - var transitions = { + const el = document.createElement("div"); + const transitions = { "transition": "transitionend", "OTransition": "oTransitionEnd", "MozTransition": "transitionend", "WebkitTransition": "webkitTransitionEnd" }; - for (t in transitions) { + for (let t in transitions) { if (el.style[t] !== undefined) { _transitionEvent = transitions[t]; return transitions[t]; @@ -184,16 +262,15 @@ define([], function () { return _transitionEvent; } - return { + export default { parentWithAttribute: parentWithAttribute, parentWithClass: parentWithClass, parentWithTag: parentWithTag, - addEventListener: addEventListenerWithOptions, - removeEventListener: removeEventListenerWithOptions, + addEventListener: addEventListener, + removeEventListener: removeEventListener, getWindowSize: getWindowSize, getScreenWidth: getScreenWidth, whichTransitionEvent: whichTransitionEvent, whichAnimationEvent: whichAnimationEvent, whichAnimationCancelEvent: whichAnimationCancelEvent }; -}); From eb047175be762e69e0fcefde26199e423a7ed87b Mon Sep 17 00:00:00 2001 From: Dmitry Lyzo Date: Sun, 29 Mar 2020 00:06:27 +0300 Subject: [PATCH 4/6] Add default export for compatibility --- src/components/cardbuilder/cardBuilder.js | 11 +++++++++++ src/components/input/keyboardnavigation.js | 15 +++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/components/cardbuilder/cardBuilder.js b/src/components/cardbuilder/cardBuilder.js index 9d86bc9d7c..1249f802af 100644 --- a/src/components/cardbuilder/cardBuilder.js +++ b/src/components/cardbuilder/cardBuilder.js @@ -1853,3 +1853,14 @@ import 'programStyles'; cell.removeAttribute('data-seriestimerid'); } } + +export default { + getCardsHtml: getCardsHtml, + getDefaultBackgroundClass: getDefaultBackgroundClass, + getDefaultText: getDefaultText, + buildCards: buildCards, + onUserDataChanged: onUserDataChanged, + onTimerCreated: onTimerCreated, + onTimerCancelled: onTimerCancelled, + onSeriesTimerCancelled: onSeriesTimerCancelled +}; diff --git a/src/components/input/keyboardnavigation.js b/src/components/input/keyboardnavigation.js index bdcb733179..caddf46797 100644 --- a/src/components/input/keyboardnavigation.js +++ b/src/components/input/keyboardnavigation.js @@ -1,3 +1,8 @@ +/** + * Module for performing keyboard navigation. + * @module components/input/keyboardnavigation + */ + import inputManager from "inputManager"; import layoutManager from "layoutManager"; @@ -55,7 +60,7 @@ if (!hasFieldKey) { /** * Returns key name from event. * - * @param {KeyboardEvent} event keyboard event + * @param {KeyboardEvent} event - keyboard event * @return {string} key name */ export function getKeyName(event) { @@ -65,7 +70,7 @@ export function getKeyName(event) { /** * 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 */ export function isNavigationKey(key) { @@ -155,3 +160,9 @@ function attachGamepadScript(e) { // No need to check for gamepads manually at load time, the eventhandler will be fired for that window.addEventListener("gamepadconnected", attachGamepadScript); + +export default { + enable: enable, + getKeyName: getKeyName, + isNavigationKey: isNavigationKey +}; From a1cc9778725bc8e4eaf4c0408919f39b4640c02b Mon Sep 17 00:00:00 2001 From: Dmitry Lyzo Date: Tue, 31 Mar 2020 18:59:12 +0300 Subject: [PATCH 5/6] Update documentation --- src/components/autoFocuser.js | 6 +- src/components/dom.js | 52 +++++------ src/components/scrollManager.js | 148 +++++++++++++++++++++----------- 3 files changed, 125 insertions(+), 81 deletions(-) diff --git a/src/components/autoFocuser.js b/src/components/autoFocuser.js index 93ebb4b3be..a469eb8854 100644 --- a/src/components/autoFocuser.js +++ b/src/components/autoFocuser.js @@ -21,7 +21,7 @@ import layoutManager from "layoutManager"; } /** - * Start AutoFocuser + * Start AutoFocuser. */ export function enable() { if (!isEnabled()) { @@ -37,8 +37,8 @@ import layoutManager from "layoutManager"; /** * Set focus on a suitable element, taking into account the previously selected. - * @param {HTMLElement} [container] - element to limit scope - * @returns {HTMLElement} focused element + * @param {HTMLElement} [container] - Element to limit scope. + * @returns {HTMLElement} Focused element. */ export function autoFocus(container) { if (!isEnabled()) { diff --git a/src/components/dom.js b/src/components/dom.js index fdc5e607eb..3fe4287320 100644 --- a/src/components/dom.js +++ b/src/components/dom.js @@ -7,10 +7,10 @@ /** * 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 + * @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))) { @@ -26,9 +26,9 @@ /** * 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 + * @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 @@ -49,9 +49,9 @@ /** * 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 + * @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) { for (let i = 0, length = classNames.length; i < length; i++) { @@ -64,9 +64,9 @@ /** * 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 + * @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 @@ -100,10 +100,10 @@ /** * 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 + * @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 || {}; @@ -115,10 +115,10 @@ /** * 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 + * @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 || {}; @@ -147,7 +147,7 @@ /** * Returns window size. - * @returns {Object} Window size + * @returns {Object} Window size. */ export function getWindowSize() { if (!windowSize) { @@ -173,7 +173,7 @@ /** * Returns screen width. - * @returns {number} Screen width + * @returns {number} Screen width. */ export function getScreenWidth() { let width = window.innerWidth; @@ -197,7 +197,7 @@ /** * Returns name of animation end event. - * @returns {string} Name of animation end event + * @returns {string} Name of animation end event. */ export function whichAnimationEvent() { if (_animationEvent) { @@ -224,7 +224,7 @@ /** * Returns name of animation cancel event. - * @returns {string} Name of animation cancel event + * @returns {string} Name of animation cancel event. */ export function whichAnimationCancelEvent() { return whichAnimationEvent().replace('animationend', 'animationcancel').replace('AnimationEnd', 'AnimationCancel'); @@ -237,7 +237,7 @@ /** * Returns name of transition end event. - * @returns {string} Name of transition end event + * @returns {string} Name of transition end event. */ export function whichTransitionEvent() { if (_transitionEvent) { diff --git a/src/components/scrollManager.js b/src/components/scrollManager.js index 96317fa998..037ca5b059 100644 --- a/src/components/scrollManager.js +++ b/src/components/scrollManager.js @@ -24,7 +24,7 @@ import layoutManager from "layoutManager"; * Returns minimum vertical scroll. * Scroll less than that value will be zeroed. * - * @return {number} minimum vertical scroll + * @return {number} Minimum vertical scroll. */ function minimumScrollY() { const topMenu = document.querySelector(".headerTop"); @@ -55,10 +55,10 @@ import layoutManager from "layoutManager"; /** * Returns value clamped by range [min, max]. * - * @param {number} value - clamped value - * @param {number} min - begining of range - * @param {number} max - ending of range - * @return {number} clamped value + * @param {number} value - Clamped value. + * @param {number} min - Begining of range. + * @param {number} max - Ending of range. + * @return {number} Clamped value. */ function clamp(value, min, max) { return value <= min ? min : value >= max ? max : value; @@ -68,11 +68,11 @@ import layoutManager from "layoutManager"; * 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. * - * @param {number} begin1 - begining of range 1 - * @param {number} end1 - ending of range 1 - * @param {number} begin2 - begining of range 2 - * @param {number} end2 - ending of range 2 - * @return {number} delta: <0 move range1 to the left, >0 - to the right + * @param {number} begin1 - Begining of range 1. + * @param {number} end1 - Ending of range 1. + * @param {number} begin2 - Begining of range 2. + * @param {number} end2 - Ending of range 2. + * @return {number} Delta: <0 move range1 to the left, >0 - to the right. */ function fitRange(begin1, end1, begin2, end2) { const delta1 = begin1 - begin2; @@ -88,13 +88,21 @@ import layoutManager from "layoutManager"; /** * Ease value. * - * @param {number} t - value in range [0, 1] - * @return {number} eased value in range [0, 1] + * @param {number} t - Value in range [0, 1]. + * @return {number} Eased value in range [0, 1]. */ function ease(t) { 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. * @@ -109,6 +117,10 @@ import layoutManager from "layoutManager"; * Tizen 5 Browser/Native: scrolls documentElement (and window); has a document.scrollingElement */ class DocumentScroller { + /** + * Horizontal scroll position. + * @type {number} + */ get scrollLeft() { return window.pageXOffset; } @@ -117,6 +129,10 @@ import layoutManager from "layoutManager"; window.scroll(val, window.pageYOffset); } + /** + * Vertical scroll position. + * @type {number} + */ get scrollTop() { return window.pageYOffset; } @@ -125,22 +141,42 @@ import layoutManager from "layoutManager"; window.scroll(window.pageXOffset, val); } + /** + * Horizontal scroll size (scroll width). + * @type {number} + */ get scrollWidth() { return Math.max(document.documentElement.scrollWidth, document.body.scrollWidth); } + /** + * Vertical scroll size (scroll height). + * @type {number} + */ get scrollHeight() { return Math.max(document.documentElement.scrollHeight, document.body.scrollHeight); } + /** + * Horizontal client size (client width). + * @type {number} + */ get clientWidth() { return Math.min(document.documentElement.clientWidth, document.body.clientWidth); } + /** + * Vertical client size (client height). + * @type {number} + */ get clientHeight() { return Math.min(document.documentElement.clientHeight, document.body.clientHeight); } + /** + * Returns bounding client rect. + * @return {Rect} Bounding client rect. + */ getBoundingClientRect() { // Make valid viewport coordinates: documentElement.getBoundingClientRect returns rect of entire document relative to viewport return { @@ -151,6 +187,10 @@ import layoutManager from "layoutManager"; }; } + /** + * Scrolls window. + * @param {...mixed} args See window.scrollTo. + */ scrollTo() { window.scrollTo.apply(window, arguments); } @@ -162,10 +202,11 @@ import layoutManager from "layoutManager"; const documentScroller = new DocumentScroller(); /** - * Returns parent element that can be scrolled. If no such, returns documentElement. + * Returns parent element that can be scrolled. If no such, returns document scroller. * - * @param {HTMLElement} element - element for which parent is being searched - * @param {boolean} vertical - search for vertical scrollable parent + * @param {HTMLElement} element - Element for which parent is being searched. + * @param {boolean} vertical - Search for vertical scrollable parent. + * @param {HTMLElement|DocumentScroller} Parent element that can be scrolled or document scroller. */ function getScrollableParent(element, vertical) { if (element) { @@ -197,17 +238,17 @@ import layoutManager from "layoutManager"; /** * @typedef {Object} ScrollerData - * @property {number} scrollPos - current scroll position - * @property {number} scrollSize - scroll size - * @property {number} clientSize - client size + * @property {number} scrollPos - Current scroll position. + * @property {number} scrollSize - Scroll size. + * @property {number} clientSize - Client size. */ /** - * Returns scroll data for specified orientation. + * Returns scroller data for specified orientation. * - * @param {HTMLElement} scroller - scroller - * @param {boolean} vertical - vertical scroll data - * @return {ScrollerData} scroll data + * @param {HTMLElement} scroller - Scroller. + * @param {boolean} vertical - Vertical scroller data. + * @return {ScrollerData} Scroller data. */ function getScrollerData(scroller, vertical) { let data = {}; @@ -228,10 +269,10 @@ import layoutManager from "layoutManager"; /** * Returns position of child of scroller for specified orientation. * - * @param {HTMLElement} scroller - scroller - * @param {HTMLElement} element - child of scroller - * @param {boolean} vertical - vertical scroll - * @return {number} child position + * @param {HTMLElement} scroller - Scroller. + * @param {HTMLElement} element - Child of scroller. + * @param {boolean} vertical - Vertical scroll. + * @return {number} Child position. */ function getScrollerChildPos(scroller, element, vertical) { const elementRect = element.getBoundingClientRect(); @@ -247,11 +288,11 @@ import layoutManager from "layoutManager"; /** * Returns scroll position for element. * - * @param {ScrollerData} scrollerData - scroller data - * @param {number} elementPos - child element position - * @param {number} elementSize - child element size - * @param {boolean} centered - scroll to center - * @return {number} scroll position + * @param {ScrollerData} scrollerData - Scroller data. + * @param {number} elementPos - Child element position. + * @param {number} elementSize - Child element size. + * @param {boolean} centered - Scroll to center. + * @return {number} Scroll position. */ function calcScroll(scrollerData, elementPos, elementSize, centered) { const maxScroll = scrollerData.scrollSize - scrollerData.clientSize; @@ -271,8 +312,8 @@ import layoutManager from "layoutManager"; /** * Calls scrollTo function in proper way. * - * @param {HTMLElement} scroller - scroller - * @param {ScrollToOptions} options - scroll options + * @param {HTMLElement} scroller - Scroller. + * @param {ScrollToOptions} options - Scroll options. */ function scrollToHelper(scroller, options) { if ("scrollTo" in scroller) { @@ -296,11 +337,11 @@ import layoutManager from "layoutManager"; /** * Performs built-in scroll. * - * @param {HTMLElement} xScroller - horizontal scroller - * @param {number} scrollX - horizontal coordinate - * @param {HTMLElement} yScroller - vertical scroller - * @param {number} scrollY - vertical coordinate - * @param {boolean} smooth - smooth scrolling + * @param {HTMLElement} xScroller - Horizontal scroller. + * @param {number} scrollX - Horizontal coordinate. + * @param {HTMLElement} yScroller - Vertical scroller. + * @param {number} scrollY - Vertical coordinate. + * @param {boolean} smooth - Smooth scrolling. */ function builtinScroll(xScroller, scrollX, yScroller, scrollY, smooth) { const scrollBehavior = smooth ? "smooth" : "instant"; @@ -313,6 +354,9 @@ import layoutManager from "layoutManager"; } } + /** + * Requested frame for animated scroll. + */ let scrollTimer; /** @@ -326,10 +370,10 @@ import layoutManager from "layoutManager"; /** * Performs animated scroll. * - * @param {HTMLElement} xScroller - horizontal scroller - * @param {number} scrollX - horizontal coordinate - * @param {HTMLElement} yScroller - vertical scroller - * @param {number} scrollY - vertical coordinate + * @param {HTMLElement} xScroller - Horizontal scroller. + * @param {number} scrollX - Horizontal coordinate. + * @param {HTMLElement} yScroller - Vertical scroller. + * @param {number} scrollY - Vertical coordinate. */ function animateScroll(xScroller, scrollX, yScroller, scrollY) { @@ -372,11 +416,11 @@ import layoutManager from "layoutManager"; /** * Performs scroll. * - * @param {HTMLElement} xScroller - horizontal scroller - * @param {number} scrollX - horizontal coordinate - * @param {HTMLElement} yScroller - vertical scroller - * @param {number} scrollY - vertical coordinate - * @param {boolean} smooth - smooth scrolling + * @param {HTMLElement} xScroller - Horizontal scroller. + * @param {number} scrollX - Horizontal coordinate. + * @param {HTMLElement} yScroller - Vertical scroller. + * @param {number} scrollY - Vertical coordinate. + * @param {boolean} smooth - Smooth scrolling. */ function doScroll(xScroller, scrollX, yScroller, scrollY, smooth) { @@ -420,9 +464,9 @@ import layoutManager from "layoutManager"; /** * Scrolls the document to a given position. * - * @param {number} scrollX - horizontal coordinate - * @param {number} scrollY - vertical coordinate - * @param {boolean} [smooth=false] - smooth scrolling + * @param {number} scrollX - Horizontal coordinate. + * @param {number} scrollY - Vertical coordinate. + * @param {boolean} [smooth=false] - Smooth scrolling. */ export function scrollTo(scrollX, scrollY, smooth) { @@ -443,8 +487,8 @@ import layoutManager from "layoutManager"; /** * Scrolls the document to a given element. * - * @param {HTMLElement} element - target element of scroll task - * @param {boolean} [smooth=false] - smooth scrolling + * @param {HTMLElement} element - Target element of scroll task. + * @param {boolean} [smooth=false] - Smooth scrolling. */ export function scrollToElement(element, smooth) { From 8789b1b69b2b5298fe90aaee51ce7ec1f151622c Mon Sep 17 00:00:00 2001 From: Dmitry Lyzo Date: Tue, 31 Mar 2020 19:07:03 +0300 Subject: [PATCH 6/6] Update documentation --- src/components/input/keyboardnavigation.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/input/keyboardnavigation.js b/src/components/input/keyboardnavigation.js index caddf46797..d356854a3e 100644 --- a/src/components/input/keyboardnavigation.js +++ b/src/components/input/keyboardnavigation.js @@ -60,8 +60,8 @@ if (!hasFieldKey) { /** * Returns key name from event. * - * @param {KeyboardEvent} event - keyboard event - * @return {string} key name + * @param {KeyboardEvent} event - Keyboard event. + * @return {string} Key name. */ export function getKeyName(event) { return KeyNames[event.keyCode] || event.key; @@ -70,8 +70,8 @@ export function getKeyName(event) { /** * Returns _true_ if key is used for navigation. * - * @param {string} key - key name - * @return {boolean} _true_ if key is used for navigation + * @param {string} key - Key name. + * @return {boolean} _true_ if key is used for navigation. */ export function isNavigationKey(key) { return NavigationKeys.indexOf(key) != -1;