OpenXE/www/js/stickybutton.js
2021-05-21 08:49:41 +02:00

197 lines
5.9 KiB
JavaScript

/**
* Zum "sticky"-machen von Buttons
*
* @example <a href="#" class="button-sticky">Abschicken</a>
*/
var StickyButton = function ($) {
'use strict';
var me = {
storage: {
$button: null,
$buttonClone: null,
isSticky: false,
isCloned: false,
stickyPositionTop: 0,
stickyPositionRight: 0,
stickyOffsetTopTrigger: 0,
mobileBreakpointWidth: 652,
buffer: null
},
selector: {
target: '.button-sticky',
menuWrapper: '.menu-wrapper'
},
/**
* Position initial berechnen und EventHandler attachen
*/
init: function () {
me.storage.$button = $(me.selector.target);
if (me.storage.$button.length === 0) {
return;
}
if (me.storage.$button.length > 1) {
console.info('StickyButton wurde deaktiviert. Es darf nur einen StickyButton pro Seite geben.');
return;
}
// Original Button klonen
me.makeClone();
// Initial alle Werte berechnen
me.debounce(me.calculateButtonPosition, 150);
// Event-Handler attachen
$(window).on('scroll', me.onWindowScroll);
$(window).on('resize', me.onWindowResize);
$(document).on('click', '.ui-tabs-anchor', me.calculateButtonPosition);
},
/**
* Button-Position berechnen
*/
calculateButtonPosition: function () {
var windowWidth = $(window).width();
var buttonWidth = me.storage.$buttonClone.outerWidth(true);
var buttonOffset = me.storage.$buttonClone.offset();
var buttonMarginLeft = parseInt(me.storage.$buttonClone.css('margin-left'));
if (typeof buttonOffset !== 'object') {
return;
}
if (buttonOffset.top === 0 && buttonOffset.left === 0) {
return;
}
var isMobileWindowSize = windowWidth < me.storage.mobileBreakpointWidth;
var menuHeight = isMobileWindowSize ? 0 : $(me.selector.menuWrapper).height();
me.storage.stickyPositionTop = parseInt(menuHeight + 9);
me.storage.stickyPositionRight = parseInt(windowWidth - (buttonOffset.left + buttonWidth) + buttonMarginLeft);
me.storage.stickyOffsetTopTrigger = parseInt(buttonOffset.top - menuHeight - 12);
},
/**
* EventHandler wenn Größe des Fenster geändert wird
*/
onWindowResize: function () {
me.debounce(me.calculateButtonPosition, 250);
},
/**
* EventHandler wenn Fenster gescrollt wird
*/
onWindowScroll: function () {
if (!me.storage.isCloned) {
return;
}
var windowScrollPos = this.scrollY;
if (windowScrollPos > me.storage.stickyOffsetTopTrigger) {
if (me.storage.isSticky === false) {
me.makeSticky();
}
} else {
if (me.storage.isSticky === true) {
me.makeUnsticky();
}
}
},
/**
* Button sticky machen
*/
makeSticky: function () {
if (me.storage.stickyPositionTop === 0 &&
me.storage.stickyPositionRight === 0) {
return;
}
me.storage.isSticky = true;
me.storage.$button.css({
'display': 'block',
'zIndex': 9999,
'position': 'fixed',
'top': me.storage.stickyPositionTop + 'px',
'right': me.storage.stickyPositionRight + 'px'
});
// Beim Klon nur die Opacity anpassen, damit nichts springt
me.storage.$buttonClone.css({
'opacity': 0
});
},
/**
* Button unsticky machen
*/
makeUnsticky: function () {
me.storage.isSticky = false;
me.storage.$button.css({
'display': 'none',
'zIndex': 9999,
'position': 'fixed',
'top': me.storage.stickyPositionTop + 'px',
'right': me.storage.stickyPositionRight + 'px'
});
me.storage.$buttonClone.css({
'opacity': 1
});
},
/**
* Erstellt einen Klon des Buttons der sticky werden soll
*
* Der Klon ist notwendig als Platzhalter, sonst würden die nebenstehenden Elemente springen.
* Beim "sticky"-machen wird der originale Button eingeblendet und der Klon versteckt.
*/
makeClone: function () {
me.storage.$buttonClone = me.storage.$button.clone();
me.storage.$buttonClone.insertAfter(me.storage.$button);
me.storage.$button.hide();
me.storage.isCloned = true;
},
/**
* @return {boolean}
*/
isVisible: function () {
var buttonVisible = me.storage.$button.is(":visible");
var cloneVisible = me.storage.isCloned ? me.storage.$buttonClone.is(":visible") : false;
return buttonVisible || cloneVisible;
},
/**
* Puffer-Funktion um Events erst nach einer bestimmten Zeit
*
* @param {function} callback
* @param {number} delay
*/
debounce: function (callback, delay) {
var context = this;
var args = arguments;
clearTimeout(me.storage.buffer);
me.storage.buffer = setTimeout(function () {
callback.apply(context, args);
}, delay || 250);
}
};
return {
init: me.init
};
}(jQuery);
/**
* Bestimmte Button "sticky" machen
*/
$(document).ready(function () {
StickyButton.init();
});