PageSourceSearch

https://jackdreilly.github.io/presentations/cdc-2012/extensions/menu/deck.menu.js

js jackdreilly.github.io collected 2026-10-03 09:21:41 UTC 5,030 bytes, 187 lines download raw bytes

1/*!
2Deck JS - deck.menu
3Copyright (c) 2011 Caleb Troughton
4Dual licensed under the MIT license and GPL license.
5https://github.com/imakewebthings/deck.js/blob/master/MIT-license.txt
6https://github.com/imakewebthings/deck.js/blob/master/GPL-license.txt
7*/
8
9/*
10This module adds the methods and key binding to show and hide a menu of all
11slides in the deck. The deck menu state is indicated by the presence of a class
12on the deck container.
13*/
14(function($, deck, undefined) {
15	var $d = $(document),
16	rootSlides; // Array of top level slides
17	
18	/*
19	Extends defaults/options.
20	
21	options.classes.menu
22		This class is added to the deck container when showing the slide menu.
23	
24	options.keys.menu
25		The numeric keycode used to toggle between showing and hiding the slide
26		menu.
27		
28	options.touch.doubletapWindow
29		Two consecutive touch events within this number of milliseconds will
30		be considered a double tap, and will toggle the menu on touch devices.
31	*/
32	$.extend(true, $[deck].defaults, {
33		classes: {
34			menu: 'deck-menu'
35		},
36		
37		keys: {
38			menu: 77 // m
39		},
40		
41		touch: {
42			doubletapWindow: 400
43		}
44	});
45
46	/*
47	jQuery.deck('showMenu')
48	
49	Shows the slide menu by adding the class specified by the menu class option
50	to the deck container.
51	*/
52	$[deck]('extend', 'showMenu', function() {
53		var $c = $[deck]('getContainer'),
54		opts = $[deck]('getOptions');
55		
56		if ($c.hasClass(opts.classes.menu)) return;
57		
58		// Hide through loading class to short-circuit transitions (perf)
59		$c.addClass([opts.classes.loading, opts.classes.menu].join(' '));
60		
61		/* Forced to do this in JS until CSS learns second-grade math. Save old
62		style value for restoration when menu is hidden. */
63		if (Modernizr.csstransforms) {
64			$.each(rootSlides, function(i, $slide) {
65				$slide.data('oldStyle', $slide.attr('style'));
66				$slide.css({
67					'position': 'absolute',
68					'left': ((i % 4) * 25) + '%',
69					'top': (Math.floor(i / 4) * 25) + '%'
70				});
71			});
72		}
73		
74		// Need to ensure the loading class renders first, then remove
75		window.setTimeout(function() {
76			$c.removeClass(opts.classes.loading)
77				.scrollTop($[deck]('getSlide').offset().top);
78		}, 0);
79	});
80
81	/*
82	jQuery.deck('hideMenu')
83	
84	Hides the slide menu by removing the class specified by the menu class
85	option from the deck container.
86	*/
87	$[deck]('extend', 'hideMenu', function() {
88		var $c = $[deck]('getContainer'),
89		opts = $[deck]('getOptions');
90		
91		if (!$c.hasClass(opts.classes.menu)) return;
92		
93		$c.removeClass(opts.classes.menu);
94		$c.addClass(opts.classes.loading);
95		
96		/* Restore old style value */
97		if (Modernizr.csstransforms) {
98			$.each(rootSlides, function(i, $slide) {
99				var oldStyle = $slide.data('oldStyle');
100
101				$slide.attr('style', oldStyle ? oldStyle : '');
102			});
103		}
104		
105		window.setTimeout(function() {
106			$c.removeClass(opts.classes.loading).scrollTop(0);
107		}, 0);
108	});
109
110	/*
111	jQuery.deck('toggleMenu')
112	
113	Toggles between showing and hiding the slide menu.
114	*/
115	$[deck]('extend', 'toggleMenu', function() {
116		$[deck]('getContainer').hasClass($[deck]('getOptions').classes.menu) ?
117		$[deck]('hideMenu') : $[deck]('showMenu');
118	});
119
120	$d.bind('deck.init', function() {
121		var opts = $[deck]('getOptions'),
122		touchEndTime = 0,
123		currentSlide,
124		slideTest = $.map([
125			opts.classes.before,
126			opts.classes.previous,
127			opts.classes.current,
128			opts.classes.next,
129			opts.classes.after
130		], function(el, i) {
131			return '.' + el;
132		}).join(', ');
133		
134		// Build top level slides array
135		rootSlides = [];
136		$.each($[deck]('getSlides'), function(i, $el) {
137			if (!$el.parentsUntil(opts.selectors.container, slideTest).length) {
138				rootSlides.push($el);
139			}
140		});
141		
142		// Bind key events
143		$d.unbind('keydown.deckmenu').bind('keydown.deckmenu', function(e) {
144			if (e.which === opts.keys.menu || $.inArray(e.which, opts.keys.menu) > -1) {
145				$[deck]('toggleMenu');
146				e.preventDefault();
147			}
148		});
149		
150		// Double tap to toggle slide menu for touch devices
151		$[deck]('getContainer').unbind('touchstart.deckmenu').bind('touchstart.deckmenu', function(e) {
152			currentSlide = $[deck]('getSlide');
153		})
154		.unbind('touchend.deckmenu').bind('touchend.deckmenu', function(e) {
155			var now = Date.now();
156			
157			// Ignore this touch event if it caused a nav change (swipe)
158			if (currentSlide !== $[deck]('getSlide')) return;
159			
160			if (now - touchEndTime < opts.touch.doubletapWindow) {
161				$[deck]('toggleMenu');
162				e.preventDefault();
163			}
164			touchEndTime = now;
165		});
166		
167		// Selecting slides from the menu
168		$.each($[deck]('getSlides'), function(i, $s) {
169			$s.unbind('click.deckmenu').bind('click.deckmenu', function(e) {
170				if (!$[deck]('getContainer').hasClass(opts.classes.menu)) return;
171
172				$[deck]('go', i);
173				$[deck]('hideMenu');
174				e.stopPropagation();
175				e.preventDefault();
176			});
177		});
178	})
179	.bind('deck.change', function(e, from, to) {
180		var container = $[deck]('getContainer');
181		
182		if (container.hasClass($[deck]('getOptions').classes.menu)) {
183			container.scrollTop($[deck]('getSlide', to).offset().top);
184		}
185	});
186})(jQuery, 'deck');
187

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.