feat: command bar bound to "Escape" key

This commit is contained in:
Joshua Seigler 2016-10-13 11:41:41 -04:00
parent 22927bfd38
commit d08935c71e
4 changed files with 166 additions and 17 deletions

View file

@ -5,12 +5,32 @@
<title>Janus Presentation Framework</title> <title>Janus Presentation Framework</title>
<link rel="stylesheet" href="styles/main.css" charset="utf-8"> <link rel="stylesheet" href="styles/main.css" charset="utf-8">
</head> </head>
<body> <body class="is-loading">
<nav>
<label for="commandField">Command:</label>
<input list="commands" type="text" id="commandField" autocomplete="off" pattern="[0-9]+|[spc]">
<ul class="help">
<li>
<strong>#</strong> - jump to a slide item
</li>
<li>
<strong>s</strong> - toggle projector simulation
</li>
<li>
<strong>p</strong> - toggle presenter mode
</li>
<li>
<strong>c</strong> - clone window
</li>
</ul>
</nav>
<main> <main>
<section style="background: linear-gradient(-30deg, black, rebeccapurple)"> <section style="background: linear-gradient(-30deg, black, rebeccapurple)">
<h1>Janus Presentations</h1> <h1>Janus Presentations</h1>
<h2>Hotkey powered, multi-window presentations</h2> <h2>Hotkey powered, multi-window presentations</h2>
<div>Press <code>Page Down</code> to continue.</div> <div><small>
Press <code>Escape</code> for commands. <code>Page Up</code> / <code>Page Down</code> to navigate.
</small></div>
</section> </section>
<section style="background: linear-gradient(-30deg, #400, black)"> <section style="background: linear-gradient(-30deg, #400, black)">
<h1>Hotkeys</h1> <h1>Hotkeys</h1>
@ -24,7 +44,7 @@
Toggle Presenter Mode: <code>F1</code> Toggle Presenter Mode: <code>F1</code>
</div> </div>
</section> </section>
<section style="text-shadow: 0 0 1em black;"> <section style="color: black">
<img class="cover" src="https://placekitten.com/1024/768" alt="" /> <img class="cover" src="https://placekitten.com/1024/768" alt="" />
<h1>Self-scaling cover images with <code>object-fit</code></h1> <h1>Self-scaling cover images with <code>object-fit</code></h1>
</section> </section>
@ -47,7 +67,7 @@
<h1>The end.</h1> <h1>The end.</h1>
</section> </section>
</main> </main>
<script type="text/javascript" src="scripts/shortcut.js"></script> <script type="text/javascript" src="libs/openjs-shortcut/shortcut.js"></script>
<script type="text/javascript" src="scripts/app.js"></script> <script type="text/javascript" src="scripts/app.js"></script>
</body> </body>
</html> </html>

View file

