Skip to content

Commit d0ba7ff

Browse files
authored
New "bookmark" plugin allows hotkey fast-travel to specific steps (#852)
add plugin bookmark supporting direct access via hotkeys similar to "click", we can now fast travel using hotkeys e.g. 1 2 3
1 parent 9475720 commit d0ba7ff

File tree

4 files changed

+146
-14
lines changed

4 files changed

+146
-14
lines changed

build.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ files.push('src/plugins/autoplay/autoplay.js',
1313
'src/plugins/form/form.js',
1414
'src/plugins/fullscreen/fullscreen.js',
1515
'src/plugins/goto/goto.js',
16+
'src/plugins/bookmark/bookmark.js',
1617
'src/plugins/help/help.js',
1718
'src/plugins/impressConsole/impressConsole.js',
1819
'src/plugins/media/media.js',

examples/2D-navigation/index.html

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,21 +28,42 @@ <h1>2D navigation</h1>
2828

2929
<ul>
3030
<li>Impress.js allows you to layout your presentation in a 3D space</li>
31-
<li>Now <a href="https://github.com/impress/impress.js/tree/master/src/plugins/goto">the
32-
goto plugin</a> also allows you to specify
31+
<li><a href="https://github.com/impress/impress.js/tree/master/src/plugins/goto">The
32+
goto plugin</a> allows you to specify
3333
non-linear navigation!</li>
3434
<li>This demo can be navigated by
3535
<ul>
36+
<li>continuously pressing Space</li>
3637
<li>continuously pressing Right Arrow</li>
3738
<li>continuously pressing Down Arrow</li>
3839
<li>(or freely, pressing Up, Down, Right, Left as you choose)</li>
3940
</ul>
41+
<li>It's up to you to decide which is the better structure</li>
42+
</li>
43+
</div>
44+
45+
<div id="bm0" class="step" data-scale="1" data-rel-x="1500" data-rel-y="0"
46+
data-bookmark-key-list="0">
47+
<h1>Using bookmark hotkeys</h1>
48+
<ul>
49+
<li><a href="https://github.com/impress/impress.js/tree/master/src/plugins/bookmark">The
50+
bookmark plugin</a> also allows you to specify
51+
non-linear navigation, in a different way.</li>
52+
<li>This demo can <em>also</em> be navigated by
53+
<ul>
54+
<li>pressing 1 2 3 4 5 6 7 8 9 to fast travel directly</li>
55+
<li>pressing J J J, K K K, L L L to cycle vertically</li>
56+
<li>pressing U U U, I I I, O O O to cycle horizontally</li>
57+
<li>pressing Z or [ to zoom out to the full view</li>
58+
<li>pressing 0 to come back to this text</li>
59+
</ul>
4060
</li>
4161
<li>It's up to you to decide which is the better structure</li>
4262
</ul>
4363
</div>
4464

45-
<div id="contents" class="step" data-rel-x="1500" data-rel-y="1500" data-scale="1">
65+
<div id="contents" class="step" data-rel-x="0" data-rel-y="1500" data-scale="1"
66+
data-bookmark-key-list="w" >
4667
<h1>Choosing a treat</h1>
4768

4869
<ul>
@@ -60,7 +81,8 @@ <h1>Choosing a treat</h1>
6081
<!-- Ice cream slides (3) -->
6182
<div id="icecream" class="step" data-x="2000" data-y="2000"
6283
data-goto-key-list="ArrowUp ArrowDown ArrowLeft ArrowRight"
63-
data-goto-next-list="contents icecream-pro contents crisps">
84+
data-goto-next-list="contents icecream-pro contents crisps"
85+
data-bookmark-key-list="7 u j" >
6486
<h1>Ice cream</h1>
6587

6688
<ul>
@@ -73,7 +95,8 @@ <h1>Ice cream</h1>
7395

7496
<div id="icecream-pro" class="step" data-rel-x="0" data-rel-y="1000"
7597
data-goto-key-list="ArrowUp ArrowDown ArrowLeft ArrowRight"
76-
data-goto-next-list="icecream icecream-con applepie crisps-pro">
98+
data-goto-next-list="icecream icecream-con applepie crisps-pro"
99+
data-bookmark-key-list="4 i j" >
77100
<h1>Ice cream: Pro's</h1>
78101

79102
<ul>
@@ -85,7 +108,8 @@ <h1>Ice cream: Pro's</h1>
85108

86109
<div id="icecream-con" class="step" data-rel-x="0" data-rel-y="1000"
87110
data-goto-key-list="ArrowUp ArrowDown ArrowLeft ArrowRight"
88-
data-goto-next-list="icecream-pro crisps applepie-pro crisps-con">
111+
data-goto-next-list="icecream-pro crisps applepie-pro crisps-con"
112+
data-bookmark-key-list="1 o j" >
89113
<h1>Ice cream: Con's</h1>
90114

91115
<ul>
@@ -99,7 +123,8 @@ <h1>Ice cream: Con's</h1>
99123
<!-- Crisps slides (3) -->
100124
<div id="crisps" class="step" data-x="3500" data-y="2000"
101125
data-goto-key-list="ArrowUp ArrowDown ArrowLeft ArrowRight"
102-
data-goto-next-list="icecream-con crisps-pro icecream applepie">
126+
data-goto-next-list="icecream-con crisps-pro icecream applepie"
127+
data-bookmark-key-list="8 u k" >
103128
<h1>Crisps</h1>
104129

105130
<ul>
@@ -112,7 +137,8 @@ <h1>Crisps</h1>
112137

113138
<div id="crisps-pro" class="step" data-rel-x="0" data-rel-y="1000"
114139
data-goto-key-list="ArrowUp ArrowDown ArrowLeft ArrowRight"
115-
data-goto-next-list="crisps crisps-con icecream-pro applepie-pro">
140+
data-goto-next-list="crisps crisps-con icecream-pro applepie-pro"
141+
data-bookmark-key-list="5 i k" >
116142
<h1>Crisps: Pro's</h1>
117143

118144
<ul>
@@ -127,7 +153,8 @@ <h1>Crisps: Pro's</h1>
127153

128154
<div id="crisps-con" class="step" data-rel-x="0" data-rel-y="1000"
129155
data-goto-key-list="ArrowUp ArrowDown ArrowLeft ArrowRight"
130-
data-goto-next-list="crisps-pro applepie icecream-con applepie-con">
156+
data-goto-next-list="crisps-pro applepie icecream-con applepie-con"
157+
data-bookmark-key-list="2 o k" >
131158
<h1>Crisps: Con's</h1>
132159

133160
<ul>
@@ -140,7 +167,8 @@ <h1>Crisps: Con's</h1>
140167
<!-- Apple pie slides (3) -->
141168
<div id="applepie" class="step" data-x="5000" data-y="2000"
142169
data-goto-key-list="ArrowUp ArrowDown ArrowLeft ArrowRight"
143-
data-goto-next-list="crisps-con applepie-pro crisps icecream-pro">
170+
data-goto-next-list="crisps-con applepie-pro crisps icecream-pro"
171+
data-bookmark-key-list="9 u l" >
144172
<h1>Apple pie</h1>
145173

146174
<ul>
@@ -152,7 +180,8 @@ <h1>Apple pie</h1>
152180

153181
<div id="applepie-pro" class="step" data-rel-x="0" data-rel-y="1000"
154182
data-goto-key-list="ArrowUp ArrowDown ArrowLeft ArrowRight"
155-
data-goto-next-list="applepie applepie-con crisps-pro icecream-con">
183+
data-goto-next-list="applepie applepie-con crisps-pro icecream-con"
184+
data-bookmark-key-list="6 i l" >
156185
<h1>Apple pie: Pro's</h1>
157186

158187
<ul>
@@ -165,7 +194,8 @@ <h1>Apple pie: Pro's</h1>
165194

166195
<div id="applepie-con" class="step" data-rel-x="0" data-rel-y="1000"
167196
data-goto-key-list="ArrowUp ArrowDown ArrowLeft ArrowRight"
168-
data-goto-next-list="applepie-pro conclusion crisps-con conclusion">
197+
data-goto-next-list="applepie-pro conclusion crisps-con conclusion"
198+
data-bookmark-key-list="3 o l" >
169199
<h1>Apple pie: Con's</h1>
170200

171201
<ul>
@@ -175,7 +205,8 @@ <h1>Apple pie: Con's</h1>
175205
</div>
176206

177207

178-
<div id="conclusion" class="step" data-rel-x="1000" data-rel-y="1000">
208+
<div id="conclusion" class="step" data-rel-x="1000" data-rel-y="1000"
209+
data-bookmark-key-list="q" >
179210
<h1>Conclusion</h1>
180211

181212
<p>Can I choose all three ;-)</p>
@@ -186,7 +217,8 @@ <h1>Conclusion</h1>
186217
<a href="https://www.flickr.com/photos/stevepj2009/6296334551">stevepj2009@Flickr</a> </p>
187218
</div>
188219

189-
<div id="overview" class="step" data-x="3000" data-y="2000" data-scale="9" style="pointer-events: none;">
220+
<div id="overview" class="step" data-x="3000" data-y="2000" data-scale="9" style="pointer-events: none;"
221+
data-bookmark-key-list="z [" >
190222
</div>
191223
</div>
192224

src/plugins/bookmark/README.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Bookmark
2+
3+
Nonlinear navigation similar to the Goto plugin.
4+
5+
Goto supports nonlinear navigation by *locally* defining *out-links*, accessible via the arrow keys.
6+
7+
Bookmark supports nonlinear navigation by *globally* defining *in-links*, accessible via normal keys like 1,2,3,A,B,C.
8+
9+
Example:
10+
11+
```html
12+
<!-- data-bookmark-key-list allows an "inbound"-oriented style of non-linear navigation. -->
13+
<div id="..." class="step" data-bookmark-key-list="Digit1 KeyA 1 2 3 a b c">
14+
```
15+
16+
An `id` is required on the `div`.
17+
18+
If you assign the same key to multiple steps, that hotkey will cycle among them.
19+
20+
WARNING: It's up to you to avoid reserved hotkeys H, B, P, ?, etc.
21+
22+
Author
23+
------
24+
25+
Copyright 2023 Wong Meng Weng (@mengwong)
26+
Released under the MIT license.
27+

src/plugins/bookmark/bookmark.js

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/**
2+
* Bookmark Plugin
3+
*
4+
* The bookmark plugin consists of
5+
* a pre-init plugin,
6+
* a keyup listener, and
7+
* a pre-stepleave plugin.
8+
*
9+
* The pre-init plugin surveys all step divs to set up bookmark keybindings.
10+
* The pre-stepleave plugin alters the destination when a bookmark hotkey is pressed.
11+
*
12+
* Example:
13+
*
14+
* <!-- data-bookmark-key-list allows an "inbound" style of non-linear navigation. -->
15+
* <div id="..." class="step" data-bookmark-key-list="Digit1 KeyA 1 2 3 a b c">
16+
*
17+
* See https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values for a table
18+
* of what strings to use for each key. Both .key and .code styles are recognized.
19+
*
20+
* It's up to the HTML author to avoid reserved hotkeys H, B, P, ? etc.
21+
*
22+
* Copyright 2016-2017 Henrik Ingo (@henrikingo)
23+
* Released under the MIT license.
24+
*/
25+
/* global document, impress */
26+
27+
( function( document ) {
28+
"use strict";
29+
var hotkeys = {};
30+
function hotkeyDest( event ) {
31+
return ( hotkeys.hasOwnProperty( event.key ) ? hotkeys[ event.key ] :
32+
hotkeys.hasOwnProperty( event.code ) ? hotkeys[ event.code ] : null ); }
33+
34+
// In pre-init phase, build a map of bookmark hotkey to div id, by reviewing all steps
35+
impress.addPreInitPlugin( function( root, api ) {
36+
root.querySelectorAll( ".step" ).forEach( function( div ) {
37+
if ( div.dataset.bookmarkKeyList !== undefined && div.id !== undefined ) {
38+
div.dataset.bookmarkKeyList.split( " " ).forEach( ( k ) => {
39+
if ( hotkeys.hasOwnProperty( k ) ) {
40+
hotkeys[ k ].push( div.id );
41+
} else { hotkeys[ k ] = [ div.id ]; } } ); } } );
42+
43+
api.lib.gc.addEventListener( document, "keyup", function( event ) {
44+
if ( hotkeyDest( event ) !== null ) {
45+
event.stopImmediatePropagation();
46+
api.next( event );
47+
48+
// Event.preventDefault();
49+
}
50+
} );
51+
} );
52+
53+
// In pre-stepleave phase, match a hotkey and reset destination accordingly.
54+
impress.addPreStepLeavePlugin( function( event ) {
55+
56+
// Window.console.log(`bookmark: running as PreStepLeavePlugin; event=`);
57+
// window.console.log(event)
58+
if ( ( !event || !event.origEvent ) ) { return; }
59+
var dest = hotkeyDest( event.origEvent );
60+
if ( dest ) {
61+
62+
// Window.console.log(`bookmark: recognizing hotkey ${event.code} goes to ${dest}`)
63+
var newTarget = document.getElementById( dest[ 0 ] ); // jshint ignore:line
64+
if ( newTarget ) {
65+
event.detail.next = newTarget;
66+
dest.push( dest.shift() ); // Repeated hotkey presses cycle through each dest.
67+
}
68+
}
69+
} );
70+
71+
} )( document );
72+

0 commit comments

Comments
 (0)