Update years, links for 1.0
[deck.js.git] / extensions / hash / deck.hash.js
blob24200b750e507233f6e4232f21c89a8ee9c61142
1 /*!
2 Deck JS - deck.hash
3 Copyright (c) 2011 Caleb Troughton
4 Dual licensed under the MIT license.
5 https://github.com/imakewebthings/deck.js/blob/master/MIT-license.txt
6 */
8 /*
9 This module adds deep linking to individual slides, enables internal links
10 to slides within decks, and updates the address bar with the hash as the user
11 moves through the deck. A permalink anchor is also updated. Standard themes
12 hide this link in browsers that support the History API, and show it for
13 those that do not. Slides that do not have an id are assigned one according to
14 the hashPrefix option. In addition to the on-slide container state class
15 kept by core, this module adds an on-slide state class that uses the id of each
16 slide.
18 (function ($, undefined) {
19 var $document = $(document);
20 var $window = $(window);
22 /* Collection of internal fragment links in the deck */
23 var $fragmentLinks;
26 Internal only function. Given a string, extracts the id from the hash,
27 matches it to the appropriate slide, and navigates there.
29 var goByHash = function(str) {
30 var id = str.substr(str.indexOf("#") + 1);
31 var slides = $.deck('getSlides');
33 $.each(slides, function(i, $slide) {
34 if ($slide.attr('id') === id) {
35 $.deck('go', i);
36 return false;
38 });
40 // If we don't set these to 0 the container scrolls due to hashchange
41 if ($.deck('getOptions').preventFragmentScroll) {
42 $.deck('getContainer').scrollLeft(0).scrollTop(0);
46 var assignSlideId = function(i, $slide) {
47 var options = $.deck('getOptions');
48 var currentId = $slide.attr('id');
49 var previouslyAssigned = $slide.data('deckAssignedId') === currentId;
50 if (!currentId || previouslyAssigned) {
51 $slide.attr('id', options.hashPrefix + i);
52 $slide.data('deckAssignedId', options.hashPrefix + i);
56 var removeContainerStateClass = function(id) {
57 var options = $.deck('getOptions');
58 $.deck('getContainer').removeClass(options.classes.onPrefix + id);
61 var addContainerStateClass = function(id) {
62 var options = $.deck('getOptions');
63 $.deck('getContainer').addClass(options.classes.onPrefix + id);
67 Extends defaults/options.
69 options.selectors.hashLink
70 The element matching this selector has its href attribute updated to
71 the hash of the current slide as the user navigates through the deck.
73 options.hashPrefix
74 Every slide that does not have an id is assigned one at initialization.
75 Assigned ids take the form of hashPrefix + slideIndex, e.g., slide-0,
76 slide-12, etc.
78 options.preventFragmentScroll
79 When deep linking to a hash of a nested slide, this scrolls the deck
80 container to the top, undoing the natural browser behavior of scrolling
81 to the document fragment on load.
83 $.extend(true, $.deck.defaults, {
84 selectors: {
85 hashLink: '.deck-permalink'
88 hashPrefix: 'slide-',
89 preventFragmentScroll: true
90 });
93 $document.bind('deck.init', function() {
94 var options = $.deck('getOptions');
95 var slides = $.deck('getSlides');
97 $fragmentLinks = $();
98 $.each(slides, function(i, $slide) {
99 var hash;
101 assignSlideId(i, $slide);
102 hash = '#' + $slide.attr('id');
103 if (hash === window.location.hash) {
104 setTimeout(function() {
105 $.deck('go', i);
106 }, 1);
108 $fragmentLinks = $fragmentLinks.add('a[href="' + hash + '"]');
111 /* Set up first id container state class */
112 if (slides.length) {
113 addContainerStateClass($.deck('getSlide').attr('id'));
117 /* Update permalink, address bar, and state class on a slide change */
118 $document.bind('deck.change', function(event, from, to) {
119 var hash = '#' + $.deck('getSlide', to).attr('id');
120 var hashPath = window.location.href.replace(/#.*/, '') + hash;
121 var options = $.deck('getOptions');
123 removeContainerStateClass($.deck('getSlide', from).attr('id'));
124 addContainerStateClass($.deck('getSlide', to).attr('id'));
125 $(options.selectors.hashLink).attr('href', hashPath);
126 if (Modernizr.history) {
127 window.history.replaceState({}, "", hashPath);
131 $window.bind('hashchange.deckhash', function(event) {
132 if (event.originalEvent && event.originalEvent.newURL) {
133 goByHash(event.originalEvent.newURL);
135 else {
136 goByHash(window.location.hash);
140 $window.bind('load', function() {
141 if ($.deck('getOptions').preventFragmentScroll) {
142 $.deck('getContainer').scrollLeft(0).scrollTop(0);
145 })(jQuery);