art with code

2013-09-20

The latest motivational flicks

Here are two documentaries that will change your perspective on life.

The first one is Touching the Void. It recounts the experiences of two British mountain climbers trying to climb a previously unclimbed mountain in the Peruvian Andes. Perseverance is the word.


The second movie is Jiro Dreams of Sushi. It's a documentary about a top-rate sushi chef. His life, seventy years of trying to top yourself every single day, trying to improve your craft.


Ars longa, vita brevis, eh?

2013-09-16

Presentation books, videos and articles

Here's a small list of presentation resources that I'm collecting. Now to go through the Kindle archive to add in some more good stuff!

2013-09-15

Message weekly - Blog, Feedback forums, HTML Export, Complexity warnings

Welcome to the second weekly update on Message - the super-fast presentation app. This week brings news of yet more successful presentations done using Message and a whole lot of new features. Let's get started with discussing the new Message blog.

Blog


Message now has it's own blog up at https://message.fhtr.net/blog. The Message blog will be introducing new features, giving you presentation tips, and acting as a playground for Message's publishing features. No worries though, I'll keep doing these wrap-up posts to keep you updated.

The Message blog is built on top of Message, so it's strictly speaking a presentation. I like it as a demonstration of the power of Message's theming system. In addition, blog-style publishing requires a few extra features that will make publishing presentations nicer as well. For example, to do a blog well you need to track page views, have draft-publish workflow, load data dynamically, have nice post URLs, have a TOC, have comments and likes — most of which would improve the presentations as well. So hey, clear and motivated goals.

Fullscreen mode


If you look at the blog screenshot closely, you may notice a "Fullscreen"-button in the bottom right corner of the screen. Yes, you can now go fullscreen with your presentations.

The fullscreen mode hides the "Edit"-button as well so that you have a screen full of presentation and can run your presos straight from the editor preview. To exit the fullscreen mode, hit ESC and you'll be back to the editor in no time.

Feedback forums


I set up an UserVoice forum for Message to have a place to collect feature requests and other issues from y'all. Currently 6 issues posted, 5.5 resolved. And the remaining half issue would be PDF export of some sort. Speaking of which, @BlurSpline wrote this little snippet to create PDFs from Message presos.

If you have any ideas or find bugs on the Message site, feel free to head over to the feedback forum and create a new issue. Or ping me on Twitter: @ilmarihei.

HTML export


You can now export your presentations as HTML bundles. The bundle is a single HTML file with your stylesheets, custom scripts and images inlined into the document. So even if you don't have Internet available, you should be able to do your presentation from the bundle file.

The Export as HTML feature is still experimental, so let me know if you run into any problems. I'll keep tinkering on it (and the whole offline story) this week.

Private share links and shorter share links


As you can see in the screenshot above, the share pane now has a private share link. If you don't want to publish a preso for all the world to see, you can send the private share link instead.

In other news, I changed the public Message share links from "viewmessage.fhtr.net?page=view&id=$ID" to "v.fhtr.net/$ID". Now they look a bit nicer. And 23 characters shorter.

Complexity warnings


Ever seen a wall of text? Yes, that slide with sixteen bullet points and a five-line quote from a technical textbook. They are real, sad to say. Worst of all, they destroy presentations.

A wall of text does active battle with whatever you're saying. People can only deal with one linguistic task at a time. You can't listen to speech while you're reading and vice versa. Heck, even listening to music makes you worse at reading.

Your presentation slides should have very few words on them. Your slides are the headlines and illustrations. What you say is the article body.

Easier said than done. When you want to explain your thinking, it's so easy to add a few extra words on the slide. And perhaps a few bullet points. Maybe an inspiring quote or two.

It's too easy to make slides that make your audience stop listening to you. So, we took a swing at solving the problem.

Message now has slide complexity warnings. When your slide is getting a bit too verbose, you get a yellow "Complex Slide"-warning. It's a sign that you should pause for a few seconds when you show that slide. Maybe take a sip of water. Because your audience is going to be too busy reading the slide to listen to you.

If you keep on writing, the warning will turn into a red "Overcomplex Slide"-warning. This is the kind of slide that will likely make your presentation worse. Your audience is going to stop listening to you for the duration of this slide. Try to break overcomplex slides into three slides.

