mirror of
https://github.com/seigler/janus
synced 2025-07-27 09:46:10 +00:00
feat: command bar bound to "Escape" key
This commit is contained in:
parent
22927bfd38
commit
d08935c71e
4 changed files with 166 additions and 17 deletions
28
index.html
28
index.html
|
@ -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>
|
||||||
|
|
|
@ -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,11 +16,13 @@
|
||||||
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;
|
||||||
localStorage.setItem('janus-currentSlideNumber', currentSlideNumber);
|
if (storeChange) {
|
||||||
|
localStorage.setItem('janus-currentSlideNumber', currentSlideNumber);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
slides.forEach(function (item, index, array) {
|
slides.forEach(function (item, index, array) {
|
||||||
if (index < currentSlideNumber) {
|
if (index < 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);
|
||||||
|
|
|
@ -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,10 +149,8 @@ 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'] {
|
||||||
|
@ -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 {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue