mirror of
https://github.com/McShelby/hugo-theme-relearn.git
synced 2024-11-27 01:33:04 +00:00
nav: restore scroll position on browser back #476
This commit is contained in:
parent
02e81b6e4b
commit
c7a819323a
2 changed files with 124 additions and 47 deletions
|
@ -2,7 +2,12 @@ window.relearn = window.relearn || {};
|
|||
|
||||
window.relearn.runInitialSearch = function(){
|
||||
if( window.relearn.isSearchInit && window.relearn.isLunrInit ){
|
||||
searchDetail();
|
||||
var input = document.querySelector('#search-by-detail');
|
||||
if( !input ){
|
||||
return;
|
||||
}
|
||||
var value = input.value;
|
||||
searchDetail( value );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,24 +45,55 @@ function initLunrIndex( index ){
|
|||
}
|
||||
|
||||
function triggerSearch(){
|
||||
searchDetail();
|
||||
var input = document.querySelector('#search-by-detail');
|
||||
if( !input ){
|
||||
return;
|
||||
}
|
||||
var value = input.value;
|
||||
searchDetail( value );
|
||||
|
||||
// add a new entry to the history after the user
|
||||
// changed the term; this does not reload the page
|
||||
// but will add to the history and update the address bar URL
|
||||
var url = new URL( window.location );
|
||||
var oldValue = url.searchParams.get('search-by');
|
||||
var oldValue = url.searchParams.get( 'search-by' );
|
||||
if( value != oldValue ){
|
||||
url.searchParams.set('search-by', value);
|
||||
window.history.pushState(url.toString(), '', url);
|
||||
var state = window.history.state || {};
|
||||
state = Object.assign( {}, ( typeof state === 'object' ) ? state : {} );
|
||||
url.searchParams.set( 'search-by', value );
|
||||
state.search = url.toString();
|
||||
// with normal pages, this is handled by the 'pagehide' event, but this
|
||||
// doesn't fire in case of pushState, so we have to do the same thing
|
||||
// here, too
|
||||
state.contentScrollTop = elc.scrollTop;
|
||||
window.history.pushState( state, '', url );
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('popstate', function ( event ) {
|
||||
window.addEventListener( 'popstate', function ( event ){
|
||||
// restart search if browsed thru history
|
||||
if (event.state && event.state.indexOf('search.html?search-by=') >= 0) {
|
||||
window.location.reload();
|
||||
if( event.state ){
|
||||
var state = window.history.state || {};
|
||||
state = Object.assign( {}, ( typeof state === 'object' ) ? state : {} );
|
||||
if( state.search ) {
|
||||
var url = new URL( state.search );
|
||||
if( url.searchParams.has('search-by') ){
|
||||
var search = url.searchParams.get( 'search-by' );
|
||||
|
||||
// we have to insert the old search term into the inputs
|
||||
var inputs = document.querySelectorAll( 'input.search-by' );
|
||||
inputs.forEach( function( e ){
|
||||
e.value = search;
|
||||
var event = document.createEvent( 'Event' );
|
||||
event.initEvent( 'input', false, false );
|
||||
e.dispatchEvent( event );
|
||||
});
|
||||
|
||||
// recreate the last search results and eventually
|
||||
// restore the previous scrolling position
|
||||
searchDetail( search );
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -161,12 +197,7 @@ function resolvePlaceholders( s, args ) {
|
|||
});
|
||||
};
|
||||
|
||||
function searchDetail() {
|
||||
var input = document.querySelector('#search-by-detail');
|
||||
if( !input ){
|
||||
return;
|
||||
}
|
||||
var value = input.value;
|
||||
function searchDetail( value ) {
|
||||
var results = document.querySelector('#searchresults');
|
||||
var hint = document.querySelector('.searchhint');
|
||||
hint.innerText = '';
|
||||
|
@ -201,14 +232,32 @@ function searchDetail() {
|
|||
}
|
||||
input.focus();
|
||||
setTimeout( adjustContentWidth, 0 );
|
||||
|
||||
// if we are initiating search because of a browser history
|
||||
// operation, we have to restore the scrolling postion the
|
||||
// user previously has used; if this search isn't initiated
|
||||
// by a browser history operation, it simply does nothing
|
||||
var state = window.history.state || {};
|
||||
state = Object.assign( {}, ( typeof state === 'object' ) ? state : {} );
|
||||
if( state.contentScrollTop ){
|
||||
window.setTimeout( function(){
|
||||
elc.scrollTop = state.contentScrollTop;
|
||||
}, 10 );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
initLunrJson();
|
||||
initLunrJs();
|
||||
|
||||
function startSearch(){
|
||||
var url = new URL( window.location );
|
||||
window.history.replaceState(url.toString(), '', url);
|
||||
var input = document.querySelector('#search-by-detail');
|
||||
if( input ){
|
||||
var state = window.history.state || {};
|
||||
state = Object.assign( {}, ( typeof state === 'object' ) ? state : {} );
|
||||
state.search = window.location.toString();
|
||||
window.history.replaceState( state, '', window.location );
|
||||
}
|
||||
|
||||
var searchList = new autoComplete({
|
||||
/* selector for the search box element */
|
||||
|
|
|
@ -815,31 +815,69 @@ function initHistory() {
|
|||
}
|
||||
}
|
||||
|
||||
function scrollToActiveMenu() {
|
||||
window.setTimeout(function(){
|
||||
function initScrollPositionSaver(){
|
||||
function savePosition( event ){
|
||||
var state = window.history.state || {};
|
||||
state = Object.assign( {}, ( typeof state === 'object' ) ? state : {} );
|
||||
state.contentScrollTop = elc.scrollTop;
|
||||
window.history.replaceState( state, '', window.location );
|
||||
};
|
||||
window.addEventListener( 'pagehide', savePosition );
|
||||
}
|
||||
|
||||
function scrollToPositions() {
|
||||
// show active menu entry
|
||||
window.setTimeout( function(){
|
||||
var e = document.querySelector( '#sidebar ul.topics li.active a' );
|
||||
if( e && e.scrollIntoView ){
|
||||
e.scrollIntoView({
|
||||
block: 'center',
|
||||
});
|
||||
}
|
||||
}, 10);
|
||||
}
|
||||
}, 10 );
|
||||
|
||||
function scrollToFragment() {
|
||||
if( !window.location.hash || window.location.hash.length <= 1 ){
|
||||
// scroll the content to point of interest;
|
||||
// if we have a scroll position saved, the user was here
|
||||
// before in his history stack and we want to reposition
|
||||
// to the position he was when he left the page;
|
||||
// otherwise if he used page search before, we want to position
|
||||
// to its last outcome;
|
||||
// otherwise he may want to see a specific fragment
|
||||
|
||||
var state = window.history.state || {};
|
||||
state = ( typeof state === 'object') ? state : {};
|
||||
if( state.contentScrollTop !== undefined ){
|
||||
window.setTimeout( function(){
|
||||
elc.scrollTop = state.contentScrollTop;
|
||||
}, 10 );
|
||||
return;
|
||||
}
|
||||
|
||||
var searchValue = sessionStorage.getItem( baseUriFull+'search-value' );
|
||||
var found = elementContains( searchValue, elc );
|
||||
var searchedElem = found.length && found[ 0 ];
|
||||
if( searchedElem ){
|
||||
searchedElem.scrollIntoView( true );
|
||||
var scrolledY = window.scrollY;
|
||||
if( scrolledY ){
|
||||
window.scroll( 0, scrolledY - 125 );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if( window.location.hash && window.location.hash.length > 1 ){
|
||||
window.setTimeout( function(){
|
||||
try{
|
||||
var e = document.querySelector( window.location.hash );
|
||||
if( e && e.scrollIntoView ){
|
||||
e.scrollIntoView({
|
||||
block: 'start',
|
||||
});
|
||||
}
|
||||
} catch( e ){}
|
||||
}, 10 );
|
||||
return;
|
||||
}
|
||||
window.setTimeout(function(){
|
||||
try{
|
||||
var e = document.querySelector( window.location.hash );
|
||||
if( e && e.scrollIntoView ){
|
||||
e.scrollIntoView({
|
||||
block: 'start',
|
||||
});
|
||||
}
|
||||
} catch( e ){}
|
||||
}, 10);
|
||||
}
|
||||
|
||||
function mark() {
|
||||
|
@ -1064,25 +1102,15 @@ function initSearch() {
|
|||
}
|
||||
mark();
|
||||
|
||||
// set initial search value on page load
|
||||
// set initial search value for inputs on page load
|
||||
if( sessionStorage.getItem( baseUriFull+'search-value' ) ){
|
||||
var searchValue = sessionStorage.getItem( baseUriFull+'search-value' );
|
||||
var search = sessionStorage.getItem( baseUriFull+'search-value' );
|
||||
inputs.forEach( function( e ){
|
||||
e.value = searchValue;
|
||||
e.value = search;
|
||||
var event = document.createEvent( 'Event' );
|
||||
event.initEvent( 'input', false, false );
|
||||
e.dispatchEvent( event );
|
||||
});
|
||||
|
||||
var found = elementContains( searchValue, document.querySelector( '#body-inner' ) );
|
||||
var searchedElem = found.length && found[ 0 ];
|
||||
if( searchedElem ){
|
||||
searchedElem.scrollIntoView( true );
|
||||
var scrolledY = window.scrollY;
|
||||
if( scrolledY ){
|
||||
window.scroll( 0, scrolledY - 125 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.relearn.isSearchInit = true;
|
||||
|
@ -1094,8 +1122,6 @@ ready( function(){
|
|||
initMermaid();
|
||||
initSwagger();
|
||||
initMenuScrollbar();
|
||||
scrollToActiveMenu();
|
||||
scrollToFragment();
|
||||
initToc();
|
||||
initAnchorClipboard();
|
||||
initCodeClipboard();
|
||||
|
@ -1104,6 +1130,8 @@ ready( function(){
|
|||
initHistory();
|
||||
initSearch();
|
||||
initImage();
|
||||
initScrollPositionSaver();
|
||||
scrollToPositions();
|
||||
});
|
||||
|
||||
function useMermaid( config ){
|
||||
|
|
Loading…
Reference in a new issue