Slide complexity warnings are turned on on all new Message presentations. They need a snippet of code in the slide parser, so old presos don't have them by default. You can add the warnings to an old preso by loading a new preso as a template for the old one.

New version history names


The version history dropdown has somewhat cryptic names now. Gone are the undescriptive names like "Version 203", replaced with something like "→ 203 | T-3m 9/15/2013 15:03:20 PM | -2+39". Let me unravel that for you. The arrow points to the version at page load time. The T-3m means "this change was done 3 minutes ago" and the timestamp gives you a more exact time. The last part tells you how many characters were deleted and how many added, so that you have an idea of the size of the change.

Suppose you wanted to go to the version from yesterday, before you decided to rewrite a large part of your presentation. You'd open the dropdown and scroll it up to yesterday's edits, find one with a large number of deleted character and pick the version before that. Zing!

Paywalls


Last but not least, I'm slowly trying to move this project to the "paying my bills"-phase. And this will require asking you, dear reader, to pay for the value you're getting out of Message. I was thinking of going with a one-off payment instead of monthly subscriptions (but don't hold me to that, plans change.) Chew on the image on the right for a minute. Does it make you want to whip out your credit card or no?

I also have a mock up ad below there. Who knows if that price point is too low (for consumers) or too high (for corporates). I guess we'll find out.

That's all this week, you can see all these amazing features in action on Message. It's still in beta, so sign-up is free!

2013-09-03

Latest on Message

The last week's been busy on the Message front, here's a quick recap:


Yes, Message has code highlighting for your slides. Start a line with > and type along. I might replace that with four spaces to go with Markdown-style slides. Or heck, do a full Markdown parser for the slides and share it as a template.



Your presentations are now displayed on a nice responsive grid with big live previews of the slides. You can flip through your presos right there without necessarily having to open the editor. Magic in action, enabled by a ground-breaking technology platform.


Speaking of ground-breaking, your slides now have a full version history. Accidentally deleted a couple slides while thumb-typing? No problem, go to the version dropdown and pick a previous version. Just think of the amount of lost work you'll save with this single dropdown. We're giving all those hours back to you. You're welcome.

To protect your work even better, Message now prompts you if have unsaved changes and you try to leave the page. It's like having a friend watch out for you and catch you when you're about to have an accident.


Last but definitely not least, you can now use other presentations as templates. Made truly beautiful slide transitions for your previous preso? Now you can load them straight into your other presos. No more arduous copy-pasting of the style definitions. And best of all, you can publish your template for others to use.

To make your presos look better from word one, I changed the default theme from the old minimalistic black-on-white one to a more advanced one. It's the same theme used in the "How to use Message"-presentation. Yes, you get to enjoy the full power of Message's theming capabilities without any extra work.

In addition to the features highlighted above, the last week's new features include a list of the latest public presentations, custom descriptions for your presentations when sharing them on social networks, and Message is now using the ACE code editor for editing your slides and themes.

And hey, I can't wait to get cracking on some new themes, it's been far too long that I've been head-down in coding and market research. Creative output!


See Message at message.fhtr.net and sign up for free during the beta phase.

2013-08-25

Message

Hey peeps, I made a webapp for making presentations quickly. It's kinda rough and geeky but give it a spin.

https://message.fhtr.net




Feature highlights

  • super fast to write preso slides 
  • embed images, video, audio and websites 
  • timing marks to keep your script straight 
  • practice count notation to help you hone your delivery 
  • your edits are synced between devices so that you can use your phone to work on your preso in the train, then whip out your laptop at work and continue on it 
  • full themability with Stylus 
  • heck, you can even hack the slide parser JS to customize everything 
I also use it as a mobile notepad, which is kinda nice... Maybe I should make a separate product for that.

2013-08-23

Adventures in OT, part 2

I've got a couple new tidbits to add to my previous post about implementing an operational transformation library. Operational transformations are about recording your edits and streaming them to the other collaborators. The concept is simple and the implementation isn't super-complicated, but it can be a bit tricky.

Anyway, I was hooking up the transformation library to inputs and textareas. Which, well, I guess you should just use a diff algorithm, it's probably less of a browser-compatibility hassle. I ended up doing it the hard way.

I'm monitoring events on the input element and keeping track of the cursor position using selectionStart and selectionEnd. When the contents of the element change, I figure out what kind of change it was and record a cursor movement followed by insert & delete events.

If the selection is empty, the change is an insert or a delete. If the input value is longer than the previous value, the change is an insert. If the value is shorter, the change is a delete. This logic works fine until you run into iOS autocorrect.

With autocorrect, the selection is empty but the cursor jumps multiple characters forwards. So I had to add a hack to the tune of "if the cursor jumps forward, set the selection length to the distance between last cursor position and current cursor position". Which works for simple autocorrect cases, but not for the autocorrect popup menu suggest action. Anyway, it sort of works. And this is why you should use a diff algorithm to record your edits.

Here's the code I've got at the moment:

// Setup event recording for the input element.
// Record the edits to the named field inside the changelist.
// Uses username as the name for the cursor.
var recordEdits = function(input, name, changelist, username) {
  input._lastValue = input.value;
  input._cursor = {
    pos: input.selectionStart,
    length: input.selectionEnd-input.selectionStart
  }; 

  getEventNames(input).forEach(function(n) {
    input.addEventListener(n, recordEdit(name, changelist, username), false);
  });
};

// Get the list of event names for the element.
var getEventNames = function(elem) {
  var a = Object.getOwnPropertyNames(elem).join(" ").match(/\bon\S+/g).join(" ").replace(/\bon/g, '').split(" ");
  // Take out touch events as Mobile Safari
  // doesn't like touch listeners on textareas inside iframes.
  a = a.filter(function(s) { return !(/^(touch|gesture)/).test(s); });
  return a;
};

// Makes an event listener to record edits.
var recordEdit = function(name, changelist, username) {
  return function(ev) {
    // Update cursor position.
    var cursor = {
      pos: this.selectionStart,
      length: this.selectionEnd-this.selectionStart
    };

    // The value has changed. Let's record the change.
    if (this.value !== this._lastValue) {

      // Hack to handle autocorrect edits.
      if (cursor.pos - this._cursor.pos > 1 && this._cursor.length === 0) {
        this._cursor.length = cursor.pos - this._cursor.pos;
      }

      // Handle selection replacements.
      // Triggers when you've got something selected and you
      // either type something or paste something.
      if (this._cursor.length > 0) {
        ChangeList.addChange(changelist, {edit: name, value: {cursor: {id: username, pos: this._cursor.pos}}});
        ChangeList.addChange(changelist, {edit: name, value: {del: this._cursor.length}});
      }

      // How much the length of the value has changed.
      // A positive value indicates that text insertion.
      // A negative value means that you've deleted text.
      var d = (this.value.length-this._lastValue.length+this._cursor.length);

      if (d > 0) {
        // Create a text insertion change.
        // Note that we insert the text from the 
        // previous cursor position. The current cursor position
        // is after the inserted text.
        ChangeList.addChange(changelist, {edit: name, value: {cursor: {id: username, pos: this._cursor.pos}}});
        ChangeList.addChange(changelist, {edit: name, value: {add: this.value.substr(this._cursor.pos, d)}});
      } else if (d < 0) {
        // Create a text deletion change.
        ChangeList.addChange(changelist, {edit: name, value: {cursor: {id: username, pos: cursor.pos}}});
        ChangeList.addChange(changelist, {edit: name, value: {del: -d}});
      }
      this._lastValue = this.value;
    }
    this._cursor = cursor;
  };
};

Ok, so it's a bit hacky. And it probably doesn't work all that well on IE. Perusing the code for ShareJS, it had a comment about IE converting \n linebreaks into \r\n linebreaks. Which would screw up cursor positions compared to other browsers.

Enough about hooking up input events. The other thing I got kinda working are writes based on a log table. Usually you'd need to have a document lock to do writes reliably. Because you need to transform new events based on events that arrived from other clients. So you can't insert new changes directly into the changelist, but need to read in tail = changelist[newChanges.lastSeenVersion..-1], then rebase the newChanges on top of the tail and push the transformed changes to the changelist. Which means that you want to lock changelist during tail read, transform and transform push. Otherwise you might get other changes in before the push and your transform goes FUBAR.

But hey, if you have an atomic push, you could do this: record the lastSeenVersion for the newChanges and push it into the changelist without transformation. Then change the changelist execution function so that it transforms the changes that have lastSeenVersion set. That way the result stays the same compared to pre-transforming the changes, though it'll cost you some performance. Not to worry though, you transform the newChanges and atomically replace the non-transformed version with the transformed version. Zing! Now the changelist results remain consistent even if other writers push more junk on top of the changelist while you're transforming.


2013-08-19

Algebra with compass and straightedge

Thought: could you use a compass and a straightedge to do basic math?

Let's see. First we need to define a couple of things. Like zero. Let's use a zero-length point as the zero. Draw a long straight line, put a mark on it somewhere in the middle. There's your zero and line of numbers.

How to represent numbers? Line segments, right? Take the ruler and draw a few short lines. You can move the short lines to your line of numbers using the compass. Measure line with the compass, move the compass to the line, make a mark with the other end, there you go. Our numbers are lines that are on the number line.

With that, we can add positive numbers. Suppose you have three lines: A, B and C. To add them together, you'd first copy A to the number line, then B starting at one end of A and C at one end of B. The resulting long line is the three lines added together.

To get a proper group going, we're going to need a way to negate lines. So, let's add a direction to the lines. Put a short line A on the number line with one end at zero. Jot a small arrowhead at the other end. Now you can negate A by flipping it around so that the arrow points in the opposite direction. A + -A would go from zero to A, then all the way back to zero. To draw A and -A, first move A to start at zero, then rotate the compass 180 degrees and make a mark on the other side of zero. That's -A.

To add these arrows together, we need to add a rule. You need to attach the non-arrow start of a line to the arrowhead of the previous line. And the result of addition can be represented as a single arrow, going from the start of the first line to be added with the arrowhead at the arrowhead of the last line.

Ok, we have numbers and their negations. We can add lines and subtract lines. And they seem to obey associativity A + (B + C) = (A + B) + C and commutativity A + B = B + A. The addition operator requires us to define A as any arrow pointing to the same direction as A and that has the same length as A. Other group axioms, A + 0 = A seems to be ok, ditto for A + -A = 0.

Right, I think we have an additive group. How about multiplication?

You can multiply two of these vectors together by doing the addition but then rotating the second arrow by 90 degrees. Then add the first vector after the second, rotate it, and repeat once more for the second vector. Now you have a rectangle. The area of the rectangle is the result of the multiplication.

Now wait a minute, how do you convert that into a vector on the number line? It's an area, a completely new dimension, totally different unit from the number line segments. Right. Well, maybe this is not the kind of multiplication we really want. Let's try to find something else.

Ok, first, define one. It's some vector. Probably pretty short. Or maybe long. It's arbitrary. So we have our one.

Let's draw a multiplication line. It's just a long straight line. Jot a zero mark on there, copy the one-vector on the line. Now draw another one-vector at the end of the previous one, but rotated 90 degrees. Draw a dotted line from the zero mark to the end of the second one. There we go, 1 multiplied by 1. Is 1.

Now take some other lines, say 4 and 5. The 4-line is 4 times longer than the one-line. And the 5-line 5 times. Multiply 4 by 5. Draw the 4-line in the place of the second one-line. So that it's standing up, one unit away from zero. Then draw a line from zero through the end of the 4-line. Right, that's the line that multiplies numbers by 4. When it's one distant from zero, it's 4 units up. When the distance is two, it's 8 units up. And so on.

Now copy the 5-line on the multiplication line. And draw a normal to the multiplication line through the end of the 5-line. This is the line that multiplies numbers by 5. Where the 4-multiplier line and the 5-multiplier line cross, there's the result. The normal vector from the multiplication line to the result point is the number 4 times 5. To convert it into a number line number, rotate it 90 degrees so that it's flat on the number line.

Division is, well, there's a trick to it. You want to create the number 1/A. So let's do the multiplication line thing again. This time, draw an upright one-vector A units away from zero. Draw a line from zero through the end of that vector. Then draw a normal line one unit away from zero. The crossing point of those two lines is 1/A.

Blog Archive