` elements are now allowed in slides.
177 |
178 | ## 2.0.2
179 |
180 | * Notes in `` are no longer included in the title of slides.
181 |
182 | ## 2.0.1
183 |
184 | * Fixes an issue where clicking on a link in a slide advanced the slide
185 | as well as clicked the link.
186 |
187 | ## 2.0.0
188 |
189 | * [63](https://github.com/tmcw/big/pull/63): a big performance improvement!
190 | Flipping between slides is now much faster.
191 |
192 | ## 1.0.0
193 |
194 | * [50](https://github.com/tmcw/big/issues/50) Fixed IE9 and earlier support by accessing data attributes with `getAttribute`
195 | rather than the `dataset` object.
196 | * [53](https://github.com/tmcw/big/issues/53) **Speakers notes**: adding
197 | notes in a `` element will show those notes in your developer
198 | console when you visit that slide.
199 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
6 |
7 | ## Our Standards
8 |
9 | Examples of behavior that contributes to creating a positive environment include:
10 |
11 | * Using welcoming and inclusive language
12 | * Being respectful of differing viewpoints and experiences
13 | * Gracefully accepting constructive criticism
14 | * Focusing on what is best for the community
15 | * Showing empathy towards other community members
16 |
17 | Examples of unacceptable behavior by participants include:
18 |
19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances
20 | * Trolling, insulting/derogatory comments, and personal or political attacks
21 | * Public or private harassment
22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission
23 | * Other conduct which could reasonably be considered inappropriate in a professional setting
24 |
25 | ## Our Responsibilities
26 |
27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
28 |
29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
30 |
31 | ## Scope
32 |
33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
34 |
35 | ## Enforcement
36 |
37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at tom@macwright.org. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
38 |
39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
40 |
41 | ## Attribution
42 |
43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
44 |
45 | [homepage]: http://contributor-covenant.org
46 | [version]: http://contributor-covenant.org/version/1/4/
47 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | # Blue Oak Model License
2 |
3 | Version 1.0.0
4 |
5 | ## Purpose
6 |
7 | This license gives everyone as much permission to work with
8 | this software as possible, while protecting contributors
9 | from liability.
10 |
11 | ## Acceptance
12 |
13 | In order to receive this license, you must agree to its
14 | rules. The rules of this license are both obligations
15 | under that agreement and conditions to your license.
16 | You must not do anything with this software that triggers
17 | a rule that you cannot or will not follow.
18 |
19 | ## Copyright
20 |
21 | Each contributor licenses you to do everything with this
22 | software that would otherwise infringe that contributor's
23 | copyright in it.
24 |
25 | ## Notices
26 |
27 | You must ensure that everyone who gets a copy of
28 | any part of this software from you, with or without
29 | changes, also gets the text of this license or a link to
30 | .
31 |
32 | ## Excuse
33 |
34 | If anyone notifies you in writing that you have not
35 | complied with [Notices](#notices), you can keep your
36 | license by taking all practical steps to comply within 30
37 | days after the notice. If you do not do so, your license
38 | ends immediately.
39 |
40 | ## Patent
41 |
42 | Each contributor licenses you to do everything with this
43 | software that would otherwise infringe any patent claims
44 | they can license or become able to license.
45 |
46 | ## Reliability
47 |
48 | No contributor can revoke this license.
49 |
50 | ## No Liability
51 |
52 | ***As far as the law allows, this software comes as is,
53 | without any warranty or condition, and no contributor
54 | will be liable to anyone for any damages related to this
55 | software or this license, under any kind of legal claim.***
56 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Big
2 |
3 |
4 |
5 |
6 |
7 |
8 | Big. The antidote to your presentation procrastination.
9 |
10 |
11 | A presentation system that works great for creative, hurried people making focused presentations. Stop tweaking fonts and filling slides with text. Big is a configuration-free system that naturally encourages good style.
12 |
13 | - [Features](#features)
14 | - [Quickstart installation: Glitch](#quickstart-installation-glitch)
15 | - [Alternative method: Local installation](#alternative-method-local-installation)
16 | - [Writing a presentation](#writing-a-presentation)
17 | - [Giving presentations](#giving-presentations)
18 | - [Using Big](#using-big)
19 | - [Layouts & Images](#layouts--images)
20 | - [Customizing the aspect ratio](#customizing-the-aspect-ratio)
21 | - [Avoiding line breaks](#avoiding-line-breaks)
22 | - [Auto advancing slides](#auto-advancing-slides)
23 | - [Showing code](#showing-code)
24 | - [Backgrounds & body classes](#backgrounds--body-classes)
25 | - [Themes](#themes)
26 |
27 | ## Features
28 |
29 | - The entire system is about 16kb
30 | - Slide layouts based on CSS Grid
31 | - Speakers notes appear in your developer console, which you can put on your other screen
32 | - Themes are just CSS, and easy to make
33 |
34 | ## Quickstart installation: Glitch
35 |
36 | The absolute fastest way to get started is with Glitch. Just click the link below, and you’ll get the freshest version of Big, in a Glitch app that you can edit and publish.
37 |
38 |
39 |
40 | With Glitch, your presentation will be online and open source by default. You can download it and continue to work on it offline, or if you want to start offline by default and have the files locally, follow the alternative method below 👇
41 |
42 | ## Alternative method: Local installation
43 |
44 | If you use NPM, the fastest way to get a copy of Big is this way:
45 |
46 | ```bash
47 | $ npx degit tmcw/big
48 | ```
49 |
50 | Preview the presentation locally by double-clicking on `index.html`. Create a repository with it to share the presentation with Github Pages, or post the files to any other hosting service. You’ll want to eventually use a real server instead of opening the file - to do that, install `serve` and run it:
51 |
52 | ```bash
53 | $ npm install -g serve
54 | $ serve
55 | ```
56 |
57 | ## Writing a presentation
58 |
59 | Big presentations are webpages: slides are `div` elements, and any text styling or additional elements are addable by using HTML. The text in each div is sized to fit the screen. A slide can be as simple as:
60 |
61 | ```html
62 |
Big
63 | ```
64 |
65 | If you want speakers notes - notes that you can see on your laptop screen but aren't shown on the main projector - you can use a `` element:
66 |
67 | ```html
68 |
72 | ```
73 |
74 | Open your [developer console](http://debugbrowser.com/), and you'll see your speaker notes in it when you visit that slide! In most browsers, the console is detachable, so you can move it to a different screen or window when you're giving the presentation.
75 |
76 | That's all you need to start writing presentations!
77 |
78 | ## Giving presentations
79 |
80 | You can advance slides the usual way, by clicking them. You can also use the left & right arrow keys, and the up and down arrow keys. On touch devices, you can navigate forward by tapping and also navigate forward and backwards by swiping.
81 |
82 | 
83 |
84 | Big also has three modes if you want to quickly jump to a slide, or print a presentation. You can switch between modes by hitting the `t`, `p`, and `j` keys.
85 |
86 | * **t**alk is the default mode. Slides are shown one at a time.
87 | * **p**rint: is useful for print output or as an overview: it'll include
88 | two slides per printed page, and shows speakers notes along with slides
89 | * **j**ump: Shows many slides per page, useful for quickly finding a slide and 'jumping' to it. When you're in jump mode, you can use the arrow keys to quickly select a slide and hit Enter to jump to that slide, or click the
90 | slide you want.
91 |
92 | ## Using Big
93 |
94 | Big is designed to be simple, so if you just want to give a [Takahashi](https://en.wikipedia.org/wiki/Takahashi_method) style presentation with just text, you don't need to read any further! But it can also go far beyond the basics.
95 |
96 | ### Layouts & Images
97 |
98 | Let's say you want to add some pictures to a presentation. If you just want the slide to _be_ an image, you can just make it the only thing on the slide:
99 |
100 | ```html
101 |
102 |
103 |
104 | ```
105 |
106 | And Big will appropriate size and place the image in the center.
107 |
108 | If you want an image and text, you'll need a little more infrastructure: this is where _layouts_ come in. See, the idea of Big is that it sizes text as big as it can be. This has the effect that if you include something else on a slide, like an image, then it'll be squeezed out by ever-expanding text. So if you want to include an image and some text, you'll need to set some ground rules for how much space each is permitted to take up. Luckily, this also lets us do flexible layouts of image and text - you can choose how they're arranged, and they'll gleefully comply.
109 |
110 | ```html
111 |
114 |
115 |
A longer description!
116 |
117 | ```
118 |
119 | So you'll see that we have two new attributes for this laid-out slide:
120 |
121 | `class='layout'` triggers a few styles from `big.css` that give the slide [grid layout](https://developer.mozilla.org/en-US/docs/Web/CSS/grid), make its subsections [flexbox](https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Flexbox), and tweaks how images work. For all slides that use layout, they'll use the layout class.
122 |
123 | The second bit - the `style` attribute, is where the customization comes in. The MDN documentation for [grid-template-rows](https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-rows) and [grid-template-columns](https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-columns) is where to start if you want to learn this inside & out, but for those that tend to learn from examples, here are some!
124 |
125 | **50% / 50% split columns: picture on the left, text on the right**
126 |
127 | ```html
128 |
129 |
130 |
A longer description!
131 |
132 | ```
133 |
134 | Grids read from left to right, top to bottom, unless you customize that with extra CSS. You'll need to specify at least grid-template-columns or grid-template-rows to divide up a cell: if you specify columns, it'll be divided horizontally, if rows, vertically.
135 |
136 | **75% image on the top, 25% text on the bottom**
137 |
138 | ```html
139 |
140 |
141 |
A longer description!
142 |
143 | ```
144 |
145 | This slide will be laid out vertically, with the image taking up 75% of the vertical space, text 25%.
146 |
147 | ***Three rows of a 25% image and 75% text***
148 |
149 | ```html
150 |
153 |
154 |
Yes
155 |
156 |
No
157 |
158 |
Just right, a lot of text goes here.
159 |
160 | ```
161 |
162 | ### Customizing the aspect ratio
163 |
164 | To keep presentations uniform across devices, Big keeps the aspect ratio of presentations constant by default: by default, presentations are 4:3 aspect ratio.
165 |
166 | You can customize the aspect ratio by setting a `BIG_ASPECT_RATIO` variable _before_ Big is included on a page:
167 |
168 | ```html
169 |
170 |
171 | ```
172 |
173 | You can also turn this feature off, by setting `BIG_ASPECT_RATIO` to `false`, which will let presentations occupy the aspect ratio of the device they're displayed on:
174 |
175 | ```html
176 |
177 |
178 | ```
179 |
180 | ### Avoiding line breaks
181 |
182 | By default, Big will wrap lines of text. Sometimes you don't want this to happen, if you have some text that would look odd wrapped. In this case, you can use the `nowrap` class to keep some text from wrapping.
183 |
184 | ```html
185 |
186 | beyond the for loop
187 |
188 | @tmcw / Tom MacWright
189 |
190 | ```
191 |
192 | ### Auto advancing slides
193 |
194 | Sometimes you'll give presentations like [PechaKucha](https://en.wikipedia.org/wiki/PechaKucha) and [Ignite](https://en.wikipedia.org/wiki/Ignite_(event)) involve auto-advancing slides. You can achieve this by adding a `data-time-to-next` attributes to slides: this will cause them to auto-advance after a specific number of seconds:
195 |
196 | ```html
197 |
198 | My sales pitch in 20 seconds
199 |
200 | ```
201 |
202 | ### Showing code
203 |
204 | There are many ways to do code highlighting in presentations. My personal
205 | philosophy is that you should never show more than 8 lines of code
206 | on a slide, and instead of using traditional semantic highlighting, you should
207 | manually add emphasis to focus points in the code.
208 |
209 | ```html
210 |
211 | problem one: make some animals rock
212 |
var animals = ['cats', 'dogs'];
213 |
214 | ```
215 |
216 | ```css
217 | pre {
218 | margin:0;
219 | padding:0.2em;
220 | background:#fff;
221 | color:#000;
222 | font-weight:normal;
223 | }
224 |
225 | pre em {
226 | color:#000;
227 | background:yellow;
228 | }
229 | ```
230 |
231 | But if you want traditional code highlighting, you can include [highlight.js](https://highlightjs.org/) to do just that. You'll want to include [the library](https://highlightjs.org/download/), and use `hljs.initHighlightingOnLoad();` like [in their usage instructions](https://highlightjs.org/usage/).
232 |
233 | ### Backgrounds & body classes
234 |
235 | You might want to customize the class & style of the body element for a single slide. For example, maybe you want to change the background of the full page. You can do this with two attributes: `data-body-style` and `data-body-class`:
236 |
237 | ```html
238 |
239 |
Slide will have an airplane background
240 |
241 | ```
242 |
243 | ### Themes
244 |
245 | Big presentations are hackable, so you can design yours from scratch, or by customizing one of the default themes, but there are also a few default themes so that you can get going with a solid aesthetic right off the bat.
246 |
247 | At the very least, themes are CSS files. You can pick a theme by picking one in the `themes` directory. Bundled with Big are these themes:
248 |
249 | - **dark**: near-black background and near-white text, this one is my go-to for most presentations that rely on underpowered projectors.
250 | - **light**: like dark, but flipped.
251 | - **white**: instead of tastefully off-white and off-black, this theme uses stark, literal black & white colors.
252 |
--------------------------------------------------------------------------------
/UPGRADING.md:
--------------------------------------------------------------------------------
1 | # Upgrading to Big 4
2 |
3 | Change for the better. Big 4 is a lot different.
4 |
5 | ## No more NPM
6 |
7 | Big used to provide a bunch of utilities: big-compose so you could write presentations in Markdown, big-offline so you could make them work offline, big-init to start presentations, big-serve so you could serve them. I removed all of these.
8 |
9 | **I removed big-compose** because I never used it, and it was never possible to do everything in Markdown, especially not layouts. Big is opinionated software: in particular, my opinions, and those I acquire from smart people along the way. One of those opinions is that HTML’s a pretty good language and if you aren't writing a lot, it’s perfectly usable as a markup language for text.
10 |
11 | **big-offline** was cool, but I recommend using your browser’s “save webpage” feature instead, which produces a more efficient result and you already have in your web browser. I really recommend making your presentations work offline by default, too, by uploading images and keeping all your resources close.
12 |
13 | **big-serve** was just a HTTP server. I don't underestimate the difficulty of setting up an HTML server for a lot of folks, but those folks are better served by double-clicking the `index.html` file, and local servers are really good in other projects, like the `serve` module.
14 |
15 | **big-init** should just be a download. Now it is.
16 |
17 | ## No more audio tracks
18 |
19 | It was a really cool feature, but I have a suspicion – and hard data — that almost nobody used it. Big is about minimalism, and niche features cut against that.
20 |
21 | ## No more Rubik font
22 |
23 | The San Francisco font included with macOS is really good. Web fonts just rub me the wrong way, and I’ve tried really hard to avoid them in new projects – they’re big binary dependencies that make everything more complex. You can really use web fonts in your presentations, and please do if you find one you love, but it wasn’t a good default.
--------------------------------------------------------------------------------
/big.css:
--------------------------------------------------------------------------------
1 | html {
2 | height: 100%;
3 | }
4 |
5 | body {
6 | font-family: -apple-system, BlinkMacSystemFont, avenir next, avenir, helvetica neue, helvetica, Ubuntu, roboto, noto, segoe ui, arial, sans-serif;
7 | font-weight: 700;
8 | margin: 0;
9 | padding: 0;
10 | }
11 |
12 | h1,
13 | h2,
14 | h3,
15 | p {
16 | margin: 0;
17 | }
18 |
19 | em {
20 | font-style: normal;
21 | }
22 |
23 | .nowrap {
24 | white-space: nowrap;
25 | }
26 |
27 | * {
28 | box-sizing: border-box;
29 | }
30 |
31 | div.slide-container {
32 | background-size: 100%;
33 | display: flex;
34 | align-items: center;
35 | justify-content: center;
36 | }
37 |
38 | div.slide {
39 | cursor: pointer;
40 | cursor: hand;
41 | }
42 |
43 | div.imageText {
44 | text-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
45 | }
46 |
47 | /* normally not good, but ok in context of full screen directional navigation */
48 | .talk-mode .slide:focus {
49 | outline: 0;
50 | }
51 |
52 | body.talk-mode {
53 | display: flex;
54 | align-items: center;
55 | justify-content: center;
56 | height: 100%;
57 | }
58 |
59 | body.print-mode {
60 | background: #fff;
61 | color: #000;
62 | font-weight: normal;
63 | padding: 0px;
64 | }
65 |
66 | body.print-mode div.sub-container {
67 | padding: 10px 20px;
68 | display: flex;
69 | flex-flow: row wrap;
70 | break-inside: avoid;
71 | }
72 |
73 | ul.notes-list {
74 | display: inline-block;
75 | float: left;
76 | vertical-align: top;
77 | }
78 |
79 | body.print-mode div.slide-container {
80 | border: 1px solid #000;
81 | }
82 |
83 | body.jump-mode {
84 | padding: 10px;
85 | }
86 |
87 | body.jump-mode div.sub-container {
88 | display: inline-block;
89 | vertical-align: top;
90 | padding: 2px;
91 | }
92 |
93 | body.jump-mode div.slide-container {
94 | border: 1px solid rgba(255, 255, 255, 0.2);
95 | cursor: pointer;
96 | }
97 |
98 | body.jump-mode div.slide-container:hover {
99 | border: 1px solid rgba(255, 255, 255, 0.8);
100 | }
101 |
102 | .layout {
103 | display: grid;
104 | }
105 |
106 | .layout div {
107 | display: flex;
108 | align-items: center;
109 | }
110 |
111 | .layout img {
112 | object-fit: contain;
113 | width: 100%;
114 | height: 100%;
115 | }
116 |
117 | div.slide > img:only-child,
118 | div.slide > canvas:only-child,
119 | div.slide > video:only-child {
120 | width: 100%;
121 | }
122 |
--------------------------------------------------------------------------------
/big.js:
--------------------------------------------------------------------------------
1 | let ASPECT_RATIO = window.BIG_ASPECT_RATIO === undefined ? 1.6 : window.BIG_ASPECT_RATIO;
2 |
3 | function parseHash() {
4 | return parseInt(window.location.hash.substring(1), 10);
5 | }
6 |
7 | function emptyNode(node) {
8 | while (node.hasChildNodes()) node.removeChild(node.lastChild);
9 | }
10 |
11 | function ce(type, className = "") {
12 | return Object.assign(document.createElement(type), { className });
13 | }
14 |
15 | addEventListener("load", () => {
16 | let slideDivs = Array.from(document.querySelectorAll("body > div"));
17 | let pc = document.body.appendChild(ce("div", "presentation-container"));
18 | slideDivs = slideDivs.map((slide, _i) => {
19 | slide.setAttribute("tabindex", 0);
20 | slide.classList.add("slide");
21 | let sc = pc.appendChild(ce("div", "slide-container"));
22 | sc.appendChild(slide);
23 | return Object.assign(sc, {
24 | _notes: Array.from(slide.querySelectorAll("notes"), noteElement => {
25 | noteElement.parentNode.removeChild(noteElement);
26 | return noteElement.innerHTML.trim();
27 | }),
28 | _i
29 | });
30 | });
31 | let timeoutInterval,
32 | { body } = document,
33 | {
34 | className: initialBodyClass,
35 | style: { cssText: initialBodyStyle }
36 | } = body,
37 | big = (window.big = {
38 | current: -1,
39 | mode: "talk",
40 | length: slideDivs.length,
41 | forward,
42 | reverse,
43 | go
44 | });
45 |
46 | function forward() {
47 | go(big.current + 1);
48 | }
49 |
50 | function reverse() {
51 | go(big.current - 1);
52 | }
53 |
54 | function go(n, force) {
55 | n = Math.max(0, Math.min(big.length - 1, n));
56 | if (!force && big.current === n) return;
57 | big.current = n;
58 | let sc = slideDivs[n],
59 | slideDiv = sc.firstChild;
60 | if (sc._notes.length) {
61 | console.group(n);
62 | for (let note of sc._notes) console.log("%c%s", "padding:5px;font-family:serif;font-size:18px;line-height:150%;", note);
63 | console.groupEnd();
64 | }
65 | for (let slide of slideDivs) slide.style.display = slide._i === n ? "" : "none";
66 | body.className = `talk-mode ${slideDiv.dataset.bodyClass || ""} ${initialBodyClass}`;
67 | body.style.cssText = `${initialBodyStyle} ${slideDiv.dataset.bodyStyle || ""}`;
68 | window.clearInterval(timeoutInterval);
69 | if (slideDiv.dataset.timeToNext) timeoutInterval = window.setTimeout(forward, parseFloat(slideDiv.dataset.timeToNext) * 1000);
70 | onResize();
71 | if (window.location.hash !== n) window.location.hash = n;
72 | document.title = slideDiv.textContent;
73 | }
74 |
75 | function resizeTo(sc, width, height) {
76 | let slideDiv = sc.firstChild,
77 | padding = Math.min(width * 0.04),
78 | fontSize = height;
79 | sc.style.width = `${width}px`;
80 | sc.style.height = `${height}px`;
81 | slideDiv.style.padding = `${padding}px`;
82 | if (getComputedStyle(slideDiv).display === "grid") slideDiv.style.height = `${height - padding * 2}px`;
83 | for (let step of [100, 50, 10, 2]) {
84 | for (; fontSize > 0; fontSize -= step) {
85 | slideDiv.style.fontSize = `${fontSize}px`;
86 | if (
87 | slideDiv.scrollWidth <= width &&
88 | slideDiv.offsetHeight <= height &&
89 | Array.from(slideDiv.querySelectorAll("div")).every(elem => elem.scrollWidth <= elem.clientWidth && elem.scrollHeight <= elem.clientHeight)
90 | ) {
91 | break;
92 | }
93 | }
94 | fontSize += step;
95 | }
96 | }
97 |
98 | function onPrint() {
99 | if (big.mode === "print") return;
100 | body.className = `print-mode ${initialBodyClass}`;
101 | body.style.cssText = initialBodyStyle;
102 | emptyNode(pc);
103 | for (let sc of slideDivs) {
104 | let subContainer = pc.appendChild(ce("div", "sub-container")),
105 | sbc = subContainer.appendChild(ce("div", sc.firstChild.dataset.bodyClass || ""));
106 | sbc.appendChild(sc);
107 | sbc.style.cssText = sc.dataset.bodyStyle || "";
108 | sc.style.display = "flex";
109 | resizeTo(sc, 512, 320);
110 | if (sc._notes.length) continue;
111 | let notesUl = subContainer.appendChild(ce("ul", "notes-list"));
112 | for (let note of sc._notes) {
113 | let li = notesUl.appendChild(ce("li"));
114 | li.innerText = note;
115 | }
116 | }
117 | big.mode = "print";
118 | }
119 |
120 | function onTalk(i) {
121 | if (big.mode === "talk") return;
122 | big.mode = "talk";
123 | body.className = `talk-mode ${initialBodyClass}`;
124 | emptyNode(pc);
125 | for (let sc of slideDivs) pc.appendChild(sc);
126 | go(i, true);
127 | }
128 |
129 | function onJump() {
130 | if (big.mode === "jump") return;
131 | big.mode = "jump";
132 | body.className = "jump-mode " + initialBodyClass;
133 | body.style.cssText = initialBodyStyle;
134 | emptyNode(pc);
135 | slideDivs.forEach(sc => {
136 | let subContainer = pc.appendChild(ce("div", "sub-container"));
137 | subContainer.addEventListener("keypress", e => {
138 | if (e.key !== "Enter") return;
139 | subContainer.removeEventListener("click", onClickSlide);
140 | e.stopPropagation();
141 | e.preventDefault();
142 | onTalk(sc._i);
143 | });
144 | let sbc = subContainer.appendChild(ce("div", sc.firstChild.dataset.bodyClass || ""));
145 | sbc.appendChild(sc);
146 | sc.style.display = "flex";
147 | sbc.style.cssText = sc.dataset.bodyStyle || "";
148 | resizeTo(sc, 192, 120);
149 | function onClickSlide(e) {
150 | subContainer.removeEventListener("click", onClickSlide);
151 | e.stopPropagation();
152 | e.preventDefault();
153 | onTalk(sc._i);
154 | }
155 | subContainer.addEventListener("click", onClickSlide);
156 | });
157 | }
158 |
159 | function onClick(e) {
160 | if (big.mode !== "talk") return;
161 | if (e.target.tagName !== "A") go((big.current + 1) % big.length);
162 | }
163 |
164 | function onKeyDown(e) {
165 | if (big.mode === "talk") {
166 | switch (e.key) {
167 | case "ArrowLeft":
168 | case "ArrowUp":
169 | case "PageUp":
170 | return reverse();
171 | case "ArrowRight":
172 | case "ArrowDown":
173 | case "PageDown":
174 | return forward();
175 | }
176 | }
177 | let m = { p: onPrint, t: onTalk, j: onJump }[e.key];
178 | if (m) m(big.current);
179 | }
180 |
181 | function onResize() {
182 | if (big.mode !== "talk") return;
183 | let { clientWidth: width, clientHeight: height } = document.documentElement;
184 | if (ASPECT_RATIO !== false) {
185 | if (width / height > ASPECT_RATIO) width = Math.ceil(height * ASPECT_RATIO);
186 | else height = Math.ceil(width / ASPECT_RATIO);
187 | }
188 | resizeTo(slideDivs[big.current], width, height);
189 | }
190 |
191 | window.matchMedia("print").addListener(onPrint);
192 | document.addEventListener("click", onClick);
193 | document.addEventListener("keydown", onKeyDown);
194 | document.addEventListener("touchstart", e => {
195 | if (big.mode !== "talk") return;
196 | let { pageX: startingPageX } = e.changedTouches[0];
197 | document.addEventListener(
198 | "touchend",
199 | e2 => {
200 | let distanceTraveled = e2.changedTouches[0].pageX - startingPageX;
201 | // Don't navigate if the person didn't swipe by fewer than 4 pixels
202 | if (Math.abs(distanceTraveled) < 4) return;
203 | if (distanceTraveled < 0) forward();
204 | else reverse();
205 | },
206 | { once: true }
207 | );
208 | });
209 | addEventListener("hashchange", () => {
210 | if (big.mode === "talk") go(parseHash());
211 | });
212 | addEventListener("resize", onResize);
213 | console.log("This is a big presentation. You can: \n\n* press j to jump to a slide\n" + "* press p to see the print view\n* press t to go back to the talk view");
214 | body.className = `talk-mode ${initialBodyClass}`;
215 | go(parseHash() || big.current);
216 | });
217 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Big
7 |
8 |
9 |
10 |
11 |
12 | Your presentation goes here
13 | Speakers notes go here.
14 |