142 lines
4.3 KiB
JavaScript
142 lines
4.3 KiB
JavaScript
|
/*!
|
||
|
Deck JS - deck.hash
|
||
|
Copyright (c) 2011 Caleb Troughton
|
||
|
Dual licensed under the MIT license and GPL license.
|
||
|
https://github.com/imakewebthings/deck.js/blob/master/MIT-license.txt
|
||
|
https://github.com/imakewebthings/deck.js/blob/master/GPL-license.txt
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
This module adds deep linking to individual slides, enables internal links
|
||
|
to slides within decks, and updates the address bar with the hash as the user
|
||
|
moves through the deck. A permalink anchor is also updated. Standard themes
|
||
|
hide this link in browsers that support the History API, and show it for
|
||
|
those that do not. Slides that do not have an id are assigned one according to
|
||
|
the hashPrefix option. In addition to the on-slide container state class
|
||
|
kept by core, this module adds an on-slide state class that uses the id of each
|
||
|
slide.
|
||
|
*/
|
||
|
(function ($, deck, window, undefined) {
|
||
|
var $d = $(document),
|
||
|
$window = $(window),
|
||
|
|
||
|
/* Collection of internal fragment links in the deck */
|
||
|
$internals,
|
||
|
|
||
|
/*
|
||
|
Internal only function. Given a string, extracts the id from the hash,
|
||
|
matches it to the appropriate slide, and navigates there.
|
||
|
*/
|
||
|
goByHash = function(str) {
|
||
|
var id = str.substr(str.indexOf("#") + 1),
|
||
|
slides = $[deck]('getSlides');
|
||
|
|
||
|
$.each(slides, function(i, $el) {
|
||
|
if ($el.attr('id') === id) {
|
||
|
$[deck]('go', i);
|
||
|
return false;
|
||
|
}
|
||
|
});
|
||
|
|
||
|
// If we don't set these to 0 the container scrolls due to hashchange
|
||
|
$[deck]('getContainer').scrollLeft(0).scrollTop(0);
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
Extends defaults/options.
|
||
|
|
||
|
options.selectors.hashLink
|
||
|
The element matching this selector has its href attribute updated to
|
||
|
the hash of the current slide as the user navigates through the deck.
|
||
|
|
||
|
options.hashPrefix
|
||
|
Every slide that does not have an id is assigned one at initialization.
|
||
|
Assigned ids take the form of hashPrefix + slideIndex, e.g., slide-0,
|
||
|
slide-12, etc.
|
||
|
|
||
|
options.preventFragmentScroll
|
||
|
When deep linking to a hash of a nested slide, this scrolls the deck
|
||
|
container to the top, undoing the natural browser behavior of scrolling
|
||
|
to the document fragment on load.
|
||
|
*/
|
||
|
$.extend(true, $[deck].defaults, {
|
||
|
selectors: {
|
||
|
hashLink: '.deck-permalink'
|
||
|
},
|
||
|
|
||
|
hashPrefix: 'slide-',
|
||
|
preventFragmentScroll: true
|
||
|
});
|
||
|
|
||
|
|
||
|
$d.bind('deck.init', function() {
|
||
|
var opts = $[deck]('getOptions');
|
||
|
$internals = $(),
|
||
|
slides = $[deck]('getSlides');
|
||
|
|
||
|
$.each(slides, function(i, $el) {
|
||
|
var hash;
|
||
|
|
||
|
/* Hand out ids to the unfortunate slides born without them */
|
||
|
if (!$el.attr('id') || $el.data('deckAssignedId') === $el.attr('id')) {
|
||
|
$el.attr('id', opts.hashPrefix + i);
|
||
|
$el.data('deckAssignedId', opts.hashPrefix + i);
|
||
|
}
|
||
|
|
||
|
hash ='#' + $el.attr('id');
|
||
|
|
||
|
/* Deep link to slides on init */
|
||
|
if (hash === window.location.hash) {
|
||
|
$[deck]('go', i);
|
||
|
}
|
||
|
|
||
|
/* Add internal links to this slide */
|
||
|
$internals = $internals.add('a[href="' + hash + '"]');
|
||
|
});
|
||
|
|
||
|
if (!Modernizr.hashchange) {
|
||
|
/* Set up internal links using click for the poor browsers
|
||
|
without a hashchange event. */
|
||
|
$internals.unbind('click.deckhash').bind('click.deckhash', function(e) {
|
||
|
goByHash($(this).attr('href'));
|
||
|
});
|
||
|
}
|
||
|
|
||
|
/* Set up first id container state class */
|
||
|
if (slides.length) {
|
||
|
$[deck]('getContainer').addClass(opts.classes.onPrefix + $[deck]('getSlide').attr('id'));
|
||
|
};
|
||
|
})
|
||
|
/* Update permalink, address bar, and state class on a slide change */
|
||
|
.bind('deck.change', function(e, from, to) {
|
||
|
var hash = '#' + $[deck]('getSlide', to).attr('id'),
|
||
|
hashPath = window.location.href.replace(/#.*/, '') + hash,
|
||
|
opts = $[deck]('getOptions'),
|
||
|
osp = opts.classes.onPrefix,
|
||
|
$c = $[deck]('getContainer');
|
||
|
|
||
|
$c.removeClass(osp + $[deck]('getSlide', from).attr('id'));
|
||
|
$c.addClass(osp + $[deck]('getSlide', to).attr('id'));
|
||
|
|
||
|
$(opts.selectors.hashLink).attr('href', hashPath);
|
||
|
if (Modernizr.history) {
|
||
|
window.history.replaceState({}, "", hashPath);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
/* Deals with internal links in modern browsers */
|
||
|
$window.bind('hashchange.deckhash', function(e) {
|
||
|
if (e.originalEvent && e.originalEvent.newURL) {
|
||
|
goByHash(e.originalEvent.newURL);
|
||
|
}
|
||
|
else {
|
||
|
goByHash(window.location.hash);
|
||
|
}
|
||
|
})
|
||
|
/* Prevent scrolling on deep links */
|
||
|
.bind('load', function() {
|
||
|
if ($[deck]('getOptions').preventFragmentScroll) {
|
||
|
$[deck]('getContainer').scrollLeft(0).scrollTop(0);
|
||
|
}
|
||
|
});
|
||
|
})(jQuery, 'deck', this);
|