mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
add requirejs
This commit is contained in:
parent
03ca18cf4f
commit
4e71751d0f
20 changed files with 379 additions and 520 deletions
385
dashboard-ui/thirdparty/headroom.js
vendored
385
dashboard-ui/thirdparty/headroom.js
vendored
|
@ -4,387 +4,4 @@
|
|||
* License: MIT
|
||||
*/
|
||||
|
||||
(function(window, document) {
|
||||
|
||||
'use strict';
|
||||
|
||||
/* exported features */
|
||||
|
||||
var features = {
|
||||
bind : !!(function(){}.bind),
|
||||
classList : 'classList' in document.documentElement,
|
||||
rAF : !!(window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame)
|
||||
};
|
||||
window.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() {
|
||||
this.callback && this.callback();
|
||||
this.ticking = false;
|
||||
},
|
||||
|
||||
/**
|
||||
* ensures events don't get stacked
|
||||
* @private
|
||||
*/
|
||||
requestTick : function() {
|
||||
if(!this.ticking) {
|
||||
requestAnimationFrame(this.rafCallback || (this.rafCallback = this.update.bind(this)));
|
||||
this.ticking = true;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Attach this as the event listeners
|
||||
*/
|
||||
handleEvent : function() {
|
||||
this.requestTick();
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Check if object is part of the DOM
|
||||
* @constructor
|
||||
* @param {Object} obj element to check
|
||||
*/
|
||||
function isDOMElement(obj) {
|
||||
return obj && typeof window !== 'undefined' && (obj === window || obj.nodeType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for extending objects
|
||||
*/
|
||||
function extend (object /*, objectN ... */) {
|
||||
if(arguments.length <= 0) {
|
||||
throw new Error('Missing arguments in extend function');
|
||||
}
|
||||
|
||||
var result = object || {},
|
||||
key,
|
||||
i;
|
||||
|
||||
for (i = 1; i < arguments.length; i++) {
|
||||
var replacement = arguments[i] || {};
|
||||
|
||||
for (key in replacement) {
|
||||
// Recurse into object except if the object is a DOM element
|
||||
if(typeof result[key] === 'object' && ! isDOMElement(result[key])) {
|
||||
result[key] = extend(result[key], replacement[key]);
|
||||
}
|
||||
else {
|
||||
result[key] = result[key] || replacement[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for normalizing tolerance option to object format
|
||||
*/
|
||||
function normalizeTolerance (t) {
|
||||
return t === Object(t) ? t : { down : t, up : t };
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 (elem, options) {
|
||||
options = extend(options, Headroom.options);
|
||||
|
||||
this.lastKnownScrollY = 0;
|
||||
this.elem = elem;
|
||||
this.debouncer = new Debouncer(this.update.bind(this));
|
||||
this.tolerance = normalizeTolerance(options.tolerance);
|
||||
this.classes = options.classes;
|
||||
this.offset = options.offset;
|
||||
this.scroller = options.scroller;
|
||||
this.initialised = false;
|
||||
this.onPin = options.onPin;
|
||||
this.onUnpin = options.onUnpin;
|
||||
this.onTop = options.onTop;
|
||||
this.onNotTop = options.onNotTop;
|
||||
}
|
||||
Headroom.prototype = {
|
||||
constructor : Headroom,
|
||||
|
||||
/**
|
||||
* Initialises the widget
|
||||
*/
|
||||
init : function() {
|
||||
if(!Headroom.cutsTheMustard) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.elem.classList.add(this.classes.initial);
|
||||
|
||||
// defer event registration to handle browser
|
||||
// potentially restoring previous scroll position
|
||||
setTimeout(this.attachEvent.bind(this), 100);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Unattaches events and removes any classes that were added
|
||||
*/
|
||||
destroy : function() {
|
||||
var classes = this.classes;
|
||||
|
||||
this.initialised = false;
|
||||
this.elem.classList.remove(classes.unpinned, classes.pinned, classes.top, classes.initial);
|
||||
this.scroller.removeEventListener('scroll', this.debouncer, false);
|
||||
},
|
||||
|
||||
/**
|
||||
* Attaches the scroll event
|
||||
* @private
|
||||
*/
|
||||
attachEvent : function() {
|
||||
if(!this.initialised){
|
||||
this.lastKnownScrollY = this.getScrollY();
|
||||
this.initialised = true;
|
||||
this.scroller.addEventListener('scroll', this.debouncer, false);
|
||||
|
||||
this.debouncer.handleEvent();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Unpins the header if it's currently pinned
|
||||
*/
|
||||
unpin : function() {
|
||||
var classList = this.elem.classList,
|
||||
classes = this.classes;
|
||||
|
||||
if(classList.contains(classes.pinned) || !classList.contains(classes.unpinned)) {
|
||||
classList.add(classes.unpinned);
|
||||
classList.remove(classes.pinned);
|
||||
this.onUnpin && this.onUnpin.call(this);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Pins the header if it's currently unpinned
|
||||
*/
|
||||
pin : function() {
|
||||
var classList = this.elem.classList,
|
||||
classes = this.classes;
|
||||
|
||||
if(classList.contains(classes.unpinned)) {
|
||||
classList.remove(classes.unpinned);
|
||||
classList.add(classes.pinned);
|
||||
this.onPin && this.onPin.call(this);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles the top states
|
||||
*/
|
||||
top : function() {
|
||||
var classList = this.elem.classList,
|
||||
classes = this.classes;
|
||||
|
||||
if(!classList.contains(classes.top)) {
|
||||
classList.add(classes.top);
|
||||
classList.remove(classes.notTop);
|
||||
this.onTop && this.onTop.call(this);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles the not top state
|
||||
*/
|
||||
notTop : function() {
|
||||
var classList = this.elem.classList,
|
||||
classes = this.classes;
|
||||
|
||||
if(!classList.contains(classes.notTop)) {
|
||||
classList.add(classes.notTop);
|
||||
classList.remove(classes.top);
|
||||
this.onNotTop && this.onNotTop.call(this);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
getScrollY : function() {
|
||||
return (this.scroller.pageYOffset !== undefined)
|
||||
? this.scroller.pageYOffset
|
||||
: (this.scroller.scrollTop !== undefined)
|
||||
? this.scroller.scrollTop
|
||||
: (document.documentElement || document.body.parentNode || document.body).scrollTop;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the height of the viewport
|
||||
* @see http://andylangton.co.uk/blog/development/get-viewport-size-width-and-height-javascript
|
||||
* @return {int} the height of the viewport in pixels
|
||||
*/
|
||||
getViewportHeight : function () {
|
||||
return window.innerHeight
|
||||
|| document.documentElement.clientHeight
|
||||
|| document.body.clientHeight;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the height of the document
|
||||
* @see http://james.padolsey.com/javascript/get-document-height-cross-browser/
|
||||
* @return {int} the height of the document in pixels
|
||||
*/
|
||||
getDocumentHeight : function () {
|
||||
var body = document.body,
|
||||
documentElement = document.documentElement;
|
||||
|
||||
return Math.max(
|
||||
body.scrollHeight, documentElement.scrollHeight,
|
||||
body.offsetHeight, documentElement.offsetHeight,
|
||||
body.clientHeight, documentElement.clientHeight
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the height of the DOM element
|
||||
* @param {Object} elm the element to calculate the height of which
|
||||
* @return {int} the height of the element in pixels
|
||||
*/
|
||||
getElementHeight : function (elm) {
|
||||
return Math.max(
|
||||
elm.scrollHeight,
|
||||
elm.offsetHeight,
|
||||
elm.clientHeight
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the height of the scroller element
|
||||
* @return {int} the height of the scroller element in pixels
|
||||
*/
|
||||
getScrollerHeight : function () {
|
||||
return (this.scroller === window || this.scroller === document.body)
|
||||
? this.getDocumentHeight()
|
||||
: this.getElementHeight(this.scroller);
|
||||
},
|
||||
|
||||
/**
|
||||
* determines if the scroll position is outside of document boundaries
|
||||
* @param {int} currentScrollY the current y scroll position
|
||||
* @return {bool} true if out of bounds, false otherwise
|
||||
*/
|
||||
isOutOfBounds : function (currentScrollY) {
|
||||
var pastTop = currentScrollY < 0,
|
||||
pastBottom = currentScrollY + this.getViewportHeight() > this.getScrollerHeight();
|
||||
|
||||
return pastTop || pastBottom;
|
||||
},
|
||||
|
||||
/**
|
||||
* determines if the tolerance has been exceeded
|
||||
* @param {int} currentScrollY the current scroll y position
|
||||
* @return {bool} true if tolerance exceeded, false otherwise
|
||||
*/
|
||||
toleranceExceeded : function (currentScrollY, direction) {
|
||||
return Math.abs(currentScrollY-this.lastKnownScrollY) >= this.tolerance[direction];
|
||||
},
|
||||
|
||||
/**
|
||||
* determine if it is appropriate to unpin
|
||||
* @param {int} currentScrollY the current y scroll position
|
||||
* @param {bool} toleranceExceeded has the tolerance been exceeded?
|
||||
* @return {bool} true if should unpin, false otherwise
|
||||
*/
|
||||
shouldUnpin : function (currentScrollY, toleranceExceeded) {
|
||||
var scrollingDown = currentScrollY > this.lastKnownScrollY,
|
||||
pastOffset = currentScrollY >= this.offset;
|
||||
|
||||
return scrollingDown && pastOffset && toleranceExceeded;
|
||||
},
|
||||
|
||||
/**
|
||||
* determine if it is appropriate to pin
|
||||
* @param {int} currentScrollY the current y scroll position
|
||||
* @param {bool} toleranceExceeded has the tolerance been exceeded?
|
||||
* @return {bool} true if should pin, false otherwise
|
||||
*/
|
||||
shouldPin : function (currentScrollY, toleranceExceeded) {
|
||||
var scrollingUp = currentScrollY < this.lastKnownScrollY,
|
||||
pastOffset = currentScrollY <= this.offset;
|
||||
|
||||
return (scrollingUp && toleranceExceeded) || pastOffset;
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles updating the state of the widget
|
||||
*/
|
||||
update : function() {
|
||||
var currentScrollY = this.getScrollY(),
|
||||
scrollDirection = currentScrollY > this.lastKnownScrollY ? 'down' : 'up',
|
||||
toleranceExceeded = this.toleranceExceeded(currentScrollY, scrollDirection);
|
||||
|
||||
if(this.isOutOfBounds(currentScrollY)) { // Ignore bouncy scrolling in OSX
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentScrollY <= this.offset ) {
|
||||
this.top();
|
||||
} else {
|
||||
this.notTop();
|
||||
}
|
||||
|
||||
if(this.shouldUnpin(currentScrollY, toleranceExceeded)) {
|
||||
this.unpin();
|
||||
}
|
||||
else if(this.shouldPin(currentScrollY, toleranceExceeded)) {
|
||||
this.pin();
|
||||
}
|
||||
|
||||
this.lastKnownScrollY = currentScrollY;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Default options
|
||||
* @type {Object}
|
||||
*/
|
||||
Headroom.options = {
|
||||
tolerance : {
|
||||
up : 0,
|
||||
down : 0
|
||||
},
|
||||
offset : 0,
|
||||
scroller: window,
|
||||
classes : {
|
||||
pinned : 'headroom--pinned',
|
||||
unpinned : 'headroom--unpinned',
|
||||
top : 'headroom--top',
|
||||
notTop : 'headroom--not-top',
|
||||
initial : 'headroom'
|
||||
}
|
||||
};
|
||||
Headroom.cutsTheMustard = typeof features !== 'undefined' && features.rAF && features.bind && features.classList;
|
||||
|
||||
window.Headroom = Headroom;
|
||||
|
||||
}(window, document));
|
||||
!function (a, b) { "use strict"; function c(a) { this.callback = a, this.ticking = !1 } function d(b) { return b && "undefined" != typeof a && (b === a || b.nodeType) } function e(a) { if (arguments.length <= 0) throw new Error("Missing arguments in extend function"); var b, c, f = a || {}; for (c = 1; c < arguments.length; c++) { var g = arguments[c] || {}; for (b in g) f[b] = "object" != typeof f[b] || d(f[b]) ? f[b] || g[b] : e(f[b], g[b]) } return f } function f(a) { return a === Object(a) ? a : { down: a, up: a } } function g(a, b) { b = e(b, g.options), this.lastKnownScrollY = 0, this.elem = a, this.debouncer = new c(this.update.bind(this)), this.tolerance = f(b.tolerance), this.classes = b.classes, this.offset = b.offset, this.scroller = b.scroller, this.initialised = !1, this.onPin = b.onPin, this.onUnpin = b.onUnpin, this.onTop = b.onTop, this.onNotTop = b.onNotTop } var h = { bind: !!function () { }.bind, classList: "classList" in b.documentElement, rAF: !!(a.requestAnimationFrame || a.webkitRequestAnimationFrame || a.mozRequestAnimationFrame) }; a.requestAnimationFrame = a.requestAnimationFrame || a.webkitRequestAnimationFrame || a.mozRequestAnimationFrame, c.prototype = { constructor: c, update: function () { this.callback && this.callback(), this.ticking = !1 }, requestTick: function () { this.ticking || (requestAnimationFrame(this.rafCallback || (this.rafCallback = this.update.bind(this))), this.ticking = !0) }, handleEvent: function () { this.requestTick() } }, g.prototype = { constructor: g, init: function () { return g.cutsTheMustard ? (this.elem.classList.add(this.classes.initial), setTimeout(this.attachEvent.bind(this), 100), this) : void 0 }, destroy: function () { var a = this.classes; this.initialised = !1, this.elem.classList.remove(a.unpinned, a.pinned, a.top, a.initial), this.scroller.removeEventListener("scroll", this.debouncer, !1) }, attachEvent: function () { this.initialised || (this.lastKnownScrollY = this.getScrollY(), this.initialised = !0, this.scroller.addEventListener("scroll", this.debouncer, !1), this.debouncer.handleEvent()) }, unpin: function () { var a = this.elem.classList, b = this.classes; (a.contains(b.pinned) || !a.contains(b.unpinned)) && (a.add(b.unpinned), a.remove(b.pinned), this.onUnpin && this.onUnpin.call(this)) }, pin: function () { var a = this.elem.classList, b = this.classes; a.contains(b.unpinned) && (a.remove(b.unpinned), a.add(b.pinned), this.onPin && this.onPin.call(this)) }, top: function () { var a = this.elem.classList, b = this.classes; a.contains(b.top) || (a.add(b.top), a.remove(b.notTop), this.onTop && this.onTop.call(this)) }, notTop: function () { var a = this.elem.classList, b = this.classes; a.contains(b.notTop) || (a.add(b.notTop), a.remove(b.top), this.onNotTop && this.onNotTop.call(this)) }, getScrollY: function () { return void 0 !== this.scroller.pageYOffset ? this.scroller.pageYOffset : void 0 !== this.scroller.scrollTop ? this.scroller.scrollTop : (b.documentElement || b.body.parentNode || b.body).scrollTop }, getViewportHeight: function () { return a.innerHeight || b.documentElement.clientHeight || b.body.clientHeight }, getDocumentHeight: function () { var a = b.body, c = b.documentElement; return Math.max(a.scrollHeight, c.scrollHeight, a.offsetHeight, c.offsetHeight, a.clientHeight, c.clientHeight) }, getElementHeight: function (a) { return Math.max(a.scrollHeight, a.offsetHeight, a.clientHeight) }, getScrollerHeight: function () { return this.scroller === a || this.scroller === b.body ? this.getDocumentHeight() : this.getElementHeight(this.scroller) }, isOutOfBounds: function (a) { var b = 0 > a, c = a + this.getViewportHeight() > this.getScrollerHeight(); return b || c }, toleranceExceeded: function (a, b) { return Math.abs(a - this.lastKnownScrollY) >= this.tolerance[b] }, shouldUnpin: function (a, b) { var c = a > this.lastKnownScrollY, d = a >= this.offset; return c && d && b }, shouldPin: function (a, b) { var c = a < this.lastKnownScrollY, d = a <= this.offset; return c && b || d }, update: function () { var a = this.getScrollY(), b = a > this.lastKnownScrollY ? "down" : "up", c = this.toleranceExceeded(a, b); this.isOutOfBounds(a) || (a <= this.offset ? this.top() : this.notTop(), this.shouldUnpin(a, c) ? this.unpin() : this.shouldPin(a, c) && this.pin(), this.lastKnownScrollY = a) } }, g.options = { tolerance: { up: 0, down: 0 }, offset: 0, scroller: a, classes: { pinned: "headroom--pinned", unpinned: "headroom--unpinned", top: "headroom--top", notTop: "headroom--not-top", initial: "headroom" } }, g.cutsTheMustard = "undefined" != typeof h && h.rAF && h.bind && h.classList, a.Headroom = g }(window, document);
|
Loading…
Add table
Add a link
Reference in a new issue