Skip to content

Commit

Permalink
Merge pull request #248 from mcaskill/alter-history
Browse files Browse the repository at this point in the history
Added 'alterChangeState' handler
  • Loading branch information
Miguel Pérez committed Feb 7, 2016
2 parents 227dfaf 2ce6150 commit 0330e73
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 52 deletions.
2 changes: 1 addition & 1 deletion .jshintrc
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 19,7 @@
"undef": true,
"unused": "vars",
"strict": true,
"maxparams": 4,
"maxparams": 5,
"maxdepth": 4,
"maxstatements": 15,
"maxcomplexity": 7
Expand Down
73 changes: 55 additions & 18 deletions demos/barebones/jquery.smoothState.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 58,9 @@
/** The name of the event we will listen to from anchors if we're prefetching */
prefetchOn: 'mouseover touchstart',

/** jQuery selector to specify elements which should not be prefetched */
prefetchBlacklist: '.no-prefetch',

/** The number of pages smoothState will try to store in memory */
cacheLength: 0,

Expand All @@ -69,13 72,24 @@

/**
* A function that can be used to alter the ajax request settings before it is called
* @param {Object} request jQuery.ajax settings object that will be used to make the request
* @param {Object} request - jQuery.ajax settings object that will be used to make the request
* @return {Object} Altered request object
*/
alterRequest: function (request) {
return request;
},

/**
* A function that can be used to alter the state object before it is updated or added to the browsers history
* @param {Object} state - An object that will be assigned to history entry
* @param {string} title - The history entry's title. For reference only
* @param {string} url - The history entry's URL. For reference only
* @return {Object} Altered state object
*/
alterChangeState: function (state, title, url) {
return state;
},

/** Run before a page load has been activated */
onBefore: function ($currentTarget, $container) {},

Expand Down Expand Up @@ -226,20 240,22 @@

