- Improved "top nav" UX
This commit is contained in:
@@ -314,7 +314,6 @@ define([
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -406,13 +405,13 @@ define([
|
||||
* init scrollSpy for navigation bar
|
||||
*/
|
||||
let initScrollSpy = () => {
|
||||
// init scrollspy
|
||||
let scrollElement = window;
|
||||
let timeout;
|
||||
|
||||
// show elements that are currently in the viewport
|
||||
let showVisibleElements = () => {
|
||||
// find all elements that should be animated
|
||||
let visibleElements = $('.' + config.animateElementClass).isInViewport();
|
||||
|
||||
let visibleElements = Util.findInViewport($('.' + config.animateElementClass));
|
||||
$(visibleElements).removeClass( config.animateElementClass );
|
||||
|
||||
$(visibleElements).velocity('transition.flipXIn', {
|
||||
@@ -431,16 +430,23 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
$( window ).scroll(() => {
|
||||
// check for new visible elements
|
||||
showVisibleElements();
|
||||
});
|
||||
let scrollHandler = () => {
|
||||
// If there's a timer, cancel it
|
||||
if(timeout){
|
||||
window.cancelAnimationFrame(timeout);
|
||||
}
|
||||
timeout = window.requestAnimationFrame(showVisibleElements);
|
||||
};
|
||||
|
||||
scrollElement.addEventListener('scroll', scrollHandler, false);
|
||||
|
||||
// initial check for visible elements
|
||||
showVisibleElements();
|
||||
|
||||
// event listener for navigation links
|
||||
Util.initPageScroll('#' + config.navigationElementId);
|
||||
|
||||
Util.initScrollSpy(document.getElementById(config.navigationElementId), scrollElement, {
|
||||
offset: 150
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,6 +13,10 @@ define([
|
||||
|
||||
let config = {
|
||||
splashOverlayClass: 'pf-splash', // class for "splash" overlay
|
||||
|
||||
// navigation
|
||||
navigationElementId: 'pf-navbar', // id for navbar element
|
||||
|
||||
webSocketStatsId: 'pf-setup-webSocket-stats', // id for webSocket "stats" panel
|
||||
webSocketRefreshStatsId: 'pf-setup-webSocket-stats-refresh' // class for "reload stats" button
|
||||
};
|
||||
@@ -64,7 +68,9 @@ define([
|
||||
let body = $('body');
|
||||
|
||||
// navigation (scroll) ----------------------------------------------------------------------------------------
|
||||
Util.initPageScroll(body);
|
||||
Util.initScrollSpy(document.getElementById(config.navigationElementId), window, {
|
||||
offset: 300
|
||||
});
|
||||
|
||||
// collapse ---------------------------------------------------------------------------------------------------
|
||||
setCollapseObserver(body, '[data-toggle="collapse"]');
|
||||
@@ -188,8 +194,8 @@ define([
|
||||
* @param data
|
||||
*/
|
||||
let updateWebSocketPanel = (data) => {
|
||||
let badgeSocketWarning = $('.navbar a[data-anchor="#pf-setup-socket"] .txt-color-warning');
|
||||
let badgeSocketDanger = $('.navbar a[data-anchor="#pf-setup-socket"] .txt-color-danger');
|
||||
let badgeSocketWarning = $('.navbar a[data-target="pf-setup-socket"] .txt-color-warning');
|
||||
let badgeSocketDanger = $('.navbar a[data-target="pf-setup-socket"] .txt-color-danger');
|
||||
let socketWarningCount = parseInt(badgeSocketWarning.text()) || 0;
|
||||
let socketDangerCount = parseInt(badgeSocketDanger.text()) || 0;
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@ define([
|
||||
$.fn.showMapManual = function(){
|
||||
|
||||
requirejs(['text!templates/dialog/map_manual.html', 'mustache'], (template, Mustache) => {
|
||||
|
||||
let data = {
|
||||
dialogNavigationClass: config.dialogNavigationClass,
|
||||
dialogNavLiClass: config.dialogNavigationListItemClass,
|
||||
@@ -67,8 +66,7 @@ define([
|
||||
|
||||
let scrollspyElement = $('#' + config.mapManualScrollspyId);
|
||||
|
||||
let whileScrolling = function(){
|
||||
|
||||
let whileScrolling = () => {
|
||||
if(disableOnScrollEvent === false){
|
||||
for(let i = 0; i < scrollBreakpointElements.length; i++){
|
||||
let offset = $(scrollBreakpointElements[i]).offset().top;
|
||||
@@ -124,11 +122,9 @@ define([
|
||||
|
||||
let mainNavigationLiElement = $(this).parent('.' + config.dialogNavigationListItemClass);
|
||||
|
||||
|
||||
whileScrolling();
|
||||
|
||||
// if link is a main navigation link (not an anchor link)
|
||||
|
||||
if(mainNavigationLiElement.length > 0){
|
||||
// remove all active classes
|
||||
scrollNavLiElements.removeClass('active');
|
||||
@@ -138,7 +134,6 @@ define([
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
},
|
||||
onScroll: function(){
|
||||
disableOnScrollEvent = false;
|
||||
|
||||
212
js/app/util.js
212
js/app/util.js
@@ -398,40 +398,6 @@ define([
|
||||
return valid;
|
||||
};
|
||||
|
||||
/**
|
||||
* check multiple element if they are currently visible in viewport
|
||||
* @returns {Array}
|
||||
*/
|
||||
$.fn.isInViewport = function(){
|
||||
let visibleElement = [];
|
||||
|
||||
this.each(function(){
|
||||
let element = $(this)[0];
|
||||
|
||||
let top = element.offsetTop;
|
||||
let left = element.offsetLeft;
|
||||
let width = element.offsetWidth;
|
||||
let height = element.offsetHeight;
|
||||
|
||||
while(element.offsetParent){
|
||||
element = element.offsetParent;
|
||||
top += element.offsetTop;
|
||||
left += element.offsetLeft;
|
||||
}
|
||||
|
||||
if(
|
||||
top < (window.pageYOffset + window.innerHeight) &&
|
||||
left < (window.pageXOffset + window.innerWidth) &&
|
||||
(top + height) > window.pageYOffset &&
|
||||
(left + width) > window.pageXOffset
|
||||
){
|
||||
visibleElement.push(this);
|
||||
}
|
||||
});
|
||||
|
||||
return visibleElement;
|
||||
};
|
||||
|
||||
/**
|
||||
* init the map-update-counter as "easy-pie-chart"
|
||||
*/
|
||||
@@ -1024,17 +990,172 @@ define([
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param element
|
||||
* filter elements from elements array that are not within viewport
|
||||
* @param elements
|
||||
* @returns {[]}
|
||||
*/
|
||||
let initPageScroll = (element) => {
|
||||
$(element).on('click', '.page-scroll', function(){
|
||||
// scroll to ancor element
|
||||
$($(this).attr('data-anchor')).velocity('scroll', {
|
||||
duration: 300,
|
||||
easing: 'swing'
|
||||
});
|
||||
});
|
||||
let findInViewport = elements => {
|
||||
let visibleElement = [];
|
||||
|
||||
for(let element of elements){
|
||||
if(!(element instanceof HTMLElement)){
|
||||
console.warn('findInViewport() expects Array() of %O; %o given', HTMLElement, element);
|
||||
continue;
|
||||
}
|
||||
|
||||
let top = element.offsetTop;
|
||||
let left = element.offsetLeft;
|
||||
let width = element.offsetWidth;
|
||||
let height = element.offsetHeight;
|
||||
let origElement = element;
|
||||
|
||||
while(element.offsetParent){
|
||||
element = element.offsetParent;
|
||||
top += element.offsetTop;
|
||||
left += element.offsetLeft;
|
||||
}
|
||||
|
||||
if(
|
||||
top < (window.pageYOffset + window.innerHeight) &&
|
||||
left < (window.pageXOffset + window.innerWidth) &&
|
||||
(top + height) > window.pageYOffset &&
|
||||
(left + width) > window.pageXOffset
|
||||
){
|
||||
visibleElement.push(origElement);
|
||||
}
|
||||
}
|
||||
|
||||
return visibleElement;
|
||||
};
|
||||
|
||||
/**
|
||||
* "Scroll Spy" implementation
|
||||
* @see https://github.com/cferdinandi/gumshoe/blob/master/src/js/gumshoe/gumshoe.js
|
||||
* @param navElement
|
||||
* @param scrollElement
|
||||
* @param settings
|
||||
*/
|
||||
let initScrollSpy = (navElement, scrollElement = window, settings = {}) => {
|
||||
let timeout, current;
|
||||
|
||||
let contents = Array.from(navElement.querySelectorAll('.page-scroll')).map(link => ({
|
||||
link: link,
|
||||
content: document.getElementById(link.getAttribute('data-target'))
|
||||
}));
|
||||
|
||||
let getOffset = settings => {
|
||||
if(typeof settings.offset === 'function'){
|
||||
return parseFloat(settings.offset());
|
||||
}
|
||||
// Otherwise, return it as-is
|
||||
return parseFloat(settings.offset);
|
||||
};
|
||||
|
||||
let getDocumentHeight = () => {
|
||||
return Math.max(
|
||||
document.body.scrollHeight, document.documentElement.scrollHeight,
|
||||
document.body.offsetHeight, document.documentElement.offsetHeight,
|
||||
document.body.clientHeight, document.documentElement.clientHeight
|
||||
);
|
||||
};
|
||||
|
||||
let activate = item => {
|
||||
if(!item) return;
|
||||
|
||||
// Get the parent list item
|
||||
let li = item.link.closest('li');
|
||||
if(!li) return;
|
||||
|
||||
// Add the active class to li
|
||||
li.classList.add('active');
|
||||
};
|
||||
|
||||
let deactivate = item => {
|
||||
if(!item) return;
|
||||
|
||||
// remove focus
|
||||
if(document.activeElement === item.link){
|
||||
document.activeElement.blur();
|
||||
}
|
||||
|
||||
// Get the parent list item
|
||||
let li = item.link.closest('li');
|
||||
if(!li) return;
|
||||
|
||||
// Remove the active class from li
|
||||
li.classList.remove('active');
|
||||
};
|
||||
|
||||
let isInView = (elem, settings, bottom) => {
|
||||
let bounds = elem.getBoundingClientRect();
|
||||
let offset = getOffset(settings);
|
||||
if(bottom){
|
||||
return parseInt(bounds.bottom, 10) < (window.innerHeight || document.documentElement.clientHeight);
|
||||
}
|
||||
return parseInt(bounds.top, 10) <= offset;
|
||||
};
|
||||
|
||||
let isAtBottom = () => {
|
||||
return window.innerHeight + window.pageYOffset >= getDocumentHeight();
|
||||
};
|
||||
|
||||
let useLastItem = (item, settings) => {
|
||||
return !!(isAtBottom() && isInView(item.content, settings, true));
|
||||
};
|
||||
|
||||
let getActive = (contents, settings) => {
|
||||
let last = contents[contents.length - 1];
|
||||
if(useLastItem(last, settings)) return last;
|
||||
for(let i = contents.length - 1; i >= 0; i--){
|
||||
if(isInView(contents[i].content, settings)) return contents[i];
|
||||
}
|
||||
};
|
||||
|
||||
let detect = () => {
|
||||
let active = getActive(contents, settings);
|
||||
|
||||
// if there's no active content, deactivate and bail
|
||||
if(!active){
|
||||
if(current){
|
||||
deactivate(current);
|
||||
current = null;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// If the active content is the one currently active, do nothing
|
||||
if (current && active.content === current.content) return;
|
||||
|
||||
// Deactivate the current content and activate the new content
|
||||
deactivate(current);
|
||||
activate(active);
|
||||
|
||||
// Update the currently active content
|
||||
current = active;
|
||||
};
|
||||
|
||||
let scrollHandler = () => {
|
||||
// If there's a timer, cancel it
|
||||
if(timeout){
|
||||
window.cancelAnimationFrame(timeout);
|
||||
}
|
||||
timeout = window.requestAnimationFrame(detect);
|
||||
};
|
||||
|
||||
// Find the currently active content
|
||||
detect();
|
||||
|
||||
scrollElement.addEventListener('scroll', scrollHandler, false);
|
||||
|
||||
// set click observer for links
|
||||
let clickHandler = function(e){
|
||||
e.preventDefault();
|
||||
this.content.scrollIntoView({behavior: 'smooth'});
|
||||
};
|
||||
|
||||
for(let item of contents){
|
||||
$(item.link).on('click', clickHandler.bind(item));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -3287,7 +3408,8 @@ define([
|
||||
getCurrentLocationData: getCurrentLocationData,
|
||||
getCurrentUserInfo: getCurrentUserInfo,
|
||||
getCurrentCharacterLog: getCurrentCharacterLog,
|
||||
initPageScroll: initPageScroll,
|
||||
findInViewport: findInViewport,
|
||||
initScrollSpy: initScrollSpy,
|
||||
convertXEditableOptionsToSelect2: convertXEditableOptionsToSelect2,
|
||||
flattenXEditableSelectArray: flattenXEditableSelectArray,
|
||||
getCharacterDataBySystemId: getCharacterDataBySystemId,
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -314,7 +314,6 @@ define([
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -406,13 +405,13 @@ define([
|
||||
* init scrollSpy for navigation bar
|
||||
*/
|
||||
let initScrollSpy = () => {
|
||||
// init scrollspy
|
||||
let scrollElement = window;
|
||||
let timeout;
|
||||
|
||||
// show elements that are currently in the viewport
|
||||
let showVisibleElements = () => {
|
||||
// find all elements that should be animated
|
||||
let visibleElements = $('.' + config.animateElementClass).isInViewport();
|
||||
|
||||
let visibleElements = Util.findInViewport($('.' + config.animateElementClass));
|
||||
$(visibleElements).removeClass( config.animateElementClass );
|
||||
|
||||
$(visibleElements).velocity('transition.flipXIn', {
|
||||
@@ -431,16 +430,23 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
$( window ).scroll(() => {
|
||||
// check for new visible elements
|
||||
showVisibleElements();
|
||||
});
|
||||
let scrollHandler = () => {
|
||||
// If there's a timer, cancel it
|
||||
if(timeout){
|
||||
window.cancelAnimationFrame(timeout);
|
||||
}
|
||||
timeout = window.requestAnimationFrame(showVisibleElements);
|
||||
};
|
||||
|
||||
scrollElement.addEventListener('scroll', scrollHandler, false);
|
||||
|
||||
// initial check for visible elements
|
||||
showVisibleElements();
|
||||
|
||||
// event listener for navigation links
|
||||
Util.initPageScroll('#' + config.navigationElementId);
|
||||
|
||||
Util.initScrollSpy(document.getElementById(config.navigationElementId), scrollElement, {
|
||||
offset: 150
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,6 +13,10 @@ define([
|
||||
|
||||
let config = {
|
||||
splashOverlayClass: 'pf-splash', // class for "splash" overlay
|
||||
|
||||
// navigation
|
||||
navigationElementId: 'pf-navbar', // id for navbar element
|
||||
|
||||
webSocketStatsId: 'pf-setup-webSocket-stats', // id for webSocket "stats" panel
|
||||
webSocketRefreshStatsId: 'pf-setup-webSocket-stats-refresh' // class for "reload stats" button
|
||||
};
|
||||
@@ -64,7 +68,9 @@ define([
|
||||
let body = $('body');
|
||||
|
||||
// navigation (scroll) ----------------------------------------------------------------------------------------
|
||||
Util.initPageScroll(body);
|
||||
Util.initScrollSpy(document.getElementById(config.navigationElementId), window, {
|
||||
offset: 300
|
||||
});
|
||||
|
||||
// collapse ---------------------------------------------------------------------------------------------------
|
||||
setCollapseObserver(body, '[data-toggle="collapse"]');
|
||||
@@ -188,8 +194,8 @@ define([
|
||||
* @param data
|
||||
*/
|
||||
let updateWebSocketPanel = (data) => {
|
||||
let badgeSocketWarning = $('.navbar a[data-anchor="#pf-setup-socket"] .txt-color-warning');
|
||||
let badgeSocketDanger = $('.navbar a[data-anchor="#pf-setup-socket"] .txt-color-danger');
|
||||
let badgeSocketWarning = $('.navbar a[data-target="pf-setup-socket"] .txt-color-warning');
|
||||
let badgeSocketDanger = $('.navbar a[data-target="pf-setup-socket"] .txt-color-danger');
|
||||
let socketWarningCount = parseInt(badgeSocketWarning.text()) || 0;
|
||||
let socketDangerCount = parseInt(badgeSocketDanger.text()) || 0;
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@ define([
|
||||
$.fn.showMapManual = function(){
|
||||
|
||||
requirejs(['text!templates/dialog/map_manual.html', 'mustache'], (template, Mustache) => {
|
||||
|
||||
let data = {
|
||||
dialogNavigationClass: config.dialogNavigationClass,
|
||||
dialogNavLiClass: config.dialogNavigationListItemClass,
|
||||
@@ -67,8 +66,7 @@ define([
|
||||
|
||||
let scrollspyElement = $('#' + config.mapManualScrollspyId);
|
||||
|
||||
let whileScrolling = function(){
|
||||
|
||||
let whileScrolling = () => {
|
||||
if(disableOnScrollEvent === false){
|
||||
for(let i = 0; i < scrollBreakpointElements.length; i++){
|
||||
let offset = $(scrollBreakpointElements[i]).offset().top;
|
||||
@@ -124,11 +122,9 @@ define([
|
||||
|
||||
let mainNavigationLiElement = $(this).parent('.' + config.dialogNavigationListItemClass);
|
||||
|
||||
|
||||
whileScrolling();
|
||||
|
||||
// if link is a main navigation link (not an anchor link)
|
||||
|
||||
if(mainNavigationLiElement.length > 0){
|
||||
// remove all active classes
|
||||
scrollNavLiElements.removeClass('active');
|
||||
@@ -138,7 +134,6 @@ define([
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
},
|
||||
onScroll: function(){
|
||||
disableOnScrollEvent = false;
|
||||
|
||||
@@ -398,40 +398,6 @@ define([
|
||||
return valid;
|
||||
};
|
||||
|
||||
/**
|
||||
* check multiple element if they are currently visible in viewport
|
||||
* @returns {Array}
|
||||
*/
|
||||
$.fn.isInViewport = function(){
|
||||
let visibleElement = [];
|
||||
|
||||
this.each(function(){
|
||||
let element = $(this)[0];
|
||||
|
||||
let top = element.offsetTop;
|
||||
let left = element.offsetLeft;
|
||||
let width = element.offsetWidth;
|
||||
let height = element.offsetHeight;
|
||||
|
||||
while(element.offsetParent){
|
||||
element = element.offsetParent;
|
||||
top += element.offsetTop;
|
||||
left += element.offsetLeft;
|
||||
}
|
||||
|
||||
if(
|
||||
top < (window.pageYOffset + window.innerHeight) &&
|
||||
left < (window.pageXOffset + window.innerWidth) &&
|
||||
(top + height) > window.pageYOffset &&
|
||||
(left + width) > window.pageXOffset
|
||||
){
|
||||
visibleElement.push(this);
|
||||
}
|
||||
});
|
||||
|
||||
return visibleElement;
|
||||
};
|
||||
|
||||
/**
|
||||
* init the map-update-counter as "easy-pie-chart"
|
||||
*/
|
||||
@@ -1024,17 +990,172 @@ define([
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param element
|
||||
* filter elements from elements array that are not within viewport
|
||||
* @param elements
|
||||
* @returns {[]}
|
||||
*/
|
||||
let initPageScroll = (element) => {
|
||||
$(element).on('click', '.page-scroll', function(){
|
||||
// scroll to ancor element
|
||||
$($(this).attr('data-anchor')).velocity('scroll', {
|
||||
duration: 300,
|
||||
easing: 'swing'
|
||||
});
|
||||
});
|
||||
let findInViewport = elements => {
|
||||
let visibleElement = [];
|
||||
|
||||
for(let element of elements){
|
||||
if(!(element instanceof HTMLElement)){
|
||||
console.warn('findInViewport() expects Array() of %O; %o given', HTMLElement, element);
|
||||
continue;
|
||||
}
|
||||
|
||||
let top = element.offsetTop;
|
||||
let left = element.offsetLeft;
|
||||
let width = element.offsetWidth;
|
||||
let height = element.offsetHeight;
|
||||
let origElement = element;
|
||||
|
||||
while(element.offsetParent){
|
||||
element = element.offsetParent;
|
||||
top += element.offsetTop;
|
||||
left += element.offsetLeft;
|
||||
}
|
||||
|
||||
if(
|
||||
top < (window.pageYOffset + window.innerHeight) &&
|
||||
left < (window.pageXOffset + window.innerWidth) &&
|
||||
(top + height) > window.pageYOffset &&
|
||||
(left + width) > window.pageXOffset
|
||||
){
|
||||
visibleElement.push(origElement);
|
||||
}
|
||||
}
|
||||
|
||||
return visibleElement;
|
||||
};
|
||||
|
||||
/**
|
||||
* "Scroll Spy" implementation
|
||||
* @see https://github.com/cferdinandi/gumshoe/blob/master/src/js/gumshoe/gumshoe.js
|
||||
* @param navElement
|
||||
* @param scrollElement
|
||||
* @param settings
|
||||
*/
|
||||
let initScrollSpy = (navElement, scrollElement = window, settings = {}) => {
|
||||
let timeout, current;
|
||||
|
||||
let contents = Array.from(navElement.querySelectorAll('.page-scroll')).map(link => ({
|
||||
link: link,
|
||||
content: document.getElementById(link.getAttribute('data-target'))
|
||||
}));
|
||||
|
||||
let getOffset = settings => {
|
||||
if(typeof settings.offset === 'function'){
|
||||
return parseFloat(settings.offset());
|
||||
}
|
||||
// Otherwise, return it as-is
|
||||
return parseFloat(settings.offset);
|
||||
};
|
||||
|
||||
let getDocumentHeight = () => {
|
||||
return Math.max(
|
||||
document.body.scrollHeight, document.documentElement.scrollHeight,
|
||||
document.body.offsetHeight, document.documentElement.offsetHeight,
|
||||
document.body.clientHeight, document.documentElement.clientHeight
|
||||
);
|
||||
};
|
||||
|
||||
let activate = item => {
|
||||
if(!item) return;
|
||||
|
||||
// Get the parent list item
|
||||
let li = item.link.closest('li');
|
||||
if(!li) return;
|
||||
|
||||
// Add the active class to li
|
||||
li.classList.add('active');
|
||||
};
|
||||
|
||||
let deactivate = item => {
|
||||
if(!item) return;
|
||||
|
||||
// remove focus
|
||||
if(document.activeElement === item.link){
|
||||
document.activeElement.blur();
|
||||
}
|
||||
|
||||
// Get the parent list item
|
||||
let li = item.link.closest('li');
|
||||
if(!li) return;
|
||||
|
||||
// Remove the active class from li
|
||||
li.classList.remove('active');
|
||||
};
|
||||
|
||||
let isInView = (elem, settings, bottom) => {
|
||||
let bounds = elem.getBoundingClientRect();
|
||||
let offset = getOffset(settings);
|
||||
if(bottom){
|
||||
return parseInt(bounds.bottom, 10) < (window.innerHeight || document.documentElement.clientHeight);
|
||||
}
|
||||
return parseInt(bounds.top, 10) <= offset;
|
||||
};
|
||||
|
||||
let isAtBottom = () => {
|
||||
return window.innerHeight + window.pageYOffset >= getDocumentHeight();
|
||||
};
|
||||
|
||||
let useLastItem = (item, settings) => {
|
||||
return !!(isAtBottom() && isInView(item.content, settings, true));
|
||||
};
|
||||
|
||||
let getActive = (contents, settings) => {
|
||||
let last = contents[contents.length - 1];
|
||||
if(useLastItem(last, settings)) return last;
|
||||
for(let i = contents.length - 1; i >= 0; i--){
|
||||
if(isInView(contents[i].content, settings)) return contents[i];
|
||||
}
|
||||
};
|
||||
|
||||
let detect = () => {
|
||||
let active = getActive(contents, settings);
|
||||
|
||||
// if there's no active content, deactivate and bail
|
||||
if(!active){
|
||||
if(current){
|
||||
deactivate(current);
|
||||
current = null;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// If the active content is the one currently active, do nothing
|
||||
if (current && active.content === current.content) return;
|
||||
|
||||
// Deactivate the current content and activate the new content
|
||||
deactivate(current);
|
||||
activate(active);
|
||||
|
||||
// Update the currently active content
|
||||
current = active;
|
||||
};
|
||||
|
||||
let scrollHandler = () => {
|
||||
// If there's a timer, cancel it
|
||||
if(timeout){
|
||||
window.cancelAnimationFrame(timeout);
|
||||
}
|
||||
timeout = window.requestAnimationFrame(detect);
|
||||
};
|
||||
|
||||
// Find the currently active content
|
||||
detect();
|
||||
|
||||
scrollElement.addEventListener('scroll', scrollHandler, false);
|
||||
|
||||
// set click observer for links
|
||||
let clickHandler = function(e){
|
||||
e.preventDefault();
|
||||
this.content.scrollIntoView({behavior: 'smooth'});
|
||||
};
|
||||
|
||||
for(let item of contents){
|
||||
$(item.link).on('click', clickHandler.bind(item));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -3287,7 +3408,8 @@ define([
|
||||
getCurrentLocationData: getCurrentLocationData,
|
||||
getCurrentUserInfo: getCurrentUserInfo,
|
||||
getCurrentCharacterLog: getCurrentCharacterLog,
|
||||
initPageScroll: initPageScroll,
|
||||
findInViewport: findInViewport,
|
||||
initScrollSpy: initScrollSpy,
|
||||
convertXEditableOptionsToSelect2: convertXEditableOptionsToSelect2,
|
||||
flattenXEditableSelectArray: flattenXEditableSelectArray,
|
||||
getCharacterDataBySystemId: getCharacterDataBySystemId,
|
||||
|
||||
@@ -22,23 +22,23 @@
|
||||
</p>
|
||||
|
||||
<ul class="nav navbar-nav navbar-right" role="tablist">
|
||||
<li class="hide-before"><a class="pf-navbar-manual" href="#">Manual</a></li>
|
||||
<li><a class="pf-navbar-manual" href="#">Manual</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav navbar-right" role="tablist">
|
||||
<li class="hide-before"><a class="page-scroll" data-anchor="#pf-landing-top" href="#">Login</a></li>
|
||||
<li><a class="page-scroll" data-target="pf-landing-top" href="#pf-landing-top">Login</a></li>
|
||||
<check if="{{ @PATHFINDER.SHOW_COMPLETE_LOGIN_PAGE}}">
|
||||
<li class="hide-before"> <a class="page-scroll" data-anchor="#pf-landing-gallery" href="#">Features</a></li>
|
||||
<li> <a class="page-scroll" data-target="pf-landing-gallery" href="#pf-landing-gallery-thumb-container">Features</a></li>
|
||||
</check>
|
||||
<li class="hide-before"> <a class="page-scroll" data-anchor="#pf-landing-maps" href="#">Maps</a></li>
|
||||
<li> <a class="page-scroll" data-target="pf-landing-maps" href="#pf-landing-maps">Maps</a></li>
|
||||
<check if="{{ @PATHFINDER.SHOW_COMPLETE_LOGIN_PAGE}}">
|
||||
<li class="hide-before"> <a class="page-scroll" data-anchor="#pf-landing-admin" href="#">Admin</a></li>
|
||||
<li class="hide-before"> <a class="page-scroll" data-anchor="#pf-landing-install" href="#">Install</a></li>
|
||||
<li class="hide-before"> <a class="page-scroll" data-anchor="#pf-landing-about" href="#">About</a></li>
|
||||
<li> <a class="page-scroll" data-target="pf-landing-admin" href="#pf-landing-admin">Admin</a></li>
|
||||
<li> <a class="page-scroll" data-target="pf-landing-install" href="#pf-landing-install">Install</a></li>
|
||||
<li> <a class="page-scroll" data-target="pf-landing-about" href="#pf-landing-about">About</a></li>
|
||||
</check>
|
||||
<li class="hide-before"> <a class="page-scroll" data-anchor="#pf-landing-faq" href="#">FAQ</a></li>
|
||||
<li class="hide-before"> <a class="pf-navbar-license" href="#">License</a></li>
|
||||
<li> <a class="page-scroll" data-target="pf-landing-faq" href="#pf-landing-faq">FAQ</a></li>
|
||||
<li> <a class="pf-navbar-license" href="#">License</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1297,8 +1297,8 @@
|
||||
<div class="navbar-collapse">
|
||||
<ul class="nav navbar-nav navbar-right" role="tablist">
|
||||
<repeat group="{{ @tplNavigation }}" key="{{ @navKey }}" value="{{ @navConfig }}">
|
||||
<li class="hide-before">
|
||||
<a class="page-scroll" data-anchor="#pf-setup-{{ @navKey }}" href="#"><i class="fas fa-fw {{ @navConfig.icon }}"></i> {{ lcfirst(@navKey) }}
|
||||
<li>
|
||||
<a class="page-scroll" data-target="pf-setup-{{ @navKey }}" href="#pf-setup-{{ @navKey }}"><i class="fas fa-fw {{ @navConfig.icon }}"></i> {{ lcfirst(@navKey) }}
|
||||
<span class="badge txt-color txt-color-warning" title="warning" data-placement="bottom">{{ @tplCounter('get', @navKey . '_warning') }}</span>
|
||||
<span class="badge txt-color txt-color-danger" title="error" data-placement="bottom">{{ @tplCounter('get', @navKey . '_danger') }}</span>
|
||||
</a>
|
||||
|
||||
@@ -205,11 +205,36 @@
|
||||
}
|
||||
|
||||
// navigation link active/hover indicator =========================================================
|
||||
@mixin navigation-active-indicator($position) {
|
||||
content: '';
|
||||
position: absolute;
|
||||
background-color: $green;
|
||||
opacity: 0;
|
||||
will-change: opacity, $position ;
|
||||
@include transition( $position 0.15s ease-out, opacity 0.15s ease-out );
|
||||
@mixin pf-navigation-indicator($position){
|
||||
&:not(.disabled){
|
||||
position: relative; // otherwise :before indicator gets to height
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
#{$position}: 0;
|
||||
background-color: $green;
|
||||
opacity: 0;
|
||||
@include transition( $position 0.15s ease-out, opacity 0.15s ease-out );
|
||||
will-change: opacity, $position;
|
||||
|
||||
@if $position == 'left' {
|
||||
width: 2px;
|
||||
height: 100%;
|
||||
} @else if $position == 'top' {
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
} @else if $position == 'bottom' {
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover, &.active {
|
||||
&:before {
|
||||
#{$position}: -4px;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -333,7 +333,6 @@
|
||||
padding: 10px 10px 5px 10px;
|
||||
min-width: 155px;
|
||||
min-height: 184px;
|
||||
overflow: visible; // overwrite default
|
||||
@include border-radius(10px);
|
||||
@include box-shadow(0 4px 10px rgba(0,0,0, 0.4));
|
||||
|
||||
|
||||
@@ -664,24 +664,16 @@ table{
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.navbar-nav {
|
||||
li:not(.disabled):not(.hide-before){
|
||||
&:hover, &.active{
|
||||
|
||||
&:before{
|
||||
top: -4px;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
&:before{
|
||||
@include navigation-active-indicator(top);
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
top: 0;
|
||||
}
|
||||
.modal .navbar-nav {
|
||||
li {
|
||||
@include pf-navigation-indicator(top);
|
||||
}
|
||||
}
|
||||
|
||||
.navbar-fixed-top .navbar-nav {
|
||||
li {
|
||||
@include pf-navigation-indicator(bottom);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -883,21 +883,7 @@ $mapBubbleWidth: 30px;
|
||||
|
||||
// top menu
|
||||
&[role] > li{
|
||||
|
||||
&:not(.disabled){
|
||||
position: relative; // otherwise :before indicator gets to height
|
||||
&:before{
|
||||
@include navigation-active-indicator(left);
|
||||
width: 2px;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
&:hover:before{
|
||||
left: -4px;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@include pf-navigation-indicator(left);
|
||||
}
|
||||
|
||||
& > li {
|
||||
|
||||
Reference in New Issue
Block a user