Skip to content

- HTML5 History API Feature #3870

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions examples/historyApi.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">

<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>fullPage.js History API Demo</title>
<meta name="author" content="Alan Alvarado" />
<meta name="description" content="fullPage very simple demo." />
<meta name="keywords" content="fullpage,jquery,demo,simple" />
<meta name="Resource-type" content="Document" />

<link rel="stylesheet" type="text/css" href="../src/fullpage.css" />
<link rel="stylesheet" type="text/css" href="examples.css" />
</head>
<body>

<div id="fullpage">
<div class="section active" id="section0" data-anchor="mysection0"><h1>fullPage.js</h1></div>
<div class="section" id="section1" data-anchor="mysection1">
<div class="slide " data-anchor="myslide0"><h1>Simple Demo</h1></div>
<div class="slide active" data-anchor="myslide1"><h1>Only text</h1></div>
<div class="slide" data-anchor="myslide2"><h1>And text</h1></div>
<div class="slide" data-anchor="myslide3"><h1>And more text</h1></div>
</div>
<div class="section" id="section2" data-anchor="mysection2"><h1>No wraps, no extra markup</h1></div>
<div class="section" id="section3" data-anchor="mysection3"><h1>Just the simplest demo ever</h1></div>
</div>

<script type="text/javascript" src="../src/fullpage.js"></script>
<script type="text/javascript">
var myFullpage = new fullpage('#fullpage', {
sectionsColor: ['#f2f2f2', '#4BBFC3', '#7BAABE', 'whitesmoke', '#ccddff'],
navigation: true,
historyApi: true
});
</script>
</body>
</html>
135 changes: 126 additions & 9 deletions src/fullpage.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@
keyboardScrolling: true,
animateAnchor: true,
recordHistory: true,
historyApi: false,

//design
controlArrows: true,
Expand Down Expand Up @@ -668,11 +669,34 @@

//setting the class for the body element
setBodyClass();
/*
* HTML5 History API
* Test history features
*/
if(options.historyApi){
historyApiTestFeatures();
}

if(document.readyState === 'complete'){
scrollToAnchor();
/*
* HTML5 History API
* Scroll to the right section on document complete
*/
if(options.historyApi){
historyApiScrollToPath();
} else {
scrollToAnchor();
}
}
/*
* HTML5 History API
* Scroll to the right section on document load
*/
if(options.historyApi) {
window.addEventListener('load', historyApiScrollToPath);
} else {
window.addEventListener('load', scrollToAnchor);
}
window.addEventListener('load', scrollToAnchor);

//if we use scrollOverflow we'll fire afterRender in the scrolloverflow file
if(!options.scrollOverflow){
Expand Down Expand Up @@ -725,6 +749,13 @@
forMouseLeaveOrTouch(eventName, true);
});
}
/**
* HTML5 History API
* Scroll to the right section when clicking on back or forward buttons
*/
if(options.historyApi) {
window.addEventListener('popstate', historyApiPopStateHandler);
}
}

function delegatedEvents(e){
Expand Down Expand Up @@ -2143,6 +2174,75 @@
}
});
}

/**
* HTML5 History API
* Function called on init()
* It will test for history api features
*/
function historyApiTestFeatures() {
if ('scrollRestoration' in history) {
window.history.scrollRestoration = 'manual';
}
}

/**
* HTML5 History API
* Function called from popstate eventlistener
* It will scroll to the right section and slide (restore state) when the user clicks on back or forward buttons
*/
function historyApiPopStateHandler(event) {
var state = historyApiStateFromUrlString(event.state);
moveTo(state.section, state.slide);
}

/**
* HTML5 History API
* Will push a new history state and url only if the same record is not already in the previous history.state
* This will prevent from adding the same state when using the back or forward buttons
*/
function historyApiPushRecord(url) {
if(window.history.state !== url) {
window.history.pushState(url, null, '/' + url);
}
}

/**
* HTML5 History API
* Convert URL string to state object
* NOTE: If accepted, this one could be merged with getAnchorsURL(urlString) and process any urlString as input
* regardless if it starts with #, / or #/
*/
function historyApiStateFromUrlString(urlString) {
var urlParts = urlString;
var section;
var slide;

if (urlString && urlString !== '/' ) {
urlParts = urlParts.replace(/^\//, '').split('/');
section = urlParts[0];
slide = urlParts[1];
} else if (!urlString) {
// TODO: In the future this should query for the default active section/slide
section = 1;
}

return {
section: section,
slide: slide
}
}

/**
* HTML5 History API
* Get the url from location.pathname and scroll to the right section and slide when loading the site
*/
function historyApiScrollToPath() {
if( window.location.pathname !== '/' ) {
var path = historyApiStateFromUrlString(window.location.pathname);
moveTo(path.section, path.slide);
}
}

/**
* Gets the active slide (or section) for the given section
Expand Down Expand Up @@ -2962,14 +3062,26 @@
*/
function setUrlHash(url){
if(options.recordHistory){
location.hash = url;
if(options.historyApi) {
// Pushes State to history api
historyApiPushRecord(url);
} else {
location.hash = url;
}

}else{
//Mobile Chrome doesn't work the normal way, so... lets use HTML5 for phones :)
if(isTouchDevice || isTouch){
window.history.replaceState(undefined, undefined, '#' + url);
}else{
var baseUrl = window.location.href.split('#')[0];
window.location.replace( baseUrl + '#' + url );

if(options.historyApi) {
// Pushes State to history api
historyApiPushRecord(url);
} else {
//Mobile Chrome doesn't work the normal way, so... lets use HTML5 for phones :)
if(isTouchDevice || isTouch){
window.history.replaceState(undefined, undefined, '#' + url);
}else{
var baseUrl = window.location.href.split('#')[0];
window.location.replace( baseUrl + '#' + url );
}
}
}
}
Expand Down Expand Up @@ -3299,6 +3411,11 @@
['mouseenter', 'touchstart', 'mouseleave', 'touchend'].forEach(function(eventName){
document.removeEventListener(eventName, onMouseEnterOrLeave, true); //true is required!
});
/**
* HTML5 History API
* Remove EventListener Needed for back and forward buttons to work
*/
window.removeEventListener('popstate', historyApiPopStateHandler);

//lets make a mess!
if(all){
Expand Down