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(){
|
window.relearn.runInitialSearch = function(){
|
||||||
if( window.relearn.isSearchInit && window.relearn.isLunrInit ){
|
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(){
|
function triggerSearch(){
|
||||||
searchDetail();
|
|
||||||
var input = document.querySelector('#search-by-detail');
|
var input = document.querySelector('#search-by-detail');
|
||||||
if( !input ){
|
if( !input ){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var value = input.value;
|
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 url = new URL( window.location );
|
||||||
var oldValue = url.searchParams.get('search-by');
|
var oldValue = url.searchParams.get( 'search-by' );
|
||||||
if( value != oldValue ){
|
if( value != oldValue ){
|
||||||
url.searchParams.set('search-by', value);
|
var state = window.history.state || {};
|
||||||
window.history.pushState(url.toString(), '', url);
|
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
|
// restart search if browsed thru history
|
||||||
if (event.state && event.state.indexOf('search.html?search-by=') >= 0) {
|
if( event.state ){
|
||||||
window.location.reload();
|
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() {
|
function searchDetail( value ) {
|
||||||
var input = document.querySelector('#search-by-detail');
|
|
||||||
if( !input ){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var value = input.value;
|
|
||||||
var results = document.querySelector('#searchresults');
|
var results = document.querySelector('#searchresults');
|
||||||
var hint = document.querySelector('.searchhint');
|
var hint = document.querySelector('.searchhint');
|
||||||
hint.innerText = '';
|
hint.innerText = '';
|
||||||
|
@ -201,14 +232,32 @@ function searchDetail() {
|
||||||
}
|
}
|
||||||
input.focus();
|
input.focus();
|
||||||
setTimeout( adjustContentWidth, 0 );
|
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();
|
initLunrJson();
|
||||||
initLunrJs();
|
initLunrJs();
|
||||||
|
|
||||||
function startSearch(){
|
function startSearch(){
|
||||||
var url = new URL( window.location );
|
var input = document.querySelector('#search-by-detail');
|
||||||
window.history.replaceState(url.toString(), '', url);
|
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({
|
var searchList = new autoComplete({
|
||||||
/* selector for the search box element */
|
/* selector for the search box element */
|
||||||
|
|
|
@ -815,31 +815,69 @@ function initHistory() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function scrollToActiveMenu() {
|
function initScrollPositionSaver(){
|
||||||
window.setTimeout(function(){
|
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' );
|
var e = document.querySelector( '#sidebar ul.topics li.active a' );
|
||||||
if( e && e.scrollIntoView ){
|
if( e && e.scrollIntoView ){
|
||||||
e.scrollIntoView({
|
e.scrollIntoView({
|
||||||
block: 'center',
|
block: 'center',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, 10);
|
}, 10 );
|
||||||
}
|
|
||||||
|
|
||||||
function scrollToFragment() {
|
// scroll the content to point of interest;
|
||||||
if( !window.location.hash || window.location.hash.length <= 1 ){
|
// 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;
|
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() {
|
function mark() {
|
||||||
|
@ -1064,25 +1102,15 @@ function initSearch() {
|
||||||
}
|
}
|
||||||
mark();
|
mark();
|
||||||
|
|
||||||
// set initial search value on page load
|
// set initial search value for inputs on page load
|
||||||
if( sessionStorage.getItem( baseUriFull+'search-value' ) ){
|
if( sessionStorage.getItem( baseUriFull+'search-value' ) ){
|
||||||
var searchValue = sessionStorage.getItem( baseUriFull+'search-value' );
|
var search = sessionStorage.getItem( baseUriFull+'search-value' );
|
||||||
inputs.forEach( function( e ){
|
inputs.forEach( function( e ){
|
||||||
e.value = searchValue;
|
e.value = search;
|
||||||
var event = document.createEvent( 'Event' );
|
var event = document.createEvent( 'Event' );
|
||||||
event.initEvent( 'input', false, false );
|
event.initEvent( 'input', false, false );
|
||||||
e.dispatchEvent( event );
|
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;
|
window.relearn.isSearchInit = true;
|
||||||
|
@ -1094,8 +1122,6 @@ ready( function(){
|
||||||
initMermaid();
|
initMermaid();
|
||||||
initSwagger();
|
initSwagger();
|
||||||
initMenuScrollbar();
|
initMenuScrollbar();
|
||||||
scrollToActiveMenu();
|
|
||||||
scrollToFragment();
|
|
||||||
initToc();
|
initToc();
|
||||||
initAnchorClipboard();
|
initAnchorClipboard();
|
||||||
initCodeClipboard();
|
initCodeClipboard();
|
||||||
|
@ -1104,6 +1130,8 @@ ready( function(){
|
||||||
initHistory();
|
initHistory();
|
||||||
initSearch();
|
initSearch();
|
||||||
initImage();
|
initImage();
|
||||||
|
initScrollPositionSaver();
|
||||||
|
scrollToPositions();
|
||||||
});
|
});
|
||||||
|
|
||||||
function useMermaid( config ){
|
function useMermaid( config ){
|
||||||
|
|
Loading…
Reference in a new issue