具有自定义后退按钮行为的单页静态网站

时间:2018-07-23 15:23:47

标签: javascript html5-history

我一直在努力寻找解决我问题的简单方法。我有一个单页静态网站(请参见操作here)。每个视图都由一个哈希片段(用于直接链接)标识,并且HTML具有与哈希片段的锚链接,作为href,用于在视图之间导航。

我想要后退按钮的自定义行为。该网站具有层次结构,而不是迭代所有以前访问的视图,我希望后退按钮在层次结构中向上移动,然后将网站移至历史上其他任何位置。

经过多次迭代,我在下面共享的代码确实满足了这些要求,但是我想知道这是否是最简单的方法...

最终解决我的问题的诀窍归结为:

  • 不构建 no 历史记录堆栈,但对所有导航使用replaceState方法。仅在初始化期间,才需要一个pushState来防止在第一次按下后退按钮时离开页面

  • 捕获点击事件,不要让浏览器处理导航(因为它会建立历史记录)

  • 捕获popstate事件(=后退按钮)以实现自定义行为,并在此处理程序中,确保当您不想将页面留在下一个页面时,发出新的pushState后退按钮按下

这是我的代码:

// Single page static website
// with collapsible content in a two-level hierarchy
// three levels of detail:
// 0. the h1 headers are displayed, all are collapsed
// 1. one h1 header is expanded, showing the contained h2 headers
// 2. one h2 header is expanded, showing the contained content
// The user navigates the site by the provided anchor links,
// expanding or callapsing headings to change the level of detail,
// or by pressing the back button
// The back button doesn't go to the previous state, 
// but moves the view one level up in the hierarchy,
// collapsing the current level of detail.
// When the top level is reached, the back button will leave the site.
// This avoids the user being 'trapped' in the site after a lot of
// navigation and allow him to leave the site by pressing the back
// button no more than 3 times.

var expansion = 0; // keep track of the current level of detail
var history_back = 1; // keep track of the history stack 

// Functions to take care of everything that must happen upon navigation:
// changing the page view and updating the history.
// Note that no actual history stack is being built,
// replaceState is called to update the title and the hash fragment
function headerOnClick(header) {
  expansion = 0;
  // [code to change the page view]
  // update history
  window.history.replaceState({}, "Katholieke Gebeden", "#");
}
function h1OnClick(h1) {
  expansion = 1;
  // [code to change the page view]
  // update history
  window.history.replaceState({}, "Katholieke Gebeden" + $(h1).text(), "#" + $(h1).attr('id'));

}
function h2OnClick(h2) {
  expansion = 2;
  // [code to change the page view]
  // update history
  window.history.replaceState({}, "Katholieke Gebeden" + $(h2).text(), "#" + $(h2).attr('id'));
  }
}

// Initialization
$(function() {

  // function to dispatch navigation action to the proper function
  var navigateToHash = function(hash) {
    if (hash && hash != '#') {
      var presetHeader = $(hash);
      if (presetHeader.is('h1')) {
        h1OnClick(presetHeader);
      } else {
        h2OnClick(presetHeader);
      }
    } else {
      headerOnClick($('header'));
    }
  };

  // on initialization, push the initial state once, 
  // otherwise the first back button will leave the page
  window.history.pushState({}, window.document.title, window.location.hash); 

  // navigate to the initial view  
  // (e.g. when been called with hash fragment in the URL)
  navigateToHash(window.location.hash);

  // handle the back button
  $(window).on('popstate', function(event) {
    // keep track of the history stack
    history_back -= 1;
    if (expansion >= 1 && history_back < 1) {
      // if expansion >= 1, push the history, 
      // so people won't leave the site when pushing back
      // if expansion = 0, don't push the history, 
      // otherwise people won't be able to leave the site
      window.history.pushState({}, window.document.title, window.location.hash); 
      history_back += 1;
    }
    if (expansion == 2) {
      // find the parent h1 and navigate there
      var openH1 = $('h1.selected'); 
      navigateToHash("#" + openH1.attr('id'));
    } else if (expansion == 1) {
      // collapse everything
      navigateToHash("#");
    } else { // expansion == 0
      // allow browser to leave the site
    }
    return false;
  });

  // handle the user performing a navigation
  $('body').on('click', 'a[href*="#"]', function(event) {
    // prevent the browser doing the navigation and updating the history
    event.preventDefault();
    navigateToHash(this.hash);
    return false;
  });
});

0 个答案:

没有答案