@ -4,7 +4,10 @@
var slides = [], var slides = [],
currentSlideNumber = 0, currentSlideNumber = 0,
slideNext, slideNext,
slidePrev; slidePrev,
commandBar,
commandField,
commandBarVisible = true;
function $(selector) { function $(selector) {
return document.querySelector(selector); return document.querySelector(selector);
@ -13,12 +16,14 @@
return Array.prototype.slice.call(document.querySelectorAll(selector), 0); return Array.prototype.slice.call(document.querySelectorAll(selector), 0);
} }
function setCurrentSlide(newSlideNumber) { function setCurrentSlide(newSlideNumber, storeChange) {
newSlideNumber = Math.max(Math.min(newSlideNumber, slides.length - 1), 0); newSlideNumber = Math.max(Math.min(newSlideNumber, slides.length - 1), 0);
if (newSlideNumber !== currentSlideNumber) { if (newSlideNumber !== currentSlideNumber) {
currentSlideNumber = newSlideNumber; currentSlideNumber = newSlideNumber;
if (storeChange) {
localStorage.setItem('janus-currentSlideNumber', currentSlideNumber); localStorage.setItem('janus-currentSlideNumber', currentSlideNumber);
} }
}
slides.forEach(function (item, index, array) { slides.forEach(function (item, index, array) {
if (index < currentSlideNumber) { if (index < currentSlideNumber) {
if (slides[index].contains(slides[currentSlideNumber])) { if (slides[index].contains(slides[currentSlideNumber])) {
@ -35,15 +40,65 @@
} }
var sessionListener = function(e) { var sessionListener = function(e) {
console.log(e);
if (e.url === window.location.href) { if (e.url === window.location.href) {
if (e.key === 'janus-currentSlideNumber') { if (e.key === 'janus-currentSlideNumber') {
setCurrentSlide(+e.newValue); setCurrentSlide(+e.newValue, false);
} }
} }
}; };
var toggleCommandBar = function() {
if (commandBarVisible) {
commandBar.style.display = 'none';
commandBarVisible = false;
} else {
commandBar.style.display = 'flex';
commandField.value = '';
commandField.focus();
commandBarVisible = true;
}
}
var commandListener = function(event) {
var typed = String.fromCharCode(event.keyCode).toLowerCase();
console.log(event);
console.log(typed);
if (/[0-9]/.test(typed)) {
return;
} else if (event.keyCode === 13) {
runCommand(commandField.value);
toggleCommandBar();
} else if (/[spc]/.test(typed)) {
runCommand(commandField.value + typed);
toggleCommandBar();
}
};
var runCommand = function(command) {
var s = command.split();
if (s.length === 1 && /^[0-9]+$/.test(s[0])) {
setCurrentSlide(+s[0], true);
} else if (s.length === 1) {
switch(s[0]) {
case 's':
document.body.classList.toggle('simulate-projection');
break;
case 'p':
document.body.classList.toggle('show-notes');
break;
case 'c':
window.open(window.location.href, '_blank');
break;
}
}
}
var init = function() { var init = function() {
commandField = $('#commandField');
commandField.addEventListener('keydown', commandListener);
commandBar = $('body > nav');
toggleCommandBar();
slides = $$('main>section, [janus-timeline]'); slides = $$('main>section, [janus-timeline]');
currentSlideNumber = 0; currentSlideNumber = 0;
shortcut.add('F1', function() { shortcut.add('F1', function() {
@ -53,17 +108,19 @@
window.open(window.location.href, '_blank'); window.open(window.location.href, '_blank');
}); });
shortcut.add('Page_down', function() { shortcut.add('Page_down', function() {
setCurrentSlide(currentSlideNumber + 1); setCurrentSlide(currentSlideNumber + 1, true);
}); });
shortcut.add('Page_up', function() { shortcut.add('Page_up', function() {
setCurrentSlide(currentSlideNumber - 1); setCurrentSlide(currentSlideNumber - 1, true);
}); });
shortcut.add('Escape', toggleCommandBar);
var storedSlideNumber; var storedSlideNumber;
if (storedSlideNumber = localStorage.getItem('janus-currentSlideNumber')) { if (storedSlideNumber = localStorage.getItem('janus-currentSlideNumber')) {
setCurrentSlide(storedSlideNumber); setCurrentSlide(storedSlideNumber, false);
} else { } else {
setCurrentSlide(0); setCurrentSlide(0);
} }
document.body.classList.remove('is-loading');
}; };
document.addEventListener('DOMContentLoaded', init); document.addEventListener('DOMContentLoaded', init);

View file

@ -8,7 +8,6 @@
:root { :root {
box-sizing: border-box; box-sizing: border-box;
line-height: 1.5;
font-family: sans-serif; font-family: sans-serif;
font-size: calc(2vw + 2em); font-size: calc(2vw + 2em);
} }
@ -24,6 +23,10 @@ code {
h1 { h1 {
font-size: 1.5rem; font-size: 1.5rem;
position: relative;
margin: 0 -10vw;
padding: 0 10vw 0.1em;
background-color: rgba(255, 255, 255, 0.2);
} }
h2 { h2 {
font-size: 1rem; font-size: 1rem;
@ -43,6 +46,25 @@ body {
overflow: hidden; overflow: hidden;
} }
body.is-loading:after {
content: 'Loading...';
font-size: 0.5em;
line-height: 100vh;
color: white;
background-image: linear-gradient(45deg, #030, #000, #003);
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
text-align: center;
z-index: 100;
}
body.simulate-projection {
filter: brightness(1.5) contrast(0.65);
}
main { main {
margin-top: 0; margin-top: 0;
perspective: 100vmin; perspective: 100vmin;
@ -51,6 +73,51 @@ main {
} }
/* Components */ /* Components */
nav {
flex-wrap: wrap;
display: flex;
position: fixed;
top: 0;
left: 0;
right: 0;
padding: 0.25em 0.25em 4em;
transition: transform ease 0.5s;
font-size: 0.5rem;
z-index: 2;
background-image: linear-gradient(to top, hsla(0, 0%, 0%, 0), hsla(0, 0%, 0%, 0.5));
}
nav > label {
flex: 0 0 auto;
padding-right: 1ch;
}
nav > input {
flex: 1 1 auto;
padding: 0;
font-size: inherit;
border: none;
background: transparent;
color: inherit;
}
nav > input:invalid {
color: red;
}
ul.help {
width: 100%;
flex-shrink: 0;
font-size: 0.5em;
}
ul.help li {
display: inline-block;
background-color: hsla(0, 0%, 100%, 0.2);
border-radius: 0.5em;
padding: 0 0.5em;
}
section { section {
position: absolute; position: absolute;
z-index: 1; z-index: 1;
@ -68,6 +135,12 @@ section {
transform-origin: 50% 50%; transform-origin: 50% 50%;
} }
/*
section > * {
transform: rotate(-7deg);
}
*/
[janus-timeline='past'] { [janus-timeline='past'] {
transition: transform ease-in 0.5s, opacity ease-in 0.5s, visibility step-end 0.5s; transition: transform ease-in 0.5s, opacity ease-in 0.5s, visibility step-end 0.5s;
} }
@ -76,11 +149,9 @@ section {
transition: transform ease-out 0.5s, opacity ease-out 0.5s, visibility step-start 0.5s; transition: transform ease-out 0.5s, opacity ease-out 0.5s, visibility step-start 0.5s;
} }
@media not print {
[janus-timeline='future'] { [janus-timeline='future'] {
visibility: hidden; visibility: hidden;
} }
}
body.show-notes section [janus-timeline='future'] { body.show-notes section [janus-timeline='future'] {
visibility: visible; visibility: visible;
@ -119,6 +190,7 @@ img.cover {
width: 100%; width: 100%;
object-fit: cover; object-fit: cover;
z-index: -1; z-index: -1;
transform: none;
} }
body.show-notes section { body.show-notes section {