The Programming Language as Human Interface

Steven Pemberton, CWI, Amsterdam

A URL in your data

<data xmlns="">

<output ref="url"/>

<output ref="url" mediatype="image/*"/>

map tile

The structure of an OSM URL


Store the parts of the URL in the data, and calculate the URL

   <map xmlns="">

<bind nodeset="url"
      calculate="concat(../site, ../zoom, '/', ../x, '/', ../y, '.png')"/>

Since the parts are data, you can input them as well

<input ref="zoom"><label>zoom</label></input>

Add nudge buttons

   <setvalue ev:event="DOMActivate" ref="x" value=". + 1"/>

Fix the zoom problem

<bind nodeset="scale" 
      calculate="power(2, 26 - ../zoom)"/>
<bind nodeset="x" 
      calculate="floor(../posx div ../scale)"/>
<bind nodeset="y" 
      calculate="floor(../posy div ../scale)"/>

Why locations bounce around as you zoom


Keeping the location in the centre


Calculating the offsets

<bind nodeset="offx" 
   calculate="0 - floor(((../posx - ../x * ../scale) div ../scale)*../tilesize)" />
<bind nodeset="offy" 
   calculate="0 - floor(((../posy - ../y * ../scale) div ../scale)*../tilesize)" />

<div style="margin-left: {offx}px; margin-top: {offy}px">...

Making the map draggable; step 1: the mouse


<action ev:event="mousemove">
   <setvalue ref="mouse/x" value="event('clientX')"/>
   <setvalue ref="mouse/y" value="event('clientY')"/>
<action ev:event="mousedown">
   <setvalue ref="mouse/state">down</setvalue>
<action ev:event="mouseup">
   <setvalue ref="mouse/state">up</setvalue>

Styling the mouse cursor

<bind nodeset="mouse/cursor"
      calculate="if(../state='up', 'pointer', 'move')"/>

<div style="cursor: {cursor}">... 

Calculating the drag


<action ev:event="mousedown">
    <setvalue ref="mouse/state">down</setvalue>
    <setvalue ref="mouse/start/x" value="event('clientX')"/>
    <setvalue ref="mouse/start/y" value="event('clientY')"/>


<bind ref="mouse/end/x" 
    calculate="if(mouse/state = 'down', mouse/x, .)"/>
<bind ref="mouse/end/y" 
    calculate="if(mouse/state = 'down', mouse/y, .)"/>
<bind ref="mouse/move/x"
    calculate="mouse/end/x - mouse/start/x"/>
<bind ref="mouse/move/y" 
    calculate="mouse/end/y - mouse/start/y"/>

Remembering the most recent location

<bind ref="posx" 
 calculate="../lastx - ../mouse/move/x*(../scale div ../tilesize)"/>
<bind ref="posy"  
 calculate="../lasty - ../mouse/move/y*(../scale div ../tilesize)"/>

<action ev:event="mouseup">
    <setvalue ref="lastx" value="posx"/>
    <setvalue ref="lasty" value="posy"/>
    <setvalue ref="mouse/start/x" value="mouse/end/x"/>
    <setvalue ref="mouse/start/y" value="mouse/end/y"/>


Adding bells and whistles

<select1 ref="site">

150-200 lines of code


In around 150 lines, we have coded a complete draggable map application.

The application is largely declarative: it says WHAT should happen, now HOW to do it.

We let the computer do more of the work.

The savings are immense.