mirror of
https://github.com/jellyfin/jellyfin-web.git
synced 2025-02-25 08:51:07 +00:00
Merge pull request #1123 from MrTimscampi/headroom
Move headroom to bundle
This commit is contained in:
commit
4185ae6925
@ -61,6 +61,7 @@
|
||||
"document-register-element": "^1.14.3",
|
||||
"fast-text-encoding": "^1.0.1",
|
||||
"flv.js": "^1.5.0",
|
||||
"headroom.js": "^0.11.0",
|
||||
"hls.js": "^0.13.1",
|
||||
"howler": "^2.1.3",
|
||||
"intersection-observer": "^0.7.0",
|
||||
|
@ -96,3 +96,16 @@ div[data-role=page] {
|
||||
margin-right: auto;
|
||||
width: 85%;
|
||||
}
|
||||
|
||||
.headroom {
|
||||
will-change: transform;
|
||||
transition: transform 200ms linear;
|
||||
}
|
||||
|
||||
.headroom--pinned {
|
||||
transform: translateY(0%);
|
||||
}
|
||||
|
||||
.headroom--unpinned {
|
||||
transform: translateY(-100%);
|
||||
}
|
||||
|
@ -146,3 +146,9 @@ var screenfull = require("screenfull");
|
||||
_define("screenfull", function () {
|
||||
return screenfull;
|
||||
});
|
||||
|
||||
// headroom.js
|
||||
var headroom = require("headroom.js/dist/headroom");
|
||||
_define("headroom", function () {
|
||||
return headroom;
|
||||
});
|
||||
|
@ -1,11 +0,0 @@
|
||||
.headroom {
|
||||
transition: transform 140ms linear;
|
||||
}
|
||||
|
||||
.headroom--pinned {
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.headroom--unpinned:not(.headroomDisabled) {
|
||||
transform: translateY(-100%);
|
||||
}
|
@ -1,343 +0,0 @@
|
||||
/*!
|
||||
* headroom.js v0.7.0 - Give your page some headroom. Hide your header until you need it
|
||||
* Copyright (c) 2014 Nick Williams - http://wicky.nillia.ms/headroom.js
|
||||
* License: MIT
|
||||
*/
|
||||
|
||||
define(['dom', 'layoutManager', 'browser', 'css!./headroom'], function (dom, layoutManager, browser) {
|
||||
|
||||
'use strict';
|
||||
|
||||
/* exported features */
|
||||
|
||||
var requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame;
|
||||
|
||||
/**
|
||||
* Handles debouncing of events via requestAnimationFrame
|
||||
* @see http://www.html5rocks.com/en/tutorials/speed/animations/
|
||||
* @param {Function} callback The callback to handle whichever event
|
||||
*/
|
||||
function Debouncer(callback) {
|
||||
this.callback = callback;
|
||||
this.ticking = false;
|
||||
}
|
||||
Debouncer.prototype = {
|
||||
constructor: Debouncer,
|
||||
|
||||
/**
|
||||
* dispatches the event to the supplied callback
|
||||
* @private
|
||||
*/
|
||||
update: function () {
|
||||
if (this.callback) {
|
||||
this.callback();
|
||||
}
|
||||
this.ticking = false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Attach this as the event listeners
|
||||
*/
|
||||
handleEvent: function () {
|
||||
if (!this.ticking) {
|
||||
requestAnimationFrame(this.rafCallback || (this.rafCallback = this.update.bind(this)));
|
||||
this.ticking = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function onHeadroomClearedExternally() {
|
||||
this.state = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* UI enhancement for fixed headers.
|
||||
* Hides header when scrolling down
|
||||
* Shows header when scrolling up
|
||||
* @constructor
|
||||
* @param {DOMElement} elem the header element
|
||||
* @param {Object} options options for the widget
|
||||
*/
|
||||
function Headroom(elems, options) {
|
||||
options = Object.assign(Headroom.options, options || {});
|
||||
|
||||
this.lastKnownScrollY = 0;
|
||||
this.elems = elems;
|
||||
|
||||
this.scroller = options.scroller;
|
||||
|
||||
this.debouncer = onScroll.bind(this);
|
||||
this.offset = options.offset;
|
||||
this.initialised = false;
|
||||
|
||||
this.initialClass = options.initialClass;
|
||||
this.unPinnedClass = options.unPinnedClass;
|
||||
this.pinnedClass = options.pinnedClass;
|
||||
|
||||
this.state = 'clear';
|
||||
|
||||
this.options = {
|
||||
offset: 0,
|
||||
scroller: window,
|
||||
initialClass: 'headroom',
|
||||
unPinnedClass: 'headroom--unpinned',
|
||||
pinnedClass: 'headroom--pinned'
|
||||
};
|
||||
|
||||
this.add = function (elem) {
|
||||
|
||||
if (browser.supportsCssAnimation()) {
|
||||
elem.classList.add(this.initialClass);
|
||||
elem.addEventListener('clearheadroom', onHeadroomClearedExternally.bind(this));
|
||||
this.elems.push(elem);
|
||||
}
|
||||
};
|
||||
|
||||
this.remove = function (elem) {
|
||||
|
||||
elem.classList.remove(this.unPinnedClass);
|
||||
elem.classList.remove(this.initialClass);
|
||||
elem.classList.remove(this.pinnedClass);
|
||||
|
||||
var i = this.elems.indexOf(elem);
|
||||
if (i !== -1) {
|
||||
this.elems.splice(i, 1);
|
||||
}
|
||||
};
|
||||
|
||||
this.pause = function () {
|
||||
this.paused = true;
|
||||
};
|
||||
|
||||
this.resume = function () {
|
||||
this.paused = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Unattaches events and removes any classes that were added
|
||||
*/
|
||||
this.destroy = function () {
|
||||
|
||||
this.initialised = false;
|
||||
|
||||
for (var i = 0, length = this.elems.length; i < length; i++) {
|
||||
|
||||
var classList = this.elems[i].classList;
|
||||
|
||||
classList.remove(this.unPinnedClass);
|
||||
classList.remove(this.initialClass);
|
||||
classList.remove(this.pinnedClass);
|
||||
}
|
||||
|
||||
var scrollEventName = this.scroller.getScrollEventName ? this.scroller.getScrollEventName() : 'scroll';
|
||||
|
||||
dom.removeEventListener(this.scroller, scrollEventName, this.debouncer, {
|
||||
capture: false,
|
||||
passive: true
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Attaches the scroll event
|
||||
* @private
|
||||
*/
|
||||
this.attachEvent = function () {
|
||||
if (!this.initialised) {
|
||||
this.lastKnownScrollY = this.getScrollY();
|
||||
this.initialised = true;
|
||||
|
||||
var scrollEventName = this.scroller.getScrollEventName ? this.scroller.getScrollEventName() : 'scroll';
|
||||
|
||||
dom.addEventListener(this.scroller, scrollEventName, this.debouncer, {
|
||||
capture: false,
|
||||
passive: true
|
||||
});
|
||||
|
||||
this.update();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Unpins the header if it's currently pinned
|
||||
*/
|
||||
this.clear = function () {
|
||||
|
||||
if (this.state === 'clear') {
|
||||
return;
|
||||
}
|
||||
|
||||
this.state = 'clear';
|
||||
|
||||
var unpinnedClass = this.unPinnedClass;
|
||||
var pinnedClass = this.pinnedClass;
|
||||
|
||||
for (var i = 0, length = this.elems.length; i < length; i++) {
|
||||
var classList = this.elems[i].classList;
|
||||
|
||||
classList.remove(unpinnedClass);
|
||||
//classList.remove(pinnedClass);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Unpins the header if it's currently pinned
|
||||
*/
|
||||
this.pin = function () {
|
||||
|
||||
if (this.state === 'pin') {
|
||||
return;
|
||||
}
|
||||
|
||||
this.state = 'pin';
|
||||
|
||||
var unpinnedClass = this.unPinnedClass;
|
||||
var pinnedClass = this.pinnedClass;
|
||||
|
||||
for (var i = 0, length = this.elems.length; i < length; i++) {
|
||||
var classList = this.elems[i].classList;
|
||||
|
||||
classList.remove(unpinnedClass);
|
||||
classList.add(pinnedClass);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Unpins the header if it's currently pinned
|
||||
*/
|
||||
this.unpin = function () {
|
||||
|
||||
if (this.state === 'unpin') {
|
||||
return;
|
||||
}
|
||||
|
||||
this.state = 'unpin';
|
||||
|
||||
var unpinnedClass = this.unPinnedClass;
|
||||
var pinnedClass = this.pinnedClass;
|
||||
|
||||
for (var i = 0, length = this.elems.length; i < length; i++) {
|
||||
var classList = this.elems[i].classList;
|
||||
|
||||
classList.add(unpinnedClass);
|
||||
//classList.remove(pinnedClass);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the Y scroll position
|
||||
* @see https://developer.mozilla.org/en-US/docs/Web/API/Window.scrollY
|
||||
* @return {Number} pixels the page has scrolled along the Y-axis
|
||||
*/
|
||||
this.getScrollY = function () {
|
||||
|
||||
var scroller = this.scroller;
|
||||
|
||||
if (scroller.getScrollPosition) {
|
||||
return scroller.getScrollPosition();
|
||||
}
|
||||
|
||||
var pageYOffset = scroller.pageYOffset;
|
||||
if (pageYOffset !== undefined) {
|
||||
return pageYOffset;
|
||||
}
|
||||
|
||||
var scrollTop = scroller.scrollTop;
|
||||
if (scrollTop !== undefined) {
|
||||
return scrollTop;
|
||||
}
|
||||
|
||||
return (document.documentElement || document.body).scrollTop;
|
||||
};
|
||||
|
||||
/**
|
||||
* determine if it is appropriate to unpin
|
||||
* @param {int} currentScrollY the current y scroll position
|
||||
* @return {bool} true if should unpin, false otherwise
|
||||
*/
|
||||
this.shouldUnpin = function (currentScrollY) {
|
||||
var scrollingDown = currentScrollY > this.lastKnownScrollY;
|
||||
var pastOffset = currentScrollY >= this.offset;
|
||||
|
||||
return scrollingDown && pastOffset;
|
||||
};
|
||||
|
||||
/**
|
||||
* determine if it is appropriate to pin
|
||||
* @param {int} currentScrollY the current y scroll position
|
||||
* @return {bool} true if should pin, false otherwise
|
||||
*/
|
||||
this.shouldPin = function (currentScrollY) {
|
||||
var scrollingUp = currentScrollY < this.lastKnownScrollY;
|
||||
var pastOffset = currentScrollY <= this.offset;
|
||||
|
||||
return scrollingUp || pastOffset;
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles updating the state of the widget
|
||||
*/
|
||||
this.update = function () {
|
||||
|
||||
if (this.paused) {
|
||||
return;
|
||||
}
|
||||
|
||||
var currentScrollY = this.getScrollY();
|
||||
|
||||
var lastKnownScrollY = this.lastKnownScrollY;
|
||||
|
||||
var isTv = layoutManager.tv;
|
||||
|
||||
if (currentScrollY <= (isTv ? 120 : 10)) {
|
||||
this.clear();
|
||||
} else if (this.shouldUnpin(currentScrollY)) {
|
||||
this.unpin();
|
||||
} else if (this.shouldPin(currentScrollY)) {
|
||||
|
||||
var toleranceExceeded = Math.abs(currentScrollY - lastKnownScrollY) >= 14;
|
||||
|
||||
if (currentScrollY && isTv) {
|
||||
this.unpin();
|
||||
} else if (toleranceExceeded) {
|
||||
this.clear();
|
||||
}
|
||||
} else if (isTv) {
|
||||
//this.clear();
|
||||
}
|
||||
|
||||
this.lastKnownScrollY = currentScrollY;
|
||||
};
|
||||
|
||||
if (browser.supportsCssAnimation()) {
|
||||
for (var i = 0, length = this.elems.length; i < length; i++) {
|
||||
this.elems[i].classList.add(this.initialClass);
|
||||
this.elems[i].addEventListener('clearheadroom', onHeadroomClearedExternally.bind(this));
|
||||
}
|
||||
|
||||
this.attachEvent();
|
||||
}
|
||||
}
|
||||
|
||||
function onScroll() {
|
||||
|
||||
if (this.paused) {
|
||||
return;
|
||||
}
|
||||
|
||||
requestAnimationFrame(this.rafCallback || (this.rafCallback = this.update.bind(this)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Default options
|
||||
* @type {Object}
|
||||
*/
|
||||
Headroom.options = {
|
||||
offset: 0,
|
||||
scroller: window,
|
||||
initialClass: 'headroom',
|
||||
unPinnedClass: 'headroom--unpinned',
|
||||
pinnedClass: 'headroom--pinned'
|
||||
};
|
||||
|
||||
return Headroom;
|
||||
});
|
@ -96,17 +96,6 @@ define(['scroller', 'dom', 'layoutManager', 'inputManager', 'focusManager', 'bro
|
||||
}
|
||||
}
|
||||
|
||||
function initHeadroom(elem) {
|
||||
require(['headroom'], function (Headroom) {
|
||||
var headroom = new Headroom([], {
|
||||
scroller: elem
|
||||
});
|
||||
|
||||
headroom.add(document.querySelector('.skinHeader'));
|
||||
elem.headroom = headroom;
|
||||
});
|
||||
}
|
||||
|
||||
ScrollerPrototype.attachedCallback = function () {
|
||||
if (this.getAttribute('data-navcommands')) {
|
||||
inputManager.on(this, onInputCommand);
|
||||
@ -120,8 +109,6 @@ define(['scroller', 'dom', 'layoutManager', 'inputManager', 'focusManager', 'bro
|
||||
slider.style['white-space'] = 'nowrap';
|
||||
}
|
||||
|
||||
var bindHeader = this.getAttribute('data-bindheader') === 'true';
|
||||
|
||||
var scrollFrame = this;
|
||||
var enableScrollButtons = layoutManager.desktop && horizontal && this.getAttribute('data-scrollbuttons') !== 'false';
|
||||
|
||||
@ -137,7 +124,7 @@ define(['scroller', 'dom', 'layoutManager', 'inputManager', 'focusManager', 'bro
|
||||
dragHandle: 1,
|
||||
autoImmediate: true,
|
||||
skipSlideToWhenVisible: this.getAttribute('data-skipfocuswhenvisible') === 'true',
|
||||
dispatchScrollEvent: enableScrollButtons || bindHeader || this.getAttribute('data-scrollevent') === 'true',
|
||||
dispatchScrollEvent: enableScrollButtons || this.getAttribute('data-scrollevent') === 'true',
|
||||
hideScrollbar: enableScrollButtons || this.getAttribute('data-hidescrollbar') === 'true',
|
||||
allowNativeSmoothScroll: this.getAttribute('data-allownativesmoothscroll') === 'true' && !enableScrollButtons,
|
||||
allowNativeScroll: !enableScrollButtons,
|
||||
@ -155,10 +142,6 @@ define(['scroller', 'dom', 'layoutManager', 'inputManager', 'focusManager', 'bro
|
||||
initCenterFocus(this, this.scroller);
|
||||
}
|
||||
|
||||
if (bindHeader && layoutManager.mobile) {
|
||||
initHeadroom(this);
|
||||
}
|
||||
|
||||
if (enableScrollButtons) {
|
||||
loadScrollButtons(this);
|
||||
}
|
||||
|
@ -733,8 +733,8 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", "
|
||||
|
||||
function initHeadRoom(elem) {
|
||||
require(["headroom"], function (Headroom) {
|
||||
var headroom = new Headroom([], {});
|
||||
headroom.add(elem);
|
||||
var headroom = new Headroom(elem);
|
||||
headroom.init();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -350,11 +350,6 @@ var AppInfo = {};
|
||||
return layoutManager;
|
||||
}
|
||||
|
||||
function createWindowHeadroom(Headroom) {
|
||||
var headroom = new Headroom([], {});
|
||||
return headroom;
|
||||
}
|
||||
|
||||
function createSharedAppFooter(appFooter) {
|
||||
return new appFooter({});
|
||||
}
|
||||
@ -707,7 +702,8 @@ var AppInfo = {};
|
||||
"fast-text-encoding",
|
||||
"intersection-observer",
|
||||
"classlist-polyfill",
|
||||
"screenfull"
|
||||
"screenfull",
|
||||
"headroom"
|
||||
]
|
||||
},
|
||||
urlArgs: urlArgs,
|
||||
@ -766,7 +762,6 @@ var AppInfo = {};
|
||||
|
||||
// TODO remove these libraries
|
||||
// all of these have been modified so we need to fix that first
|
||||
define("headroom", [componentsPath + "/headroom/headroom"], returnFirstDependency);
|
||||
define("scroller", [componentsPath + "/scroller"], returnFirstDependency);
|
||||
define("navdrawer", [componentsPath + "/navdrawer/navdrawer"], returnFirstDependency);
|
||||
|
||||
|
13
yarn.lock
13
yarn.lock
@ -5527,6 +5527,11 @@ he@1.2.x, he@^1.2.0:
|
||||
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
|
||||
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
|
||||
|
||||
headroom.js@^0.11.0:
|
||||
version "0.11.0"
|
||||
resolved "https://registry.yarnpkg.com/headroom.js/-/headroom.js-0.11.0.tgz#26547a932025e4243abf8ace001b4ce5e110ed20"
|
||||
integrity sha512-yI4ciZRD1WH22wa5uJDg2kMtRvhJwUJWo2l41Eby0BoAD+lzXL98lf5jDFxP4Q5W3HmlrpfItSfmqc3jCtasbw==
|
||||
|
||||
hex-color-regex@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e"
|
||||
@ -11317,10 +11322,10 @@ svgo@^1.0.0, svgo@^1.3.2:
|
||||
unquote "~1.1.1"
|
||||
util.promisify "~1.0.0"
|
||||
|
||||
swiper@^5.3.1:
|
||||
version "5.3.6"
|
||||
resolved "https://registry.yarnpkg.com/swiper/-/swiper-5.3.6.tgz#102b7f8145d734ec4c30e04602160382356b5948"
|
||||
integrity sha512-FUz50g6RuvGAuXQWmR5lRPoA129leRUZ/p57ckr8+P5kR7VktElVQ47JGmWD86mOJCFfvMhUf0hinyC5UFL5iw==
|
||||
swiper@^5.3.7:
|
||||
version "5.3.7"
|
||||
resolved "https://registry.yarnpkg.com/swiper/-/swiper-5.3.7.tgz#1349c055730e9247e4482b72631166119b83f409"
|
||||
integrity sha512-BFpXllmUNj1k/Uz6FRW7ykZfUfeCpfqUZxOxeTFZKYy3gv/kOWULHjwy0xlQIJdsiVGF5nZgRG2VbVl6XWy3gw==
|
||||
dependencies:
|
||||
dom7 "^2.1.3"
|
||||
ssr-window "^1.0.1"
|
||||
|
Loading…
x
Reference in New Issue
Block a user