/**
* Stores a document fragment into an object
* @param {object} object - object where it will be stored
* @param {string} url - name of the entry
* @param {string|document} doc - entire html
* @param {string} id - the id of the fragment
*
* @param {object} object - object where it will be stored
* @param {string} url - name of the entry
* @param {string|document} doc - entire html
* @param {string} id - the id of the fragment
* @param {object} state - the history entry's object
* @return {object} updated object store
*/
storePageIn: function (object, url, doc, id) {
storePageIn: function (object, url, doc, id, state) {
var $html = $( '<html></html>' ).append( $(doc) );
object[url] = { // Content is indexed by the url
status: 'loaded',
// Stores the title of the page, .first() prevents getting svg titles
title: $html.find('title').first().text(),
html: $html.find('#' id), // Stores the contents of the page
doc: doc, // Stores the whole page document
state: state, // Stores the history entry for comparisons
};
return object;
},
Expand Down Expand Up @@ -294,9 310,14 @@
if(e.state !== null) {
var url = window.location.href,
$page = $('#' e.state.id),
page = $page.data('smoothState');
page = $page.data('smoothState'),
diffUrl = (page.href !== url && !utility.isHash(url, page.href)),
diffState = (event.state !== page.cache[page.href].state);

if(page.href !== url && !utility.isHash(url, page.href)) {
if(diffUrl || diffState) {
if (diffState) {
page.clear(page.href);
}
page.load(url, false);
}
}
Expand Down Expand Up @@ -326,6 347,9 @@
/** Variable that stores pages after they are requested */
cache = {},

/** Variable that stores data for a history entry */
state = {},

/** Url of the content that is currently displayed */
currentHref = window.location.href,

Expand All @@ -346,8 370,8 @@

/**
* Fetches the contents of a url and stores it in the 'cache' variable
* @param {String|Object} request url or request settings object
* @param {Function} callback function that will run as soon as it finishes
* @param {String|Object} request - url or request settings object
* @param {Function} callback - function that will run as soon as it finishes
*/
fetch = function (request, callback) {

Expand All @@ -372,19 396,19 @@
var ajaxRequest = $.ajax(settings);

// Store contents in cache variable if successful
ajaxRequest.success(function (html) {
ajaxRequest.done(function (html) {
utility.storePageIn(cache, settings.url, html, elementId);
$container.data('smoothState').cache = cache;
});

// Mark as error to be acted on later
ajaxRequest.error(function () {
ajaxRequest.fail(function () {
cache[settings.url].status = 'error';
});

// Call fetch callback
if(callback) {
ajaxRequest.complete(callback);
ajaxRequest.always(callback);
}
},

Expand Down Expand Up @@ -496,7 520,14 @@
}

if (push) {
window.history.pushState({ id: elementId }, cache[settings.url].title, settings.url);
/** Prepare a history entry */
state = options.alterChangeState({ id: elementId }, cache[settings.url].title, settings.url);

/** Update the cache to include the history entry for future comparisons */
cache[settings.url].state = state;

/** Add history entry */
window.history.pushState(state, cache[settings.url].title, settings.url);
}

if (callbBackEnded && !cacheResponse) {
Expand Down Expand Up @@ -677,8 708,9 @@

if (options.anchors) {
$element.on('click', options.anchors, clickAnchor);

if (options.prefetch) {
$element.on(options.prefetchOn, options.anchors, hoverAnchor);
$element.find(options.anchors).not(options.prefetchBlacklist).on(options.prefetchOn, null, hoverAnchor);
}
}

Expand All @@ -700,11 732,16 @@

/** Sets a default state */
if(window.history.state === null) {
window.history.replaceState({ id: elementId }, document.title, currentHref);
state = options.alterChangeState({ id: elementId }, document.title, currentHref);

/** Update history entry */
window.history.replaceState(state, document.title, currentHref);
} else {
state = {};
}

/** Stores the current page in cache variable */
utility.storePageIn(cache, currentHref, document.documentElement.outerHTML, elementId);
utility.storePageIn(cache, currentHref, document.documentElement.outerHTML, elementId, state);

/** Bind all of the event handlers on the container, not anchors */
utility.triggerAllAnimationEndEvent($container, 'ss.onStartEnd ss.onProgressEnd ss.onEndEnd');
Expand Down
73 changes: 55 additions & 18 deletions demos/csstricks/jquery.smoothState.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 58,9 @@
/** The name of the event we will listen to from anchors if we're prefetching */
prefetchOn: 'mouseover touchstart',

/** jQuery selector to specify elements which should not be prefetched */
prefetchBlacklist: '.no-prefetch',

/** The number of pages smoothState will try to store in memory */
cacheLength: 0,

Expand All @@ -69,13 72,24 @@

/**
* A function that can be used to alter the ajax request settings before it is called
* @param {Object} request jQuery.ajax settings object that will be used to make the request
* @param {Object} request - jQuery.ajax settings object that will be used to make the request
* @return {Object} Altered request object
*/
alterRequest: function (request) {
return request;
},

/**
* A function that can be used to alter the state object before it is updated or added to the browsers history
* @param {Object} state - An object that will be assigned to history entry
* @param {string} title - The history entry's title. For reference only
* @param {string} url - The history entry's URL. For reference only
* @return {Object} Altered state object
*/
alterChangeState: function (state, title, url) {
return state;
},

/** Run before a page load has been activated */
onBefore: function ($currentTarget, $container) {},

Expand Down Expand Up @@ -226,20 240,22 @@

/**
* Stores a document fragment into an object
* @param {object} object - object where it will be stored
* @param {string} url - name of the entry
* @param {string|document} doc - entire html
* @param {string} id - the id of the fragment
*
* @param {object} object - object where it will be stored
* @param {string} url - name of the entry
* @param {string|document} doc - entire html
* @param {string} id - the id of the fragment
* @param {object} state - the history entry's object
* @return {object} updated object store
*/
storePageIn: function (object, url, doc, id) {
storePageIn: function (object, url, doc, id, state) {
var $html = $( '<html></html>' ).append( $(doc) );
object[url] = { // Content is indexed by the url
status: 'loaded',
// Stores the title of the page, .first() prevents getting svg titles
title: $html.find('title').first().text(),
html: $html.find('#' id), // Stores the contents of the page
doc: doc, // Stores the whole page document
state: state, // Stores the history entry for comparisons
};
return object;
},
Expand Down Expand Up @@ -294,9 310,14 @@
if(e.state !== null) {
var url = window.location.href,
$page = $('#' e.state.id),
page = $page.data('smoothState');
page = $page.data('smoothState'),
diffUrl = (page.href !== url && !utility.isHash(url, page.href)),
diffState = (event.state !== page.cache[page.href].state);

if(page.href !== url && !utility.isHash(url, page.href)) {
if(diffUrl || diffState) {
if (diffState) {
page.clear(page.href);
}
page.load(url, false);
}
}
Expand Down Expand Up @@ -326,6 347,9 @@
/** Variable that stores pages after they are requested */
cache = {},

/** Variable that stores data for a history entry */
state = {},

/** Url of the content that is currently displayed */
currentHref = window.location.href,

Expand All @@ -346,8 370,8 @@

/**
* Fetches the contents of a url and stores it in the 'cache' variable
* @param {String|Object} request url or request settings object
* @param {Function} callback function that will run as soon as it finishes
* @param {String|Object} request - url or request settings object
* @param {Function} callback - function that will run as soon as it finishes
*/
fetch = function (request, callback) {

Expand All @@ -372,19 396,19 @@
var ajaxRequest = $.ajax(settings);

// Store contents in cache variable if successful
ajaxRequest.success(function (html) {
ajaxRequest.done(function (html) {
utility.storePageIn(cache, settings.url, html, elementId);
$container.data('smoothState').cache = cache;
});

// Mark as error to be acted on later
ajaxRequest.error(function () {
ajaxRequest.fail(function () {
cache[settings.url].status = 'error';
});

// Call fetch callback
if(callback) {
ajaxRequest.complete(callback);
ajaxRequest.always(callback);
}
},

Expand Down Expand Up @@ -496,7 520,14 @@
}

if (push) {
window.history.pushState({ id: elementId }, cache[settings.url].title, settings.url);
/** Prepare a history entry */
state = options.alterChangeState({ id: elementId }, cache[settings.url].title, settings.url);

/** Update the cache to include the history entry for future comparisons */
cache[settings.url].state = state;

/** Add history entry */
window.history.pushState(state, cache[settings.url].title, settings.url);
}

if (callbBackEnded && !cacheResponse) {
Expand Down Expand Up @@ -677,8 708,9 @@

if (options.anchors) {
$element.on('click', options.anchors, clickAnchor);

if (options.prefetch) {
$element.on(options.prefetchOn, options.anchors, hoverAnchor);
$element.find(options.anchors).not(options.prefetchBlacklist).on(options.prefetchOn, null, hoverAnchor);
}
}

Expand All @@ -700,11 732,16 @@

/** Sets a default state */
if(window.history.state === null) {
window.history.replaceState({ id: elementId }, document.title, currentHref);
state = options.alterChangeState({ id: elementId }, document.title, currentHref);

/** Update history entry */
window.history.replaceState(state, document.title, currentHref);
} else {
state = {};
}

/** Stores the current page in cache variable */
utility.storePageIn(cache, currentHref, document.documentElement.outerHTML, elementId);
utility.storePageIn(cache, currentHref, document.documentElement.outerHTML, elementId, state);

/** Bind all of the event handlers on the container, not anchors */
utility.triggerAllAnimationEndEvent($container, 'ss.onStartEnd ss.onProgressEnd ss.onEndEnd');
Expand Down
Loading

0 comments on commit 0330e73

Please sign in to comment.