# The Universe of Discourse

Mon, 02 Nov 2020

A few months ago I wrote an article about a strategy I had tried when giving a talk via videochat. Typically:

The slides are presented by displaying them on the speaker's screen, and then sharing the screen image to the audience.

I thought I had done it a better way:

I published the slides on my website ahead of time, and sent the link to the attendees. They had the option to follow along on the web site, or to download a copy and follow along in their own local copy.

1. Each audience person can adjust the monitor size, font size, colors to suit their own viewing preferences.

2. The audience can see the speaker. Instead of using my outgoing video feed to share the slides, I could share my face as I spoke.

3. With the slides under their control, audience members can go back to refer to earlier material, or skip ahead if they want.

When I brought this up with my co-workers, some of them had a very good objection:

I am too lazy to keep clicking through slides as the talk progresses. I just want to sit back and have it do all the work.

Fair enough! I have done this.

If you package your slides with page-turner, one instance becomes the “leader” and the rest are “followers”. Whenever the leader moves from one slide to the next, a very simple backend server is notified. The followers periodically contact the server to find out what slide they are supposed to be showing, and update themselves accordingly. The person watching the show can sit back and let it do all the work.

But! If an audience member wants to skip ahead, or go back, that works too. They can use the arrow keys on their keyboard. Their follower instance will stop synchronizing with the leader's slide. Instead, it will display a box in the corner of the page, next to the current slide's page number, that says what slide the leader is looking at. The number in this box updates dynamically, so the audience person always knows how far ahead or behind they are.

 Synchronized Unsynchronized

At left, the leader is displaying slide 3, and the follower is there also. When the leader moves on to slide 4, the follower instance will switch automatically.

At right, the follower is still looking at slide 3, but is detached from the leader, who has moved on to slide 007, as you can see in the gray box.

When the audience member has finished their excursion, they can click the gray box and their own instance will immediately resynchronize with the leader and follow along until the next time they want to depart.

I used this to give a talk to the Charlotte Perl Mongers last week and it worked. Responses were generally positive even though the UI is a little bit rough-looking.

### Technical details

The back end is a tiny server, written in Python 3 with Flask. The server is really tiny, only about 60 lines of code. It has only two endpoints: for getting the leader's current page, and for setting it. Setting requires a password.

    @app.route('/get-page')
def get_page():
return { "page": app.server.get_pageName() }

@app.route('/set-page', methods=['POST'])
def set_page():
…
page = request.data["page"]
try:

return { "success": True }


The front end runs in the browser. The user downloads the front-end script, pageturner.js, from the same place they are getting the slides. Each slide contains, in its head element:

    <LINK REL='next'     HREF='slide003.html' TYPE='text/html; charset=utf-8'>

<script language="javascript" src="pageturner.js" >
</script>


The link elements tell page-turner where to go when someone uses the arrow keys. (This could, of course, be a simple counter, if your slides are simply numbered, but my slide decks often have slide002a.html and the like.) Most of page-turner's code is in pageturner.js, which is a couple hundred lines of JavaScript.

On page switching, a tiny amount of information is stored in the browser window's sessionStorage object. This is so that after the new page is loaded, the program can remember whether it is supposed to be synchronized.

If you want page-turner to display the leader's slide number when the follower is desynchronized, as in the example above, you include an element with class phantom_number. The phantom_click handler resynchronizes the follower:

    <b onclick="phantom_click()"  class="phantom_number"></b>


The password for the set-page endpoint is embedded in the pageturner.js file. Normally, this is null, which means that the instance is a follower. If the password is null, page-turner won't try to update set-page. If you want to be the leader, you change

   "password": null,


to

   "password": "swordfish",


or whatever.

Many improvements are certainly possible. It could definitely look a lot better, but I leave that to someone who has interest and aptitude in design.

I know of one serious bug: at present the server doesn't handle SSL, so must be run at an http://… address; if the slides reside at an https://… location, the browser will refuse to make the AJAX requests. This shouldn't be hard to fix.