Hello, my name is Dmitry Karlovsky and I sometimes speak at conferences, meetings, and also recently I myself enter the team of organizers of one of them - PiterJS . Recently, we had an anniversary - 40 meetings held. But instead of relaxing and receiving congratulations, we got tired and ourselves prepared reports from the organizers .
But this is not enough for us, so we decided to celebrate a big anniversary by organizing a conference on the banks of the Neva PiterJSConf , which will be held this Saturday, September 7, 2019. Hurry to sign up, while there are still vacant seats, because participation in it will be completely free for you.
We do all this not for money, but for the great idea that knowledge should be free. Therefore, everything we do is available in Open Source . We are happy to share our best practices, knowledge and experience with others. And we urge the cooperation of organizers from other cities to create an open platform for organizing technological meetings on a regular basis. Join us as an organizer , partner , speaker , volunteer , patron or just a listener.
In the meantime, I offer you a story about the $hyoo_slides
presentation web application that I use for all my presentations. Video recording is available on YouTube , but not everything is there. You can read this story as an article , or open it in the interface of the application itself . Next I will tell you how much it can do and how it works.
Here is the interface that the audience sees during the performance. There is nothing superfluous in it.
The name and number of the slide are displayed at the top. Listeners may have questions. And quickly recording this number, they will be able to name it after the speech and thereby save the audience from tedious waiting, when the speaker will find a slide on which the question is being asked.
Below you can pay attention to the progress bar, showing late listeners how much they missed. And to everyone else - how much is left to the end. It is calculated not by the number of slides, but by the volume of the narrated speech.
The basic idea is to let the speaker concentrate on the content and not worry about the design. The report does not need any special beauties and spectacular animations at all. Otherwise, the design will draw attention to itself. And the content runs the risk of flying past ears.
But the design should nevertheless be neat so as not to spoil the impression of the report. Therefore, the application design is simple, not catchy, and, most importantly, consistent with the recommendations of program committees.
The speaker's interface is divided into two parts.
On the left is what listeners see. And on the right are the speaker’s notes. They will help you remember a lost thought, without turning away from the audience and without straining them for a long ... um ... this is ... a pause.
Therefore, in our case, the content is written as an article in MarkDown format and laid out on some GitHub Pages. And the web application takes care of the rest.
# #
After the speech, the text transcript of the report is often laid out in the form of an article on some Habré . They can do it for a month, two, half a year. The task is an ungrateful translation of speech into text. But, due to the fact that the source of the slides is already in markdown format and contains the speaker’s comments, they can be immediately published in this form.
Plain text is displayed only to the presenter. And all sorts of pictures, lists, tables, quotes, etc. are visible to everyone.
- ** - ** ** - ~~~~ - ``````
Of course, various inline formatting tools are available.
Blocks of source code, of course, are also supported, and are painted in all colors of the rainbow. Just as you like.
```javascript const hello = ()=> <body> Hello, "world"! </body> ```
const hello = ()=> <body> Hello, "world"! </body>
Comparison of various pieces will help you tables. For example, let's see why $hyoo_slides
better than its closest competitors - shwr.me and google slides
| | shwr.me | google slides | slides.hyoo.ru | |--------------------------|---------|---------------|----------------| | MarkDown | - | - | + | | | - | + | + | | | - | - | + | | | - | + | + |
shwr.me | google slides | slides.hyoo.ru | |
---|---|---|---|
Source in MarkDown | - | - | + |
Dual panel mode | - | + | + |
Auto slide switch | - | - | + |
Offline | - | + | + |
As you can see, $hyoo_slides
beats competitors on all fronts. Except for those that are not included in the table, of course.
Well lano, tables are boring.
Hold the cat.
![](https://github.com/nin-jin/slides/raw/master/slides/cat.gif)
Notice that the background of the slides is slightly gray. Therefore, it is better to prepare images not on a white background, but with transparency so that there is no unpleasant white rectangle around the pictures. This is done so that the white areas look in contrast, and do not merge with the background.
You can post videos, web pages and any other external content using the same MarkDown syntax as for inserting pictures.
![ ](https://www.youtube.com/embed/exfBX2pb7AQ?autoplay=1)
For example, I inserted a video illustrating that modern interfaces are so simple and convenient that even a monkey can handle them.
You can switch slides with arrows on the keyboard. But in order not to be tied to a laptop, but to walk freely around the stage, a radio extension cord is useful for you. He is a clicker.
But what if the clicker is broken?
You probably think that in the hall here somewhere I have a mishandled Cossack who switches slides instead of me? However, it is not.
Please repeat. A voice from above repeats the last phrase.
Yes, slides can completely control the voice, leaving your hands free for gestures. It uses standard web api for voice recognition and synthesis.
But repeating these code phrases ten times in a row is boring, so $hyoo_slides
can analyze the speaker’s notes and, when you say the last word, switch the slide automatically.
Okay, complicating the situation. Someone after listening to your speech, decided to see your slides from the tablet while riding home on the subway.
There is no keyboard. The trains are noisy. Here, ordinary finger gestures come to the rescue.
But then he drives into the tunnel and his connection disappears.
It doesn’t matter, we have Web2.0 HTML5 Progressive Web Application with full functionality even when there is no Internet.
But here the organizers come up to you and say: "We want a PDF."
Which pdf? We have here a multimedia interactive Web2.0 HTML5 Progressive Web Application. However, they explain to you that the application is today, and tomorrow it is no longer there. And if there is, he wants money. And if you don’t want to, then the slides there can already be changed beyond recognition. And PDF is quietly in the archive with exactly the content that corresponds to the video recorded during the performance.
Well, it doesn’t matter, press Ctrl+P
, select "Print to PDF" and get what you need. This is done simply - the onbeforeprint
event is onbeforeprint
and, when it occurs, instead of just the current slide, all slides are rendered at all. And onafterprint
, all but the current one, the slides are deleted.
On this, the feature lists are now over.
Trying $hyoo_slides
really easy. You will need readme.md
with your content and pictures. Also nearby you will need to paste index.html
, which redirects to the web application and opens your presentation in it. And also offline.js for offline support.
readme.md
index.html
offline.js
Keep in mind that this index.html
will give the application any files that are accessible from the domain where you put the whole thing. GitHub Pages is a very convenient and safe option. I use it myself.
If you liked this application, you can take a look at other interesting applications implemented on the $ mol framework. They are so lightweight that even a few dozen are not afraid to load them all at once on one slide.
But about them somehow later ...
You can learn more about the framework at a separate presentation. You can dig deeper in a presentation on the PPR. And you can lift the curtain of the future in a presentation on the quantization of computations.
They all use $ hyoo_slides to display. I hope soon there will be more such presentations.
And now, let's open the hood a bit and see how the application is arranged, and how to make our own in just one evening.
$hyoo_slides_page $mol_view sub / <= Listener <= Speaker
export class $hyoo_slides_page extends $mol_view { sub() { return [ this.Listener() , this.Speaker() , ] } }
Here is a top-level description of a single screen in view.tree and equivalent TypeScript code. Here we declare the component $hyoo_slides_page
, which extends the base component of $mol_view
. This component has a sub
property. Everything that returns this property will be rendered inside the component. Therefore, we redefine it, passing as an value an array of two elements: Listener
- a component for outputting a slide to listeners and Speaker
- a component of an additional speaker panel.
In addition to the description of the structure, we can also apply program logic that allows any properties to be calculated dynamically.
sub() { const role = this.role() return [ this.Listener() , ... ( role === 'speaker' ) ? [ this.Speaker() ] : [] , ] }
Here the logic is simple: we always display slides for listeners, but the speaker panel is only shown if the current role is speaker
. If the role changes, then the layout of the application will also change due to the magic of object reactive programming.
We will take the role from the address parameter, through the special reactive API $mol_state_arg
.
role() : 'speaker' | 'listener' { return $mol_state_arg.value( 'role' ) || 'speaker' }
For whatever reason the address has changed - the role will be extracted from it automatically, and passed through to this method.
Let's describe the listener interface.
Listener $mol_page title <= title tools / <= Slide_switcher body / <= Listener_content <= Progress
It uses the standard component $mol_page
which draws a typical page with a header and a body. There is an area in the header where the page name is displayed. Through the title
property, you can specify what to output there. Which we did by associating its title
property with our property of the same name. Now, changing our property, we have full control over what will be displayed on the page as a title.
On the right in the header, there is an output area for additional tools - tools
. We Slides_switcher
- a component for displaying the slide number and switching between adjacent slides.
And finally, as the page body
in body
we display the contents of the slide and the progress bar.
How to implement Slide_switcher
? Just use the standard component $mol_paginator
.
Slide_switcher $mol_paginator value?val <=> slide?val
All he has is a mutable value
property, which we bilaterally associate with our property containing the number of the current slide. No imports, callbacks, events and other trash. These two lines are all that is necessary for a working page switch to appear on your page.
To display the contents of the slide, we again use the standard component $mol_text
.
Listener_content $mol_text uri_base <= uri_base text <= listener_content
It takes markdown
and renders it. Since the links in this text will be relative to the source file, and not to our application, we pass the link to the uri_base property, regarding which all paths will resolve.
As you may have already guessed, there is also a standard component for displaying progress - $mol_portion
.
Progress $mol_portion portion <= progress
portion: [ 0 .. 1 ]
We feed him a number from 0 to 1 and get an indicator filled for this share.
We have something more interesting in the speaker’s interface. The tools displayed in the header are not attached to the current page in any way - they are common to the entire application. Therefore, instead of hardcoding them here, we will only place the speaker_tools
slot through which we will transfer the list of components from the outside.
Speaker $mol_page head <= speaker_tools /$mol_view body / <= Speaker_content
Now go up a level and create an application component $hyoo_slides
that uses the page component.
$hyoo_slides $mol_view Page!index $hyoo_slides_page - ... plugins / <= Nav <= Touch <= Speech_next - ...
Any $mol_view
component has a plugins
property through which additional logic can be connected to it. Plugin plugins live on the same DOM node as the component itself. The component initiates them during its rendering. And when about ceases to be rendered - plugins are destroyed automatically.
We also announced the Page
property, which for each index returns a separate instance of the $hyoo_slides_page
component we developed earlier.
Page!index $hyoo_slides_page role <= role slide?val <=> page_slide!index?val speaker_tools / <= Speech_toggle <= Speech_text <= Open_listener
We pass the role
property to the subcomponent as is. The slide
property of the page component is connected by two-way communication with the page_slide
property of the application. Please note that page_slide
accepts not only the optional new value, but also the page index. This allows you to return a number for each page. Finally, in the speaker_tools
slot we announced earlier, we put three components to help manage the slides.
We implement Speech_toggle
through the standard component $mol_check_icon
, which draws an icon. When you click on it, it toggles the checked
flag. And the current state is displayed by changing the color of the icon.
Speech_toggle $mol_check_icon Icon <= Speech_toggle_icon $mol_icon_microphone checked?flag <=> speech_enabled?flag
We took the icon from the $mol_icon
, where out of 4000 icons made in the ascetic material design style, it is easy to find the right one.
Everything is simple here. This button will be the link $mol_link
. She can set the uri
property with an address, or she can do something more cunning and just patch the current address, replacing some parameters through arg
.
Listener_open $mol_link target \_blank arg * role \listener slide null sub / <= Listener_open_icon $mol_icon_external
Here we erased the slide number from the address so that the slave window would take it from the local storage, and not from the address. This will ensure that the windows synchronize with each other. And also indicated that the role should be a "listener". Inside the link, we put an icon instead of text.
Plugins can significantly expand the capabilities of the component. We will use them to the maximum.
plugins / <= Nav <= Touch <= Speech_next <= Speech_prev <= Speech_start <= Speech_end - ...
All the plugins used by us can be divided into 3 categories: keyboard navigation, gesture control and voice control.
Through $mol_nav
it is easy to implement keyboard navigation both vertically and horizontally. All that is needed is to provide the plug-in with a list of keys by which it will switch, and two-way communication to the current value.
Nav $mol_nav keys_y <= slide_keys keys_x <= slide_keys current_y?val <=> slide?val current_x?val <=> slide?val
slide_keys: [ 0 , 1 , 2 , 3 , ... , 30 ] ^ slide
For finger tracking, there is a $mol_touch
. With it, you can zoom, pan and swipe. It is the last opportunity that interests us now.
Touch $mol_touch swipe_to_left?event <=> go_next?event swipe_to_right?event <=> go_prev?event
go_next( event? : Event ) { this.slide( this.slide() + 1 ) }
There are two types of swipe. For example, swipe left or right from any part of the screen and swipe due to the right or left edge of the screen towards the center. In the presented code, we hung our handlers on the first type of swipe.
For voice control, use the $mol_speech
. It is necessary to create an instance of the plugin for each version of the action.
Sing $mol_speech event_catch?val <=> sing?val patterns / \sing( \S+?)* \( \S+?)*
The plugin accepts an action handler and a set of patterns, upon detection of which, an event will be triggered. You can use capturing brackets in the patterns to get the words corresponding to their contents in the handler.
By default, $mol_speech
requires courteous handling. For example, you should say not “sing,” but “sing, please.” You can override the suffix
property to change or remove this codeword altogether.
Speech_next_auto $mol_speech event_catch?val <=> go_next?val suffix \ patterns <= speech_next_auto_patterns
For example, to implement automatic slide switching, we do not need magic words. But we will generate a set of patterns dynamically, based on the analysis of the contents of the speaker’s text.
Having an application component, you can instantiate it manually like any ordinary class. But we will use automatic launch through the special attribute mol_view_root
.
<body mol_view_root="$hyoo_slides"> <script src="web.js" charset="utf-8"></script> </body>
The attribute name is the name of the component. Rendering in this way, of course, can be absolutely any component.
To add offline support, just include the mol/offline/install
module in the bundle.
include \/mol/offline/install
It automatically raises a ServiceWorker, which caches all requests. And if the network is unavailable, it returns data from the cache. This is not the coolest implementation, but for simple cases when you do not want to bother, it will do.
I said earlier that during printing you need to render all pages, but there’s no need to manually monitor onbeforeprint
and onafterprint
, because we have full-reactive programming, so we will use the reactive state $mol_print
, which gives us a reactive flag, which we can tie up rendering.
sub() { if( !this.$.$mol_print.active() ) { return [ this.Page( this.slide() ) ] } return $mol_range2( index => this.Page( index ) , ()=> this.slide_keys().length , ) }
Here we return only one page if the active
flag is not raised. Otherwise, we return a lazy array that calculates its length and elements according to the given formulas.
As a result, we got a modern web application with a bunch of functionality and a weight of only 35kb. Add manifest and there will be a full-fledged Progressive Web Application. Of course, many details were not considered. You can see them in the code on the github. For all questions, write telegrams in chat.
These slides are in the app: slides.hyoo.ru
Application sources: hyoo-ru / slides.hyoo.ru
Presentation examples: nin-jin / slides
Telegram chat: @mam_mol
I will be glad if you try to make your presentation with $hyoo_slides
. And I will be very happy if you help make it even better than it is now. Thanks for your attention!