<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  <title>BenjaminBenBen</title>
  <subtitle>Some stuff by Ben Foxall</subtitle>
  <link href="https://benjaminbenben.com/atom.xml" rel="self" />
  <link href="https://benjaminbenben.com/" />
  <updated>2025-08-19T00:00:00Z</updated>
  <id>https://benjaminbenben.com/</id>
  <author>
    <name>Ben Foxall</name>
  </author>
  <entry>
    <title>Offline QR Codes</title>
    <link href="https://benjaminbenben.com/2025/08/19/offline-qr-codes/" />
    <updated>2025-08-19T00:00:00Z</updated>
    <id>https://benjaminbenben.com/2025/08/19/offline-qr-codes/</id>
    <content type="html">&lt;p class=&quot;lead&quot;&gt;Using QR Codes to send data from offline devices&lt;/p&gt;
&lt;h2&gt;👉 From a sensor&lt;/h2&gt;
&lt;p&gt;If a sensor has a display, it can show a qr code with the data encoded in a url. An example is &lt;a href=&quot;https://github.com/benfoxall/sensor&quot;&gt;this temperature sensor&lt;/a&gt; sharing recent values in a &lt;a href=&quot;https://benjaminbenben.com/sensor/?d=905,904,902,902,900,900,899,899,898,898,897,897,897,896,896,896,896,896,894,894&amp;amp;c=35&quot;&gt;collector page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://benjaminbenben.com/img/offline-collector.png&quot; alt=&quot;A Pi Pico + e-ink display linking to a web page that shows a graph of values&quot; class=&quot;no-border&quot;&gt;&lt;/p&gt;
&lt;p&gt;🛜 &lt;strong&gt;Everything works offline&lt;/strong&gt;. The microcontroller has no network code and the collector page can work offline.&lt;/p&gt;
&lt;p&gt;🔋 &lt;strong&gt;Power efficient&lt;/strong&gt;. E-ink displays don&#39;t require continous power so controller could go into deep sleep between updates.&lt;/p&gt;
&lt;p&gt;🔨 &lt;strong&gt;Robust&lt;/strong&gt;. You could take a polaroid photo of the sensor and mail it to your friend for them to scan it if you want!&lt;/p&gt;
&lt;p&gt;💾 &lt;strong&gt;Collection&lt;/strong&gt;. Storing historical data is possible by forwarding to server when the collector device is &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Background_Synchronization_API&quot;&gt;back online&lt;/a&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;👉 From a web page&lt;/h2&gt;
&lt;p&gt;You don&#39;t need a microcontroller to collect data. Browsers are a rich source of content. When you draw in the box below it&#39;ll encode your art in a qr code (&lt;a href=&quot;https://github.com/benfoxall/qdraw&quot;&gt;source&lt;/a&gt;).&lt;/p&gt;
&lt;div class=&quot;qdraw&quot; data-target=&quot;https://benjaminbenben.com/qdraw/&quot;&gt;
  &lt;canvas class=&quot;qdraw-paint&quot; width=&quot;1024&quot; height=&quot;1024&quot;&gt;&lt;/canvas&gt;
  &lt;a href=&quot;https://benjaminbenben.com/2025/08/19/offline-qr-codes/&quot; class=&quot;qdraw-link&quot; target=&quot;_blank&quot;&gt;
    &lt;canvas class=&quot;qdraw-qr&quot; width=&quot;100&quot; height=&quot;100&quot;&gt;&lt;/canvas&gt;
  &lt;/a&gt;
  &lt;script src=&quot;https://benjaminbenben.com/js/qdraw.js&quot;&gt;&lt;/script&gt;
  &lt;script&gt;
    document.querySelector(&#39;.qdraw-paint&#39;).addEventListener(&#39;touchstart&#39;, e =&gt; e.preventDefault())
  &lt;/script&gt;
&lt;/div&gt;
&lt;p&gt;You might notice as you draw more lines the QR code becomes more dense. I implemented some rudimentary path simplification, but there&#39;s limits to the amount of content you can share this way.&lt;/p&gt;
&lt;p&gt;The key requirement is that target page state should be derived from the url, and once you&#39;ve got that you can save and share content in any number of ways, not just a qr code.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;👉 Between web pages&lt;/h2&gt;
&lt;p&gt;Browsers can also &lt;strong&gt;scan&lt;/strong&gt; QR Codes. This allows us to create a bidirectional socket between two offline devices using their front-facing cameras.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://benjaminbenben.com/img/qr-socket.svg&quot; alt=&quot;QR Socket Demo&quot; class=&quot;no-border&quot;&gt;&lt;/p&gt;
&lt;p&gt;I &lt;a href=&quot;https://remotehack.space/QR-TX/&quot;&gt;implemented this&lt;/a&gt; as a joke, but after a while it started working oddly well.&lt;/p&gt;
&lt;p&gt;To manage the connection I used a basic protocol; a client bootstraps the connection by displaying the url of the current page (useful for setting up the second device). When a matching url is detected the devices go into &amp;quot;data mode&amp;quot;, where a string of &lt;strong&gt;&lt;code&gt;[RX, TX, Data]&lt;/code&gt;&lt;/strong&gt; is encoded in the qr code.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;RX&lt;/code&gt; - last message id seen by the device&lt;/li&gt;
&lt;li&gt;&lt;code&gt;TX&lt;/code&gt; - message id being transmitted&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Data&lt;/code&gt; - payload (string)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Messages are chunked to a fairly arbitrary string length. This could definitely be improved to target the capacity of a particular code size. An interesting extension could be switching between different resolutions to pick the highest capacity for a camera+screen combination.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Side note: QR Codes support &lt;a href=&quot;https://ozeki.hu/p_3465-qr-code-encoding.html#:~:text=0011-,Structured%20append&quot;&gt;structured append&lt;/a&gt; for spreading messages over multiple codes. Pretty cool, but I didn&#39;t use it.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The coding interface feels a bit like a WebSocket:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; qs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;QRSocket&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

qs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;message&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
qs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Hello World!&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;One area for improvement is disposing of the socket; currently you have to close the page otherwise the camera will still be active. Having some method for pausing the socket might make this feel more natural.&lt;/p&gt;
&lt;p&gt;🕹️ There&#39;s some demos online at &lt;a href=&quot;https://remotehack.space/QR-TX/&quot;&gt;remotehack.space/QR-TX&lt;/a&gt; and &lt;a href=&quot;https://github.com/remotehack/QR-TX&quot;&gt;source on github&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://remotehack.space/QR-TX/?demo=send&quot;&gt;Send&lt;/a&gt; - Basic example that sends text of different lengths.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://remotehack.space/QR-TX/?demo=chat&quot;&gt;Chat&lt;/a&gt; - Send multiple messages between devices. &lt;a href=&quot;https://www.ticklethepanda.dev/&quot;&gt;Panda&lt;/a&gt; and I built this at &lt;a href=&quot;https://remotehack.space&quot;&gt;remote hack&lt;/a&gt;, it was a lot of fun and slightly mind-bending when we were lining up our phones remotely over a discord room.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://remotehack.space/QR-TX/?demo=signal&quot;&gt;Signalling&lt;/a&gt; - Negotiates a peer-to-peer webrtc video link between devices.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure style=&quot;max-width: 50%; margin-left: 25%; text-align:center; display: flex; flex-direction: column&quot;&gt;
  &lt;video src=&quot;https://benjaminbenben.com/img/qr-sock-hello.mp4&quot; muted=&quot;&quot; autoplay=&quot;&quot; loop=&quot;&quot; controls=&quot;&quot;&gt;&lt;/video&gt;
  &lt;figcaption&gt;[Chatting](https://remotehack.space/QR-TX/?demo=chat) between my desktop &amp;amp; phone&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;As before, these demos have a Service Worker which caches the page. I&#39;ve enjoyed giving demos to people before showing them that my phone is in aeroplane mode 🤯. It feels like there&#39;s interesting use cases of being able to sync with someone when either of you are completely offline.&lt;/p&gt;
&lt;p&gt;I shared a quick demo at &lt;a href=&quot;https://lu.ma/foclondon&quot;&gt;Future of Coding&lt;/a&gt; [&lt;a href=&quot;https://benjaminbenben.com/assets/slides/qrtx.pdf&quot;&gt;slides&lt;/a&gt;] last year. And a longer talk about QR Codes and other stuff at &lt;a href=&quot;https://mkgeeknight.co.uk/events/mkgn-50#Ben&quot;&gt;MKGN&lt;/a&gt; [&lt;a href=&quot;https://www.youtube.com/watch?v=mJnzN8pd8Gc&quot;&gt;video&lt;/a&gt;].&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;More things&lt;/h2&gt;
&lt;p&gt;That I&#39;ve built:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://benjaminbenben.com/qr/&quot;&gt;QR Code Scanner&lt;/a&gt; - This scanner auto-redirects to any detected urls (even if that url is &lt;code&gt;&#39;javascript:alert(&amp;quot;hello&amp;quot;)&#39;&lt;/code&gt; 😬).&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://benjaminbenben.com/flatten/live.html&quot;&gt;QR Undistort&lt;/a&gt; - This looks for a QR Code from a camera feed and transforms the video element so that it&#39;s central. &lt;a href=&quot;https://benjaminbenben.com/img/qr-undistort.jpg&quot;&gt;Like this&lt;/a&gt;!&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://benjaminbenben.com/qtext/&quot;&gt;QR Text&lt;/a&gt; - An text-based version of &lt;a href=&quot;https://github.com/benfoxall/qdraw&quot;&gt;qdraw&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That I like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=w5ebcowAJD8&quot;&gt;&amp;quot;I built a QR code with my bare hands to see how it works&amp;quot;&lt;/a&gt; - great video exploring how qr codes work. This made reed solomon encoding finally click for me.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=ExwqNreocpg&quot;&gt;Snake in a QR Code&lt;/a&gt; - there&#39;s something I love about &amp;quot;chmod +x&amp;quot; on something you captured from your webcam.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/qifi-dev/qrs&quot;&gt;qrs&lt;/a&gt; &amp;amp; &lt;a href=&quot;https://github.com/divan/txqr&quot;&gt;txr&lt;/a&gt; - cool approach for one-way streaming using &lt;a href=&quot;https://divan.dev/posts/fountaincodes/&quot;&gt;fountain&lt;/a&gt; codes.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://meshtastic.org/&quot;&gt;meshtastic&lt;/a&gt; - not QR codes, but it&#39;s pretty cool to use WebBluetooth to communicate with devices over a different network.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Video Space</title>
    <link href="https://benjaminbenben.com/2025/07/16/video-space/" />
    <updated>2025-07-16T00:00:00Z</updated>
    <id>https://benjaminbenben.com/2025/07/16/video-space/</id>
    <content type="html">&lt;p class=&quot;lead&quot;&gt;Here&#39;s a video that&#39;s played back in the space it was captured&lt;/p&gt;
&lt;p&gt;👀 It&#39;s interactive, drag the viewer to adjust the viewpoint&lt;/p&gt;
&lt;pose-tracker poses=&quot;https://vs.benjaminbenben.com/motocamp/poses.ply&quot; points=&quot;https://vs.benjaminbenben.com/motocamp/points.bin.ply&quot;&gt;
    &lt;video src=&quot;https://vs.benjaminbenben.com/motocamp/720.mp4&quot; crossorigin=&quot;anonymous&quot; muted=&quot;&quot; autoplay=&quot;&quot; playsinline=&quot;&quot;&gt;&lt;/video&gt;
&lt;/pose-tracker&gt;
&lt;script src=&quot;https://benjaminbenben.com/js/pose-tracker.js&quot; async=&quot;&quot;&gt;&lt;/script&gt;
&lt;label style=&quot;padding-top: .5em; display: block&quot;&gt;
    &lt;select&gt;
        &lt;option value=&quot;motocamp&quot;&gt;Motocamping&lt;/option&gt;
        &lt;option value=&quot;wall&quot;&gt;A beach near Poolbeg Lighthouse&lt;/option&gt;
        &lt;option value=&quot;bike-dog&quot;&gt;Cycling next to a friendly dog&lt;/option&gt;
        &lt;option value=&quot;drone-chile&quot;&gt;A confluence in Chile&lt;/option&gt;
        &lt;option value=&quot;mizen-walk&quot;&gt;Mizen head: A start/finish line&lt;/option&gt;
        &lt;option value=&quot;mizen-fly&quot;&gt;Mizen head: Flying over some cliffs&lt;/option&gt;
    &lt;/select&gt;
    &lt;script&gt;
        document.currentScript.previousElementSibling.addEventListener(&#39;change&#39;, ({target: {value}}) =&gt; {
            document.querySelector(&#39;pose-tracker&#39;).outerHTML = `
                    &lt;pose-tracker 
                        poses=&quot;https://vs.benjaminbenben.com/${value}/poses.ply&quot; 
                        points=&quot;https://vs.benjaminbenben.com/${value}/points.bin.ply&quot;&gt;
                        &lt;video src=&quot;https://vs.benjaminbenben.com/${value}/720.mp4&quot; crossorigin=&quot;anonymous&quot; muted autoplay playsinline&gt;&lt;/video&gt;
                    &lt;/pose-tracker&gt;
                `
            document.querySelector(&#39;pose-tracker video&#39;).play()
        })
    &lt;/script&gt;
    &amp;larr; More videos 
&lt;/label&gt;
&lt;h3&gt;Locating frames&lt;/h3&gt;
&lt;p&gt;I was hoping to use the telemetry data from my &lt;a href=&quot;https://www.dji.com/mini-4-pro&quot;&gt;drone&lt;/a&gt;; it produces a text file with it&#39;s location as it captures video. However this doesn&#39;t include orientation or camera gimble info so I wasn&#39;t able to map it into a pose.&lt;/p&gt;
&lt;p&gt;So I decided to use &lt;a href=&quot;https://colmap.github.io/&quot;&gt;COLMAP&lt;/a&gt;, a Structure-from-Motion tool which allows you to take a series of images to build a scene. COLMAP stores the position from which each image was captured which I was able to use for aligning the video frames. As a bonus, this works for other video sources, not just drone footage.&lt;/p&gt;
&lt;p&gt;I wrote some slightly scrappy code to extract and serialise the poses and points into a ply file that I could load into a webgl component. You can read some of the process (and see some gaussian splats) on this &lt;a href=&quot;https://bsky.app/profile/benfoxall.bsky.social/post/3lt2wjk6tgc22&quot;&gt;bluesky&lt;/a&gt; thread.&lt;/p&gt;
&lt;h3&gt;Implementation&lt;/h3&gt;
&lt;p&gt;I’m pretty happy with how this is structured, it’s a web component that wraps a &lt;code&gt;&amp;lt;video /&amp;gt;&lt;/code&gt; element with links to the colmap data:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;pose-tracker&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;poses&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;poses.ply&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;points&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;points.ply&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;video&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;motocamp.mp4&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;video&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;pose-tracker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Internally the video element is hidden but still drives the playback of the component, which is some html controls &amp;amp; a webgl canvas element.&lt;/p&gt;
&lt;p&gt;The canvas is rendered by threejs. The key trick is using a single 2d texture array to stash the historical video frames, with an instanced mesh that allows everything to be drawn together. My original approach for pushing the frames was using a 2dCanvas to write the pixels into a array buffer, but I found &lt;code&gt;WebGLArrayRenderTarget&lt;/code&gt; which lets you populate texture arrays directly!&lt;/p&gt;
&lt;p&gt;I didn&#39;t want/need every frame of the video, so I sampled it (from 60 → 2-5 Hz) and interpolate to find the position at a set timestamp. Orientation is quite straightforward in threejs, but for translation I was really happy when I found &lt;a href=&quot;https://www.npmjs.com/package/curve-interpolator&quot;&gt;curve-interpolator&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Data sources &amp;amp; formats&lt;/h2&gt;
&lt;p&gt;Using structure from motion is cool, but you can get potentially richer data from sensors on the capture device.&lt;/p&gt;
&lt;p&gt;For drones, the &lt;a href=&quot;https://fpv.ifi.uzh.ch/datasets/&quot;&gt;UZH-FPV Drone Racing Dataset&lt;/a&gt; is a great example of the sort of data that&#39;s available.&lt;/p&gt;
&lt;p&gt;For capturing from a mobile device &lt;a href=&quot;https://immersive-web.github.io/raw-camera-access/&quot;&gt;WebXR Raw Camera Access&lt;/a&gt; could be an option for capturing pose-aligned video.&lt;/p&gt;
&lt;p&gt;GoPro cameras have a &lt;a href=&quot;https://github.com/gopro/gpmf-parser&quot;&gt;telemetry format&lt;/a&gt; which looks like it captures a bunch of metadata.&lt;/p&gt;
&lt;p&gt;And for output formats, I enjoyed using &lt;a href=&quot;https://en.wikipedia.org/wiki/PLY_(file_format)&quot;&gt;ply&lt;/a&gt; because it&#39;s so lightweight/flexible (it can be just a text file!). But if I was doing this properly I&#39;d probably use something like &lt;a href=&quot;https://mcap.dev/&quot;&gt;mcap&lt;/a&gt; to link everything together.&lt;/p&gt;
&lt;p&gt;I&#39;ve got a fairly shonky pipeline for processing videos now, so if there&#39;s something that you think would be interesting give me a shout and I&#39;ll run it through!&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Stacks Camera</title>
    <link href="https://benjaminbenben.com/2025/06/29/stacks-camera/" />
    <updated>2025-06-29T00:00:00Z</updated>
    <id>https://benjaminbenben.com/2025/06/29/stacks-camera/</id>
    <content type="html">&lt;p&gt;I’ve been working on a side project - &lt;a href=&quot;https://stacks.camera&quot;&gt;stacks.camera&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://stacks.camera&quot;&gt;&lt;img src=&quot;https://benjaminbenben.com/img/stacks-home.png&quot; alt=&quot;stacks.camera&quot; class=&quot;no-border&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It’s a tool that lets you capture a series of images by overlaying the most recent capture when you’re taking a new photo.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://stacks.camera&quot;&gt;&lt;img src=&quot;https://benjaminbenben.com/img/stacks-overlay.png&quot; alt=&quot;stacks.camera&quot; class=&quot;no-border&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can see my public stacks at &lt;a href=&quot;https://stacks.camera/u/ben&quot;&gt;u/ben&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here&#39;s some that I&#39;ve enjoyed creating:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://stacks.camera/u/ben/89n1HJNT&quot;&gt;Window&lt;/a&gt; - I started taking pictures out of my window as a test, but I’ve found it pretty satisfying to keep adding to.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stacks.camera/u/ben/OW9AyEFg&quot;&gt;Circles&lt;/a&gt; - stacks can be collaborative, this is one that I created to experiment with that.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stacks.camera/u/ben/nRezTTQj3lWQ&quot;&gt;Pipes&lt;/a&gt; - it’s been fun to walk around objects and create animations.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stacks.camera/u/saz/87XM1YV-VdHX&quot;&gt;Poolbeg Chimneys&lt;/a&gt; - Sarah and I captured this on a walk along Dublin Bay, it felt quite fun!&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h3&gt;Why I&#39;ve been working on this&lt;/h3&gt;
&lt;p&gt;I’ve been playing around this topic for years (&lt;a href=&quot;https://benjaminbenben.com/2016/03/03/gif/&quot;&gt;gif-stack&lt;/a&gt;, &lt;a href=&quot;https://benjaminbenben.com/video-stills/&quot;&gt;video-stills&lt;/a&gt;, &lt;a href=&quot;https://benjaminbenben.com/scrub&quot;&gt;scrub&lt;/a&gt;, &lt;a href=&quot;https://benjaminbenben.com/overlay&quot;&gt;overlay&lt;/a&gt;), I wanted to make something more than a hack/proof-of-concept, and see if resonates with anyone.&lt;/p&gt;
&lt;p&gt;It was also a chance to experiment &amp;amp; learn with some stuff. I’ve been learning a lot about Cloudflare Workers/Images/Workflows, Passkeys, image loading/rendering approaches, and also seeing where AI tooling can fit into my development.&lt;/p&gt;
&lt;p&gt;It’s rough around the edges, but I’ve enjoyed the decisions that have made it that way! Please do &lt;a href=&quot;https://stacks.camera&quot;&gt;sign up&lt;/a&gt; (it’s very minimal), and I’d love to know what you think.&lt;/p&gt;
&lt;h1&gt;👉 &lt;a href=&quot;https://stacks.camera&quot;&gt;stacks.camera&lt;/a&gt;&lt;/h1&gt;
</content>
  </entry>
  <entry>
    <title>Dublin London Dublin</title>
    <link href="https://benjaminbenben.com/2025/06/12/london+dublin/" />
    <updated>2025-06-12T00:00:00Z</updated>
    <id>https://benjaminbenben.com/2025/06/12/london+dublin/</id>
    <content type="html">&lt;p class=&quot;lead&quot;&gt;I&#39;ve not posted here for a while &lt;small style=&quot;opacity:0.4; font-size: .6em&quot;&gt;5 years 😱&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;This is some stuff that I&#39;ve been doing since then:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Working at &lt;a href=&quot;https://oxa.tech&quot;&gt;Oxa&lt;/a&gt;&lt;/strong&gt; I had super fun times working on Map Tech and various web things across the company.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Moved to Dublin with Sarah&lt;/strong&gt; I packed for a couple of weeks, which covid turned into a couple of years.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Got a job at &lt;a href=&quot;https://wayve.ai&quot;&gt;Wayve&lt;/a&gt; and moved to London&lt;/strong&gt; started out in Experiment Orchestration 🙅🫶 then created the Robot Web team to focus on in-vehicle and remote access tools.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sarah moved to London&lt;/strong&gt; after a year of us travelling between the UK &amp;amp; Ireland, Sarah came to join me in London.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sarah and I got married&lt;/strong&gt; it was a lovely day with lovely people 🥰.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Left Wayve and moved back to Dublin&lt;/strong&gt; earlier this year we left London and returned to Dublin.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&#39;ve managed to travel a lot - Namibia, Whistler, France, Chile and a few trips to California for work. I&#39;ve taken some &lt;a href=&quot;https://www.polarsteps.com/BenFoxall/5408429-motorbiking&quot;&gt;motorbiking trips&lt;/a&gt;, been snowboarding a bunch of times, and travelled by bicycle on a few trips.&lt;/p&gt;
&lt;p&gt;During lockdowns we started &lt;a href=&quot;https://remotehack.space/&quot;&gt;Remote Hack&lt;/a&gt; which was such a lovely way to connect and explore some fun projects. And in person I loved catching up with folks at places like MKGN, OGN &amp;amp; emfcamp.&lt;/p&gt;
&lt;p&gt;Next up, I&#39;m taking some time off to relax, recharge and work on some side projects before I start looking for a new roles later in the summer.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;PS. This is where I&#39;d usually curse myself by saying I&#39;ll post more often, but I think I&#39;ll just leave it at that for now!&lt;/em&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Hacks</title>
    <link href="https://benjaminbenben.com/2020/05/26/hacks/" />
    <updated>2020-05-26T00:00:00Z</updated>
    <id>https://benjaminbenben.com/2020/05/26/hacks/</id>
    <content type="html">&lt;p class=&quot;lead&quot;&gt;I built some things a (long) while ago – I found it really satisfying but never bothered to blog about it.&lt;/p&gt;
&lt;h2&gt;Cardboctober&lt;/h2&gt;
&lt;p&gt;Way back in 2016, &lt;a href=&quot;https://twitter.com/omgmog&quot;&gt;Max&lt;/a&gt;, &lt;a href=&quot;https://twitter.com/peterjwest&quot;&gt;Pete&lt;/a&gt; &amp;amp; I tried to make a &lt;a href=&quot;https://arvr.google.com/cardboard/&quot;&gt;Google Cardboard&lt;/a&gt; hack for every day of October.&lt;/p&gt;
&lt;p&gt;It was an awesome experience. There&#39;s something very liberating about the daily time constraint; it&#39;s stops you striving for perfection, and lets you move on to something new without feeling regret.&lt;/p&gt;
&lt;p&gt;I also loved sharing the experience with Pete and Max. We all took different directions &lt;a href=&quot;https://cardboctober.github.io/&quot;&gt;with our hacks&lt;/a&gt;. I was trying to build my own render engine, Max was exploring UX ideas and Tetris, and Pete went off playing with cats, fish, the moon, archery, lasers and beer cans.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://cardboctober.github.io/ben/&quot;&gt;&lt;img src=&quot;https://benjaminbenben.com/img/2020-hacks-cardboctober.png&quot; alt=&quot;Cardboctober (ben)&quot; class=&quot;no-border&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Webgl hacks&lt;/h2&gt;
&lt;p&gt;Into 2017 &lt;small&gt;(don&#39;t worry, I&#39;ll be blogging about newer stuff soon)&lt;/small&gt;, I decided to learn WebGL from the ground up. Before then, I&#39;d used it a bit through libraries or frameworks.&lt;/p&gt;
&lt;p&gt;I spent a &lt;strong&gt;whole day&lt;/strong&gt; on my first hack, and ended up with this:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://benjaminbenben.com/webgl-hacks/01/&quot;&gt;&lt;img src=&quot;https://benjaminbenben.com/img/2020-hacks-dot.png&quot; alt=&quot;Small pink square in a web browser&quot; class=&quot;no-border&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I&#39;m still proud of that square.&lt;/p&gt;
&lt;p&gt;Over a few weeks, I explored a few more ideas and learned a &lt;strong&gt;lot&lt;/strong&gt;. It&#39;s kinda cool to think back to this, as I&#39;m doing quite a lot of WebGL as part of &lt;a href=&quot;https://oxbotica.com&quot;&gt;my job&lt;/a&gt; these days.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://benjaminbenben.com/webgl-hacks/&quot;&gt;&lt;img src=&quot;https://benjaminbenben.com/img/2020-hacks-webgl.png&quot; alt=&quot;WebGL hacks&quot; class=&quot;no-border&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Simple Things&lt;/h2&gt;
&lt;p&gt;I gave a one-off talk at a hack day.&lt;/p&gt;
&lt;p&gt;It was about applying bounds to your creative output (much like Cardboctober &amp;amp; WebGL Hacks).&lt;/p&gt;
&lt;p&gt;I described the properties that I&#39;d like from a &amp;quot;Thing&amp;quot;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Easily described &amp;amp; understood&lt;/li&gt;
&lt;li&gt;A self-contained object&lt;/li&gt;
&lt;li&gt;Open to be reused&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Then I talked about cassette tapes a lot because I think they&#39;re a really great example of a unit of creativity.&lt;/p&gt;
&lt;script async=&quot;&quot; class=&quot;speakerdeck-embed&quot; data-slide=&quot;9&quot; data-id=&quot;9328bb0bc62a40f1a98e49ebebf1bd4d&quot; data-ratio=&quot;1.77777777777778&quot; src=&quot;https://speakerdeck.com/assets/embed.js&quot;&gt;&lt;/script&gt;
&lt;h2&gt;Making a lot of things&lt;/h2&gt;
&lt;p&gt;This sounds like a similar talk, but it was entirely different.&lt;/p&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/Pve8JoaTNqE&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;p&gt;I&#39;d followed &amp;quot;what is a unit of creativity&amp;quot; through to JavaScript, and I wrote an &lt;a href=&quot;https://cojs.co/&quot;&gt;experimental code editor&lt;/a&gt; to play with some of the ideas of constraint and exploration.&lt;/p&gt;
&lt;p&gt;Although I&#39;m really proud of the ideas and effort that I put into this talk, I&#39;m unhappy with how I gave it. I was the closing talk at my favourite conference, and instead of getting confidence from that, I ended up trying to prove that I was worthy of being there by throwing down a bunch of technical and portfolio stuff.&lt;/p&gt;
&lt;p&gt;Having said that, I just found a &lt;a href=&quot;http://blog.mathieu-leplatre.info/the-joy-of-microhacks.html&quot;&gt;really awesome post about it by Mathieu&lt;/a&gt;. Also, &lt;a href=&quot;https://coverhound.com/blog/post/joe-jv-take-on-full-stack-fest-2017&quot;&gt;Joe&lt;/a&gt; &amp;amp; &lt;a href=&quot;https://medium.com/@SkyscannerEng/problems-of-today-wonders-from-the-future-d6c9d1eff290&quot;&gt;Calum&lt;/a&gt; wrote some kind words about the talk.&lt;/p&gt;
&lt;h2&gt;Microhacks&lt;/h2&gt;
&lt;p&gt;I ended that talk with the idea of &amp;quot;Microhacks&amp;quot;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Plan the goal, not the approach&lt;/strong&gt; – as developers, we can spend a lot of time working out a perfect technical solution and not actually doing anything.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Schedule as little time as possible&lt;/strong&gt; – it&#39;s easier to fit in &amp;quot;smashing something out in 20 minutes&amp;quot;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Explore&lt;/strong&gt; – if it doesn&#39;t look like you thought it would; great! You&#39;ve got a different thing.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Define your outlet&lt;/strong&gt; – have a goal of where you&#39;ll publish it, so you&#39;ll know when it&#39;s done.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Publish first, tinker second&lt;/strong&gt; – we often go into a &amp;quot;clean up&amp;quot; phase. For hacks, you can do this later (or not at all).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Do it again&lt;/strong&gt; - Make a fresh copy, and do something even cooler this time.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>2018 ➡️ 2020</title>
    <link href="https://benjaminbenben.com/2020/05/25/update/" />
    <updated>2020-05-25T00:00:00Z</updated>
    <id>https://benjaminbenben.com/2020/05/25/update/</id>
    <content type="html">&lt;p class=&quot;lead&quot;&gt;I&#39;ve been up to a load of things over the last couple of years.&lt;/p&gt;
&lt;p&gt;A few highlights:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;🇳🇿 Cycled around New Zealand with Sarah&lt;/li&gt;
&lt;li&gt;🤖 Started working at &lt;a href=&quot;https://www.oxbotica.com/&quot;&gt;Oxbotica&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;🏍 Bought a motorbike&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For a more visual guide – I drew some emoji over the top of a calendar (&lt;a href=&quot;https://twitter.com/benjaminbenben/status/1257382520179605505&quot;&gt;see twitter for more details&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://benjaminbenben.com/img/2018-2020.png&quot; alt=&quot;2018-2020&quot;&gt;&lt;/p&gt;
&lt;p&gt;It might not be the most efficient diary of events, though it was pretty fun to put together 💕.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Blog Post</title>
    <link href="https://benjaminbenben.com/2020/05/25/blog-post/" />
    <updated>2020-05-25T00:00:00Z</updated>
    <id>https://benjaminbenben.com/2020/05/25/blog-post/</id>
    <content type="html">&lt;p class=&quot;lead&quot;&gt;My friend &lt;a href=&quot;https://www.oliverlorton.co.uk/&quot;&gt;Oliver&lt;/a&gt; logged &lt;a href=&quot;https://github.com/benfoxall/benfoxall.github.com/issues/69&quot;&gt;this issue&lt;/a&gt; over on GitHub.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/benfoxall/benfoxall.github.com/issues/69&quot;&gt;&lt;img src=&quot;https://benjaminbenben.com/img/2020-blog-issue.png&quot; alt=&quot;Needs more blog posts: Hey Ben, write something.&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Thanks dude.&lt;/p&gt;
&lt;p&gt;I hope this blog post, and the words within it, helps resolve the issue for you?&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>GIF</title>
    <link href="https://benjaminbenben.com/2016/03/03/gif/" />
    <updated>2016-03-03T00:00:00Z</updated>
    <id>https://benjaminbenben.com/2016/03/03/gif/</id>
    <content type="html">&lt;div id=&quot;gs-choose&quot;&gt;
&lt;img src=&quot;https://benjaminbenben.com/img/example.gif&quot; id=&quot;gs-file-preview&quot;&gt;
&lt;/div&gt;
&lt;p class=&quot;lead&quot;&gt;Animated gifs are &lt;em&gt;brilliant&lt;/em&gt;…&lt;/p&gt;
&lt;p&gt;…But they’re also kind of rubbish. We can’t pause a gif, skip to a particular point, or grab individual frames from the image element.&lt;/p&gt;
&lt;p&gt;One way around these problems is to load the file content with JavaScript and decode it manually.&lt;/p&gt;
&lt;p&gt;There are a bunch of different libraries that can decode gif (check out &lt;a href=&quot;https://github.com/deanm/omggif&quot;&gt;omggif&lt;/a&gt;, &lt;a href=&quot;https://github.com/rfrench/gify&quot;&gt;gify&lt;/a&gt; &amp;amp; &lt;a href=&quot;https://github.com/devongovett/gif-stream&quot;&gt;gif-stream&lt;/a&gt;). I’m a fan of the decoder in &lt;a href=&quot;http://slbkbs.org/jsgif/&quot;&gt;jsgif&lt;/a&gt;; it’s awkward to use, pretty inefficient, a bit dated, and feels nice.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token function&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;file&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function-variable function&quot;&gt;hdr&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// handle header data&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You provide an object with a set of callbacks for the different parts of the gif.  Callbacks are fired as soon as that part of the gif is parsed and we can choose what we do with the data.&lt;/p&gt;
&lt;p&gt;For example, we can listen out for the &lt;code&gt;hdr&lt;/code&gt; (header) block, and pull out the global colour table for the gif.&lt;/p&gt;
&lt;p&gt;&lt;canvas id=&quot;gs-palette&quot;&gt;&lt;/canvas&gt;&lt;/p&gt;
&lt;p id=&quot;gs-palette-label&quot; class=&quot;gs-label&quot;&gt;Global colour table for example.gif&lt;/p&gt;
&lt;p&gt;With the actual image data; each frame of the animated gif starts with a Graphics Control Extension (GCE) block which contains information about the section being drawn, followed by the actual (LZW encoded) pixel data.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;I&#39;ve skimmed over a lot of really interesting stuff here - for a really in-depth look at gif encoding, check out &lt;a href=&quot;http://matthewflickinger.com/lab/whatsinagif/bits_and_bytes.asp&quot;&gt;this blog post&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Once we&#39;ve got those decoded pixel values back, we can map them through our colour tables to get the RGB values for each pixel, and now we&#39;ve got something that can be drawn to a canvas.&lt;/p&gt;
&lt;p&gt;&lt;canvas id=&quot;gs-canvas&quot; width=&quot;500&quot; height=&quot;500&quot;&gt;&lt;/canvas&gt;&lt;/p&gt;
&lt;p class=&quot;gs-label&quot;&gt;Exported frame data&lt;/p&gt;
&lt;p&gt;Each frame has an overwrite rule provided in its GCE block, which defines how the frame data is drawn to the existing graphic - either being appended to, or completely replacing it. This, combined with the transparency capabilities of the gif allow frames to update only the changed pixels of the image.&lt;/p&gt;
&lt;p&gt;By implementing overwrite rules, frame delays, and probably some other stuff, it&#39;s possible to play/pause/scrub through a gif file (see &lt;a href=&quot;https://github.com/buzzfeed/libgif-js&quot;&gt;libgif-js&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Though, back to the frame data - we don&#39;t have to settle on canvas .drawImage. If we load our data into a WebGL context, we can stack up the frames to get an overall feel for the structure of the gif:&lt;/p&gt;
&lt;p&gt;&lt;canvas id=&quot;gs-three&quot; width=&quot;500&quot; height=&quot;500&quot;&gt;&lt;/canvas&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;Other gifs&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://benjaminbenben.com/img/example-overwrite.gif&quot; class=&quot;gif-link&quot;&gt;A spinning shape&lt;/a&gt; - full re-draw each frame&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://benjaminbenben.com/img/example-colours.gif&quot; class=&quot;gif-link&quot;&gt;&amp;gt;256 colours&lt;/a&gt; - a palette limitation workaround&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://benjaminbenben.com/img/example-iso.gif&quot; class=&quot;gif-link&quot;&gt;Iso cubes&lt;/a&gt; by Bees&amp;amp;Bombs - looks awesome&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://benjaminbenben.com/img/example-bb-hex-friends.gif&quot; class=&quot;gif-link&quot;&gt;Hexagon Friends&lt;/a&gt; also, Bees&amp;amp;Bombs - looks pretty&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://benjaminbenben.com/img/example-trefoil.gif&quot; class=&quot;gif-link&quot;&gt;Trefoil&lt;/a&gt; yup, Bees&amp;amp;Bombs - nice angles&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://benjaminbenben.com/img/example-adventure.gif&quot; class=&quot;gif-link&quot;&gt;Adventure time&lt;/a&gt; - a more &lt;em&gt;traditional&lt;/em&gt; animation&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://benjaminbenben.com/img/example-kitten.gif&quot; class=&quot;gif-link&quot;&gt;Kitten&lt;/a&gt; - the majority of gifs&lt;/li&gt;
&lt;li&gt;
&lt;input type=&quot;file&quot; accept=&quot;.gif&quot; id=&quot;gs-choose-file&quot;&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Recommendation&lt;/h3&gt;
&lt;p&gt;Here&#39;s what the original gif spec has to say about animation:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Animation&lt;/strong&gt; : The Graphics Interchange Format is not intended as a platform for animation, even though it can be done in a limited way.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;…I kind of feel for the person who wrote this; it must be hard to look around the web and see millions of people ignoring your advice&lt;!--, and have the GIF become synonymous for the thing that it&#39;s worst at--&gt;. Though I hope they see the positive side - animated gifs might be a terrible hack; but they&#39;re totally brilliant.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;small&gt;ps. check out &lt;a href=&quot;http://beesandbombs.tumblr.com/&quot;&gt;Bees &amp;amp; Bombs&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;
&lt;!--
http://commandlinefanatic.com/cgi-bin/showarticle.cgi?article=art011
http://blog.pkh.me/p/21-high-quality-gif-with-ffmpeg.html
--&gt;
</content>
  </entry>
  <entry>
    <title>In with the old</title>
    <link href="https://benjaminbenben.com/2015/09/09/in-with-the-old/" />
    <updated>2015-09-09T00:00:00Z</updated>
    <id>https://benjaminbenben.com/2015/09/09/in-with-the-old/</id>
    <content type="html">&lt;p class=&quot;lead&quot;&gt;After more than a year of no posts - I&#39;m still here&lt;/p&gt;
&lt;p&gt;It’s been a really busy year; a lot of my spare time has been spent hacking on, or preparing for, talks. In the last year I’ve spoken at:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://mkgeeknight.co.uk/past#mkgn10&quot;&gt;MK Geek Night&lt;/a&gt;, &lt;a href=&quot;http://2014.ffconf.org/#getting-close-with-the-web&quot;&gt;FFconf&lt;/a&gt;, &lt;a href=&quot;http://breakingborde.rs/past-events/bleeding-edge/&quot;&gt;Breaking Borders&lt;/a&gt;, &lt;a href=&quot;https://vimeo.com/110060328&quot;&gt;All Your Base&lt;/a&gt;, &lt;a href=&quot;http://oxford.geeknights.net/ogn38/&quot;&gt;Oxford Geek Night&lt;/a&gt;, &lt;a href=&quot;http://jqueryuk.com/2015/talks.php#benfoxall&quot;&gt;jQueryUK&lt;/a&gt;, &lt;a href=&quot;http://mkgeeknight.co.uk/past#mkgn13&quot;&gt;MK Geek Night&lt;/a&gt;, &lt;a href=&quot;http://talkwebdesign.co.uk/twd/people/#post-335&quot;&gt;talk web design&lt;/a&gt;, &lt;a href=&quot;http://upfrontconf.com/speakers.html#ben&quot;&gt;Upfront&lt;/a&gt;, &lt;a href=&quot;http://www.fullstackfest.com/agenda/the-internet-of-browsers&quot;&gt;Full Stack Fest&lt;/a&gt; and &lt;a href=&quot;http://reasons.to/speakers/index.php?id=benfoxall&quot;&gt;Reasons to be creative&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.flickr.com/photos/garrettc/15666043922/&quot;&gt;&lt;img src=&quot;https://benjaminbenben.com/img/ayb.garrett.jpg&quot; alt=&quot;Ben Foxall, by garrettc&quot; class=&quot;img-responsive&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;photo: All Your Base, by Garrettc&lt;/p&gt;
&lt;p&gt;It’s been pretty exhausting, though I’ve got a lot from it.  I’ve been able to explore ideas with combining capabilities of lots of devices, how we can use IoT to inspire the way that we build applications, and recently I’ve been looking into our relationship with the data that we produce.&lt;/p&gt;
&lt;p&gt;I&#39;ve also been helping out with &lt;a href=&quot;http://jsoxford.com/&quot;&gt;JSOxford&lt;/a&gt; quite a lot; it&#39;s so awesome to see the community grow.  This year we had our second &lt;a href=&quot;http://summerofhacks.io/&quot;&gt;Summer of Hacks&lt;/a&gt;, which had &lt;strong&gt;FIVE&lt;/strong&gt; events (totally &lt;a href=&quot;https://twitter.com/spikeheap&quot;&gt;Ryans&#39;&lt;/a&gt; fault).&lt;/p&gt;
&lt;h3&gt;Next up&lt;/h3&gt;
&lt;p&gt;I&#39;ve got a few blog posts ideas logged as &lt;a href=&quot;https://github.com/benfoxall/benfoxall.github.com/labels/blog&quot;&gt;github issues&lt;/a&gt;; so I&#39;m going to try and start working through those.  A bit of a warning; I&#39;m going to focus on getting stuff written than making it super-great quality.  If you see typos, mistakes, or bad grammar; that&#39;s &lt;strong&gt;totally&lt;/strong&gt; why, ok. (also, it would be ace if you could &lt;a href=&quot;https://github.com/benfoxall/benfoxall.github.com&quot;&gt;correct&lt;/a&gt; them.)&lt;/p&gt;
&lt;p&gt;(most things I&#39;m working on are in github issues: &lt;a href=&quot;https://github.com/benfoxall/benfoxall.github.com/labels/talk&quot;&gt;talks&lt;/a&gt;, &lt;a href=&quot;https://github.com/benfoxall/benfoxall.github.com/labels/project&quot;&gt;projects&lt;/a&gt; and &lt;a href=&quot;https://github.com/benfoxall/benfoxall.github.com/labels/external&quot;&gt;other stuff&lt;/a&gt;)&lt;/p&gt;
&lt;h3&gt;And also&lt;/h3&gt;
&lt;p&gt;Although I’ve not been posting much online; other people have been putting stuff online with my face on it:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://twitter.com/omgmog&quot;&gt;Max&lt;/a&gt; built &lt;a href=&quot;https://web.archive.org/web/20180831115054/http://www.bensmindpalace.co.uk/&quot;&gt;bensmindpalace.co.uk&lt;/a&gt;; it’s got my face, some code, and a soundtrack.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://twitter.com/rogue_michael&quot;&gt;Michael&lt;/a&gt; made &lt;a href=&quot;http://michaelblatherwick.co.uk/ben/&quot;&gt;this page&lt;/a&gt;, which transitions from &lt;a href=&quot;https://en.wikipedia.org/wiki/Lorem_ipsum&quot;&gt;lorem-ipsum&lt;/a&gt; to &lt;a href=&quot;https://github.com/peterjwest/lorem_bensum&quot;&gt;lorem-bensum&lt;/a&gt;, then into a picture of my face.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Thanks, guys.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Open inbox</title>
    <link href="https://benjaminbenben.com/2014/07/09/emails/" />
    <updated>2014-07-09T00:00:00Z</updated>
    <id>https://benjaminbenben.com/2014/07/09/emails/</id>
    <content type="html">&lt;p class=&quot;lead&quot;&gt;I&#39;m pretty rubbish at responding to emails - I&#39;ve tried inbox zero a few times but never stuck at it.  I thought being public about the state of my inbox might encourage me to keep on top of things.&lt;/p&gt;
&lt;h3&gt;Home&lt;/h3&gt;
&lt;div data-cr=&quot;email-stats&quot; data-stat=&quot;home&quot; class=&quot;cr email-stats&quot;&gt;&lt;/div&gt;
&lt;h3&gt;Work&lt;/h3&gt;
&lt;div data-cr=&quot;email-stats&quot; data-stat=&quot;work&quot; class=&quot;cr email-stats&quot;&gt;&lt;/div&gt;
&lt;p&gt;(key: orange - unread, yellow - read)&lt;/p&gt;
&lt;p&gt;It&#39;s updated every 30 minutes by a short python script that uses the new gmail api to fetch the inbox counts, then post them at a heroku app.  The heroku app stores the data in Redis.  The server is slightly hacked together, though the source is &lt;a href=&quot;https://github.com/benfoxall/email-analytics&quot;&gt;on github&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I guess you could say that it&#39;s a slight invasion of my privacy - though I think the benefits of having it open far outweigh that.  It forces to be honest about my inbox, helps other people see if I&#39;m making progress, or spot patterns and help me.&lt;/p&gt;
&lt;h3&gt;Hyperlinks&lt;/h3&gt;
&lt;p&gt;If you are doing some more heavy duty time series monitoring, I&#39;d check out &lt;a href=&quot;http://influxdb.com/&quot;&gt;influxDB&lt;/a&gt; - seems like a really powerful tool.&lt;/p&gt;
&lt;p&gt;I couldn&#39;t use it for this data, but &lt;a href=&quot;https://www.npmjs.org/package/redis-timeseries&quot;&gt;redis-timeseries&lt;/a&gt; is a nice node library for storing event counts in redis (like website hits or other events).&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>LastFM to CSV</title>
    <link href="https://benjaminbenben.com/2014/05/29/lastfm-to-csv/" />
    <updated>2014-05-29T00:00:00Z</updated>
    <id>https://benjaminbenben.com/2014/05/29/lastfm-to-csv/</id>
    <content type="html">&lt;p class=&quot;lead&quot;&gt;I made &lt;a href=&quot;http://benjaminbenben.com/lastfm-to-csv/&quot;&gt;lastfm to csv&lt;/a&gt; - a page for downloading lastfm listening data as a csv file.  API requests are made directly from the browser, avoiding the need for any server-side code.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://benjaminbenben.com/lastfm-to-csv/&quot; class=&quot;btn.btn-primary&quot;&gt;give it a shot now&lt;/a&gt; (my username is benjaminf)&lt;/p&gt;
&lt;p&gt;My friend &lt;a href=&quot;https://twitter.com/acotgreave&quot;&gt;Andy&lt;/a&gt; wanted some lastfm listening data for a visualisation project so I wrote him a &lt;a href=&quot;https://gist.github.com/benfoxall/7976631&quot;&gt;ruby script&lt;/a&gt; that uses the &lt;a href=&quot;http://www.last.fm/api/show/user.getRecentTracks&quot;&gt;user.getrecenttracks&lt;/a&gt; method to get the track history for a user.  This worked fine though if someone else wanted to use it - they would need to install ruby, and have a familiarity of the command line.&lt;/p&gt;
&lt;p&gt;I figured it might be easier for people to do this in the browser - so I put together &lt;a href=&quot;http://benjaminbenben.com/lastfm-to-csv/&quot;&gt;lastfm-to-csv&lt;/a&gt;, which lets you enter a username and download a csv file containing all the tracks for a user.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://benjaminbenben.com/lastfm-to-csv/&quot;&gt;&lt;img src=&quot;https://benjaminbenben.com/img/lastfm-to-csv.png&quot; alt=&quot;lastfm-to-csv&quot; class=&quot;img-responsive&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Using the browser&lt;/h2&gt;
&lt;p&gt;Generating a csv of all the tracks requires many requests to the api, these need to be processed and combined together. I decided to do this all from the browser, by using xhr to make requests to the api and storing the processed csv data in a javascript Blob.&lt;/p&gt;
&lt;p&gt;A few libraries that I found useful:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ded/reqwest&quot;&gt;reqwest&lt;/a&gt; - for making xhr calls, nice and lightweight.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/caolan/async&quot;&gt;async&lt;/a&gt; - for organising the calls to the api and processing the results.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/eligrey/FileSaver.js/&quot;&gt;Filesaver.js&lt;/a&gt; - lets you download the resulting Blob objects as a file.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A few things I noticed by doing it this way:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;people have access to their data instantly - no waiting around for a file to be generated on the server before downloading it.&lt;/li&gt;
&lt;li&gt;no servers to keep running - all code runs in the browser&lt;/li&gt;
&lt;li&gt;harder to avoid api limiting - it someone gathers data in several windows, they could get rate limited.&lt;/li&gt;
&lt;li&gt;potential access issues. Last fm gives you access to a nice &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS&quot;&gt;cors&lt;/a&gt; endpoint, though that&#39;s not always the case with other apis.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;Andy blogged about his awesome &lt;a href=&quot;http://gravyanecdote.com/uncategorized/lastfmthesummary/&quot;&gt;last fm visualisations&lt;/a&gt;, you should check them out - turns out that I&#39;m &lt;a href=&quot;http://gravyanecdote.com/uncategorized/last-fm-part-3-obsessions/&quot;&gt;quite obsessive&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Unknown Pleasures</title>
    <link href="https://benjaminbenben.com/2013/10/21/unknown-pleasures/" />
    <updated>2013-10-21T00:00:00Z</updated>
    <id>https://benjaminbenben.com/2013/10/21/unknown-pleasures/</id>
    <content type="html">&lt;p class=&quot;lead&quot;&gt;The artwork for Joy Division&#39;s &lt;a href=&quot;http://en.wikipedia.org/wiki/Unknown_Pleasures&quot;&gt;Unknown Pleasures&lt;/a&gt; album is based on a graph of radio waves from the first identified pulsar - this is a graph of radio waves from the same pulsar, but recorded in 2012.&lt;/p&gt;
&lt;div id=&quot;pulsar&quot; class=&quot;cr&quot; data-cr=&quot;pulsar&quot; data-cr-defer=&quot;&quot;&gt;
  &lt;div id=&quot;pulsar-graph&quot;&gt;&lt;!-- --&gt;&lt;/div&gt;
  &lt;form&gt;
    &lt;label&gt;
      &lt;input id=&quot;pulsar-colouring&quot; type=&quot;checkbox&quot; value=&quot;&quot;&gt;
      Encyclopedia of Astronomy colouring
    &lt;/label&gt;
    &lt;label&gt;
      &lt;input id=&quot;pulsar-transparent&quot; type=&quot;checkbox&quot; value=&quot;&quot;&gt;
      Transparent fill
    &lt;/label&gt;
    &lt;label&gt;
      &lt;input id=&quot;pulsar-scale&quot; type=&quot;checkbox&quot; value=&quot;&quot;&gt;
      &quot;Full scale&quot;
    &lt;/label&gt;
  &lt;/form&gt;
&lt;/div&gt;
&lt;h2&gt;Origins of the Joy Division artwork&lt;/h2&gt;
&lt;p&gt;Stephen Morris (the Joy Division drummer) found this image in the Cambridge Encyclopedia of Astronomy.  It&#39;s a graph showing the regularity of the pulses of &lt;a href=&quot;http://en.wikipedia.org/wiki/PSR_B1919%2B21&quot;&gt;CP 1919 (PSR B1919+21)&lt;/a&gt; - the first radio pulsar discovered (1967).&lt;/p&gt;
&lt;p&gt;Peter Saville took this image and inverted it for the for the cover of the Unknown Pleasures, there&#39;s more information in the video below.&lt;/p&gt;
&lt;iframe src=&quot;https://player.vimeo.com/video/51365288?byline=0&amp;amp;portrait=0&quot; width=&quot;550&quot; height=&quot;309&quot; frameborder=&quot;0&quot; webkitallowfullscreen=&quot;true&quot; mozallowfullscreen=&quot;true&quot; allowfullscreen=&quot;true&quot;&gt;&lt;!----&gt;&lt;/iframe&gt;
&lt;p&gt;&lt;a href=&quot;http://adamcap.com/2011/05/19/history-of-joy-division-unknown-pleasures-album-art/&quot;&gt;This blog post&lt;/a&gt; gives some information about when the graph appeared.&lt;/p&gt;
&lt;h2&gt;Data&lt;/h2&gt;
&lt;p class=&quot;lead&quot;&gt;&lt;strong&gt;Disclaimer: I know almost nothing about pulsars&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The data for the graph above comes from &lt;a href=&quot;http://www.atnf.csiro.au/people/pulsar/index.html?n=Main.Audio&quot;&gt;Pulsar Group CSIRO Astronomy and Space Science&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Recording of the first-discovered pulsar CP1919 (PSR B1919+21) made at the Parkes radio telescope in April 2012. The observing frequency was 732 MHz and bandwidth 64 MHz. The audio is the detected and dedispersed signal modulating white noise.&lt;/p&gt;
&lt;p&gt;Credit: R. N. Manchester, G. Hobbs and J. Khoo, CSIRO Astronomy and Space Science&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;You can listen to it &lt;a href=&quot;http://www.atnf.csiro.au/research/pulsar/audio/CP1919.wav&quot;&gt;here&lt;/a&gt; - you&#39;re listening to a star which is pretty mental.&lt;/p&gt;
&lt;p&gt;I took that wav file and had a look at the data with &lt;a href=&quot;http://sox.sourceforge.net/&quot;&gt;sox&lt;/a&gt; (I eventually pulled out numbers with &lt;a href=&quot;https://github.com/aalin/canvas_waveform&quot;&gt;canvas_waveform&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://benjaminbenben.com/img/un-pl-spectrogram.png&quot;&gt;&lt;img alt=&quot;Spectogram of CP1919 (PSR B1919+21)&quot; src=&quot;https://benjaminbenben.com/img/un-pl-spectrogram.png&quot; class=&quot;img-responsive&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;There was a lot of blank space in the data. I&#39;m not sure if this is because of the way that I extracted it, or the way that it had been pre-processed, or maybe that equiptment has changed over the last 40 years.&lt;/p&gt;
&lt;p&gt;When I managed to plot it, it&#39;s no-where as pretty as the original one.  I&#39;ve just been talking to &lt;a href=&quot;https://twitter.com/intent/user?screen_name=olorton&quot;&gt;@olorton&lt;/a&gt; about why this might be the case - we think it might be because I&#39;m plotting amplitude rather than frequency, he&#39;s going to have a hack tonight to see if he can get something better.  If you have any ideas, please do give me a shout.&lt;/p&gt;
&lt;h2&gt;Visualisation&lt;/h2&gt;
&lt;p&gt;Looking at the original plot, I thought that the peaks obscuring the preceeding ones above meant a loss of information.  Though when I plotted it with a transparency it became a lot harder to read - you don&#39;t know whether lines were going up or down and it looks a bit messy too.  Though I could see that some lines were totally flat, which is cool and I don&#39;t know why.&lt;/p&gt;
&lt;p&gt;Another thing that I realised when I came to plot the graph was that there is a period of silence between each of the peaks (the pulsar has a period of 1.33730s and a 0.04s pulse width) - I&#39;ve added a toggle so that you can see pluses along with the silence.&lt;/p&gt;
&lt;p&gt;Both of these points are good cases for the original visualisation which is to show how periodic the pulsar is (I think).&lt;/p&gt;
&lt;p&gt;Also, this shows 80 cycles of the pulsar - so it covers about 1m47s (I was slightly sad that none of the songs on the album are this length).&lt;/p&gt;
&lt;h2&gt;Other things&lt;/h2&gt;
&lt;p&gt;If you liked listening to the stars, check out this &lt;a href=&quot;http://en.wikipedia.org/wiki/List_of_unexplained_sounds&quot;&gt;list of unexplained sounds&lt;/a&gt; on Wikipedia, they are mostly things in the sea and pretty awesome. I like how the &lt;a href=&quot;http://en.wikipedia.org/wiki/52-Hertz_whale&quot;&gt;52-hertz whale&lt;/a&gt; is described as being &amp;quot;just higher than the lowest note on a tuba&amp;quot;.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Context require</title>
    <link href="https://benjaminbenben.com/2013/10/01/context-require/" />
    <updated>2013-10-01T00:00:00Z</updated>
    <id>https://benjaminbenben.com/2013/10/01/context-require/</id>
    <content type="html">&lt;p class=&quot;lead&quot;&gt;This is how I organise JavaScript assets on this site.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;btn btn-default&quot; href=&quot;https://github.com/benfoxall/context-require&quot;&gt;view code on github&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Motivation&lt;/h3&gt;
&lt;p&gt;When I started this blog, I knew that I wanted to include specific and varied scripts on each post.&lt;/p&gt;
&lt;p&gt;I didn&#39;t want to serve all my js files together in one blob with each page load:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The built js file would get bigger with each post I add&lt;/li&gt;
&lt;li&gt;I wanted the flexibility to use any new library that I came across (didn&#39;t want to think &amp;quot;I&#39;ve already used X, so I&#39;ll just use that&amp;quot;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Approach&lt;/h3&gt;
&lt;p&gt;I use &lt;a href=&quot;http://requirejs.org/&quot;&gt;require.js&lt;/a&gt; to modularise my code.  If I want to make part of the document &lt;em&gt;fancy&lt;/em&gt; - then I define it in a file called &lt;code&gt;fancy.js&lt;/code&gt; like this:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token function&quot;&gt;define&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;jquery&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;element&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;doFancyStuff&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;… the module defines a function that can be applied with a particular dom node.&lt;/p&gt;
&lt;p&gt;Then, in the markup - I specify which module I want to apply to a particular piece of markup:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;cr&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;data-cr&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;fancy&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;RAINBOWS&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;UNICORNS&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I then stitch this together with another require.js module which looks through the page, loads any modules and applies them appropriately.  It looks something like this (I&#39;ve used jQuery here for succinctness):&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;.cr&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;each&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; self &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; requirement &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;cr&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;requirement&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Profit&lt;/h3&gt;
&lt;p&gt;Now I can load only the necessary scripts to display a page; which vary across pages on my blog:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://benjaminbenben.com/2013/04/05/lllocal/&quot;&gt;lllocal&lt;/a&gt; - only loads jQuery and a plugin to thumb between images&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://benjaminbenben.com/2013/04/07/tweet-globe/&quot;&gt;tweet-globe&lt;/a&gt; - will load in a datafile and a vector manipulation library&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://benjaminbenben.com/2013/05/09/wtcss/&quot;&gt;wtcss&lt;/a&gt; - won&#39;t load any extra libraries&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Dogfooding&lt;/h3&gt;
&lt;p&gt;I&#39;ve enjoyed using this approach - it&#39;s made it really easy to add new posts. I&#39;ve felt like I&#39;ve been writing code rather than tweaking and maintaining it.&lt;/p&gt;
&lt;p&gt;It also feels like a good distinction of concerns - by starting with the html/dom I&#39;ve focussed on what I&#39;m trying to enhance with javascript.&lt;/p&gt;
&lt;h3&gt;Only loading scripts for on-screen elements&lt;/h3&gt;
&lt;p&gt;This approach kind of sucked for my homepage though - I&#39;ve got all my posts in full, so every single script would be loaded.&lt;/p&gt;
&lt;p&gt;So I rewrote my script to defer the loading of a module until the related element is on-screen.  It looks something like this (again, jQuery here for brevity):&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// using jquery.inview&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;.cr-defer&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;one&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;inview&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; self &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; requirement &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;cr&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;requirement&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I&#39;ve written a way to display the modules as they are loaded, which you can turn on with the button below (if the module loaded okay!)&lt;/p&gt;
&lt;p class=&quot;cr-defer&quot; data-cr=&quot;cr-debug-toggle&quot;&gt;&lt;!----&gt;&lt;/p&gt;
&lt;p&gt;This should reload the page with a panel to the left which will display:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;cr - the script with loads in the modules for the page&lt;/li&gt;
&lt;li&gt;cr-debug - the module that displays the panel on the left&lt;/li&gt;
&lt;li&gt;ko - knockout, which is used to update the panel&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;as you scroll down the page, you should see more modules loading in as you go past the posts.&lt;/p&gt;
&lt;h3&gt;Limitations / solutions&lt;/h3&gt;
&lt;p&gt;I can use this approach because I&#39;ve got independent bits of content.  Creating larger scale interconnected sites requires a lot more thought and planning. &lt;a href=&quot;https://twitter.com/intent/user?screen_name=addyosmani&quot;&gt;Addy Osami&lt;/a&gt; did a &lt;a href=&quot;http://vimeo.com/40866386&quot;&gt;great talk&lt;/a&gt; on building large scale JS applications at last years jQueryUK. He also has an online book - &lt;a href=&quot;http://addyosmani.com/resources/essentialjsdesignpatterns/book/&quot;&gt;Learning JavaScript Design Patterns&lt;/a&gt; which is worth a read.&lt;/p&gt;
&lt;p&gt;The other limitation of this approach is performance.  Require.js has a great build tool which lets you compile your components into a single file - though this would defeat the purpose of what I was trying to do in the first place.&lt;/p&gt;
&lt;p&gt;The issue isn&#39;t with the size of download, but the waterfall effect that happens when each dependency is loaded (as a module must be loaded before the dependencies can be found).  This (and a solution to this) is described brilliantly in a presentation at last years JSConfEU - &lt;a href=&quot;http://www.youtube.com/watch?v=mGENRKrdoGY&quot;&gt;A novel, efficient approach to JavaScript loading&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Also, if you&#39;re interested in this kind of stuff - have a read of &lt;a href=&quot;https://twitter.com/intent/user?screen_name=SlexAxton&quot;&gt;Alex Sexton&lt;/a&gt;&#39;s blog post about &lt;a href=&quot;http://alexsexton.com/blog/2013/03/deploying-javascript-applications/&quot;&gt;deploying javascript applications&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I have a feeling that this is the kind of problem that people have dealt with or have had ideas about before.  I&#39;d really love to hear what you think - ping me on twitter or &lt;a href=&quot;https://news.ycombinator.com/item?id=6483160&quot;&gt;comment on hacker news&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>The other side of responsive</title>
    <link href="https://benjaminbenben.com/2013/09/20/other-side-of-responsive/" />
    <updated>2013-09-20T00:00:00Z</updated>
    <id>https://benjaminbenben.com/2013/09/20/other-side-of-responsive/</id>
    <content type="html">&lt;iframe width=&quot;100%&quot; height=&quot;166&quot; scrolling=&quot;no&quot; frameborder=&quot;no&quot; src=&quot;https://w.soundcloud.com/player/?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F112467729&amp;amp;color=0088cc&amp;amp;auto_play=false&amp;amp;show_artwork=true&quot;&gt;&lt;!-- --&gt;&lt;/iframe&gt;
&lt;p class=&quot;lead&quot;&gt;Yesterday I gave a talk &quot;The other side of responsive&quot; which was about how responsive web development gives us a great platform for creating interfaces that combine multiple devices. This post explains some of the tech/approaches that I used for it.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;I&#39;m writing this in a car, with the limit of a half charged laptop, so apologies for any mistakes or over-wordiness. Also - for context - my mother (who is driving) is playing Mozart Clarinet Concerto in A really loud, which is awesome.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;The setup&lt;/h2&gt;
&lt;p&gt;My laptop has a node.js server which does two things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Serve the static content of the presentation (written with &lt;a href=&quot;http://lab.hakim.se/reveal-js/#/&quot;&gt;reveal.js&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Host a &lt;a href=&quot;http://binaryjs.com/&quot;&gt;binary.js&lt;/a&gt; server which publishes anything sent to it to any other connected browsers&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;My phone has a 3g connection, and acts as a hotspot for my laptop (I would have used the wifi, but it was a bit shakey on my phone - this worked a lot better)&lt;/p&gt;
&lt;p&gt;There&#39;s a page hosted at &lt;a href=&quot;https://github.com/benfoxall/benfoxall.github.com/blob/master/party/index.html&quot;&gt;benjaminbenben.com/archive/party&lt;/a&gt; which has the markup for each of the phone slides, and some JavaScript to link it up to my talk.  I took some effort to make this as performant as possible (from accessing the web server with your phone, the &amp;quot;hello&amp;quot; is able to display within the first network roundtrip!); so I was glad to hear &lt;a href=&quot;https://twitter.com/intent/user?screen_name=drewm&quot;&gt;Drew&lt;/a&gt; talk about web performance, it&#39;s such an important aspect of working with the web.&lt;/p&gt;
&lt;p&gt;I used &lt;a href=&quot;http://www.pubnub.com/&quot;&gt;PubNub&lt;/a&gt; to communicate with the devices in the room.  I had two channels, one to give the status of the slides and another for devices to publish information about themselves and forward touch events when we &amp;quot;went collaborative&amp;quot;.  The publish / subscribe style worked brilliantly for this - all devices would publish and the slide deck would be the only subscriber, and the other way round for the slide states.  PubNub has a few features which were really useful for this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;multiplexing - this meant that your device only needed one connection for both of the channels.&lt;/li&gt;
&lt;li&gt;windowing - this option let my slides recieve messages in 500ms batches, which fixes the number of requests that my laptop would make, regardless of how many people connected.&lt;/li&gt;
&lt;li&gt;backfill - if you were to refresh a device, all the &#39;hot&#39; messages would be sent down, so the browser would be able to replay them all and catch up with all the other devices; this also allows people to join in half way through.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;The talk&lt;/h2&gt;
&lt;p&gt;My first slide was the short url for the &lt;a href=&quot;http://benjaminbenben.com/archive/party&quot;&gt;benjaminbenben.com/party&lt;/a&gt; with a counter below it.  When someone loads the page, there is a script that:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Generates and locks down a uuid for the user, so that reloading the page won&#39;t create more devices&lt;/li&gt;
&lt;li&gt;Uses modernizr to find the capabilities of the device&lt;/li&gt;
&lt;li&gt;Subscribes to the slide deck messages&lt;/li&gt;
&lt;li&gt;Publishes a &#39;hello&#39; message&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The hello message looks something like this:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;message &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;uuid&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;some-long-random-id&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;hello&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;features&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;appcache webgl webrtc ...&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;pixels&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1234567&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;innerC&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;red&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// random colours&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;outerC&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;blue&#39;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// for the circles&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The counter on the slide deck increments when it gets one of these messages, the features and colours are stored - so from this point I know that I can display the capabilities chart (which is nice).&lt;/p&gt;
&lt;p&gt;I then continue to the title slide and wave my hands about a bit.  I&#39;ve got the slides open on my phone too, when I go to the next slide I use binary.js to broadcast a message to all other browsers, which proceed to that slide.&lt;/p&gt;
&lt;p&gt;The next slide is a file input field, which looks like this:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;input type&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;file&quot;&lt;/span&gt; id&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;photo&quot;&lt;/span&gt; accept&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;image/*&quot;&lt;/span&gt; capture&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;camera&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The capture attribute means that it fires up the camera on my phone rather than asking where I want to get my file from.&lt;/p&gt;
&lt;p&gt;When I take and accept the picture of the geek night, it is streamed with binary.js to all other connected slide decks - it&#39;s based on &lt;a href=&quot;https://github.com/binaryjs/binaryjs/tree/master/examples/imageshare&quot;&gt;this binary.js example&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;img-responsive&quot; alt=&quot;MKGN&quot; src=&quot;https://benjaminbenben.com/img/mkgn.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;Once the image is in the slide deck, this sequence of things happens:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;It&#39;s displayed on the presentation&lt;/li&gt;
&lt;li&gt;It starts &lt;a href=&quot;http://aws.amazon.com/articles/1434&quot;&gt;uploading to s3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The s3 url is published to all devices&lt;/li&gt;
&lt;li&gt;It&#39;s base64 encoded and sent to twitter (using &lt;a href=&quot;https://github.com/jublonet/codebird-js&quot;&gt;codebird&lt;/a&gt;, which gives you a proxy to the twitter api for client side apps)&lt;/li&gt;
&lt;li&gt;The twitter &lt;a href=&quot;https://dev.twitter.com/docs/api/1/get/statuses/oembed&quot;&gt;embed html requested&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The twitter embed html is appended to the presentation is published to all devices&lt;/li&gt;
&lt;li&gt;The twitter widget script is added to render the tweet (this also happens on the devices)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So, at this point - the the last slide is rendered (on the devices as well). Also, the devices are displaying the picture on screen (I forgot to say that).&lt;/p&gt;
&lt;p&gt;The next slide is the interactive slide of circles representing each device, this is an svg generated with d3. There is a basic animation loop which applies and dampens the speed of a circle and repels it from any nearby circles, this was running for the last couple of slides - so they&#39;ve kind of organised themselves into a nice pattern.&lt;/p&gt;
&lt;p&gt;D3 is fantastic, the enter/exit/transition approach is so intuitive for dynamic data - if someone joined at this point, a circle would pop onto the page and everything would just carry on.&lt;/p&gt;
&lt;p&gt;By this point a coinciding circle was displayed on each device, when anyone pressed their circle, the x/y coordinates were published with PubNub. When received by the presentation, the x/y speed on the underlying data is incremented accordingly - d3 does the rest.&lt;/p&gt;
&lt;p&gt;Moving to the table of capabilities is just stopping the animation loop, then transitioning the elements to new positions and appending new elements for each capability. I &amp;lt;3 D3.&lt;/p&gt;
&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p&gt;&lt;a href=&quot;https://twitter.com/benjaminbenben&quot;&gt;@benjaminbenben&lt;/a&gt; blowing minds with real time analysis of the audience&amp;#39;s devices &lt;a href=&quot;https://twitter.com/MKGeekNight&quot;&gt;@mkgeeknight&lt;/a&gt; &lt;a href=&quot;https://twitter.com/search?q=%23mkgn&amp;amp;src=hash&quot;&gt;#mkgn&lt;/a&gt; &lt;a href=&quot;http://t.co/e8bohM3iaL&quot;&gt;pic.twitter.com/e8bohM3iaL&lt;/a&gt;&lt;/p&gt;&amp;mdash; Al Power (@alpower) &lt;a href=&quot;https://twitter.com/alpower/statuses/380800187490254849&quot;&gt;September 19, 2013&lt;/a&gt;&lt;/blockquote&gt;
&lt;p&gt;I then used 3 of &lt;a href=&quot;https://twitter.com/intent/user?screen_name=brad_frost&quot;&gt;Brad Frosts&lt;/a&gt; slides from his blog post &amp;quot;&lt;a href=&quot;http://bradfrostweb.com/blog/post/this-is-the-web/&quot;&gt;this is the web&lt;/a&gt;&amp;quot;.  Each slide sends a message out to all the devices which keep in sync.  The middle slide (This is the web) just displayed the word &amp;quot;web&amp;quot; on the devices rather than the image, to show that your device is part of that.&lt;/p&gt;
&lt;p&gt;The last slide was a quote by Igor Stravinsky about the freedom of constraints. The slide only showed part of the quote (highlighted below) - the full quote was displayed on each of the devices.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;My freedom thus consists in my moving about within the narrow frame that I have assigned to myself for each one of my undertakings.  I shall go even further: &lt;strong&gt;my freedom will be so much the greater and more meaningful the more narrowly I limit my field of action and the more I surround myself with obstacles&lt;/strong&gt;. Whatever diminishes constraint diminishes strength. The more constraints one imposes, the more one frees oneself of the claims that shackle the spirit.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I like that quote.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Graphing links</title>
    <link href="https://benjaminbenben.com/2013/08/08/link-areas/" />
    <updated>2013-08-08T00:00:00Z</updated>
    <id>https://benjaminbenben.com/2013/08/08/link-areas/</id>
    <content type="html">&lt;p class=&quot;lead&quot;&gt;This is an example of displaying content pulled from a PhantomJS webservice&lt;/p&gt;
&lt;p&gt;I used this example when I talked about &amp;quot;serving websites to websites with PhantomJS&amp;quot; at this months Oxford Geek Nights&lt;/p&gt;
&lt;h2&gt;Link Areas&lt;/h2&gt;
&lt;p&gt;With phantomjs you are able to access more than just the HTML/DOM of a page - how the page is eventually rendered in a browser.  In this example - we can pull out all the links of a page and find out what area (in pixels) they consume.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;img-responsive&quot; alt=&quot;link areas on oxford geek nights&quot; src=&quot;https://benjaminbenben.com/img/link-areas.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;Using this script we can get a map of the links to the element areas, which looks something like this:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token string-property property&quot;&gt;&quot;http://benjaminbenben.com/&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;6534&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token string-property property&quot;&gt;&quot;http://bit.ly/Pesy75&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10640&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token string-property property&quot;&gt;&quot;http://lanyrd.com/cqfdw&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;18012&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token string-property property&quot;&gt;&quot;http://mynameismartin.com/&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;8646&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token string-property property&quot;&gt;&quot;http://oxford.geeknights.net/&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;84000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token string-property property&quot;&gt;&quot;http://oxford.geeknights.net/ogn29&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;52052&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token string-property property&quot;&gt;&quot;http://oxford.geeknights.net/ogn30&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;52052&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token string-property property&quot;&gt;&quot;http://oxford.geeknights.net/ogn31&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;52052&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token string-property property&quot;&gt;&quot;http://oxford.geeknights.net/volunteer.html&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;29520&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token string-property property&quot;&gt;&quot;http://torchbox.com/&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;4760&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token string-property property&quot;&gt;&quot;http://twitter.com/oxfordgeeks&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;20112&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token string-property property&quot;&gt;&quot;http://www.marianamota.com/&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;33128&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token string-property property&quot;&gt;&quot;http://www.torchbox.com/&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3360&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token string-property property&quot;&gt;&quot;https://github.com/LuRsT&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;8580&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Graphing the data&lt;/h2&gt;
&lt;p&gt;We can now pull in this data with AJAX and render it on the page using d3 (the force directed graph layout)&lt;/p&gt;
&lt;div class=&quot;cr&quot; data-cr=&quot;link-areas&quot; data-cr-defer=&quot;&quot;&gt;
	&lt;form class=&quot;form-inline&quot; action=&quot;http://ogn32-link-areas.herokuapp.com&quot;&gt;
		&lt;input type=&quot;url&quot; name=&quot;url&quot; class=&quot;visurl form-control&quot; placeholder=&quot;Enter a URL&quot; required=&quot;required&quot;&gt;
		&lt;input type=&quot;submit&quot; class=&quot;btn btn-primary&quot; value=&quot;add&quot;&gt;
		&lt;button class=&quot;btn btn-default&quot;&gt;clear&lt;/button&gt;
	&lt;/form&gt;
	&lt;div class=&quot;vis&quot;&gt;&lt;!----&gt;&lt;/div&gt;
	&lt;p&gt;&lt;small&gt;initially populated with this blog post, double click to check one of the urls.&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;h4&gt;examples&lt;/h4&gt;
&lt;ul class=&quot;examples unstyled&quot;&gt;
&lt;li&gt;
&lt;a class=&quot;btn btn-default btn-mini&quot; href=&quot;http://oxford.geeknights.net/&quot;&gt;OGN#32&lt;/a&gt;
&lt;a class=&quot;btn btn-default&quot; href=&quot;http://benjaminbenben.com/2013/07/28/phantomjs-webserver/&quot;&gt;blog post (about ogn32 &amp;amp; PhantomJS)&lt;/a&gt;
&lt;a class=&quot;btn btn-default&quot; href=&quot;http://phantomjs.org/&quot;&gt;PhantomJS site&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a class=&quot;btn btn-default&quot; href=&quot;http://getbootstrap.com/&quot;&gt;bootstrap 3 docs&lt;/a&gt;
&lt;a class=&quot;btn btn-default&quot; href=&quot;http://getbootstrap.com/2.3.2/&quot;&gt;bootstrap 2.3.2 docs&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;
&lt;/div&gt;
</content>
  </entry>
  <entry>
    <title>PhantomJS WebServer</title>
    <link href="https://benjaminbenben.com/2013/07/28/phantomjs-webserver/" />
    <updated>2013-07-28T00:00:00Z</updated>
    <id>https://benjaminbenben.com/2013/07/28/phantomjs-webserver/</id>
    <content type="html">&lt;p class=&quot;lead&quot;&gt;The &lt;a href=&quot;http://phantomjs.org/&quot;&gt;PhantomJS&lt;/a&gt; WebServer module lets you create self contained web applications that are easy to deploy to heroku using the PhantomJS build pack.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;I&#39;ll be talking about this at &lt;a href=&quot;http://oxford.geeknights.net&quot;&gt;Oxford geek nights&lt;/a&gt; on the &lt;a href=&quot;http://lanyrd.com/2013/ogn32/&quot;&gt;7th of August&lt;/a&gt; - come along if you&#39;re in the area.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;(tl;dr - deployed example &lt;a href=&quot;http://quiet-lowlands-5118.herokuapp.com/&quot;&gt;here&lt;/a&gt; &amp;amp; more involved app &lt;a href=&quot;http://phantomjs-webserver-example.herokuapp.com/&quot;&gt;here&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Let&#39;s start with a base PhantomJS script - this loads the Oxfordshire &lt;a href=&quot;http://lanyrd.com/places/oxfordshire/&quot;&gt;lanyrd page&lt;/a&gt; and outputs the names of any upcoming events:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; page &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;WebPage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

page&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;http://lanyrd.com/places/oxfordshire/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; events &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; page&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;evaluate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;.vevent .summary&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;* &#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;innerText
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;&#92;n&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Upcoming Events in Oxfordshire:&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;events&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  phantom&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This script can be run with &lt;code&gt;phantomjs example.js&lt;/code&gt; and it will print the names of all upcoming events in the terminal - something like this:&lt;/p&gt;
&lt;pre&gt;Upcoming Events in Oxfordshire:
* Oxford Geek Night 32
* WitneyMeets
* XML Summer School 2013
* Sterling Geo Intergraph ERDAS UK UGM
* All Your Base Conference 2013
* jQuery UK 2014
* World Humanist Congress 2014&lt;/pre&gt;
&lt;p&gt;…super cool.  Have a look at the &lt;a href=&quot;https://github.com/ariya/phantomjs/wiki/Quick-Start&quot;&gt;quick start guide&lt;/a&gt; on the &lt;a href=&quot;https://github.com/ariya/phantomjs/wiki&quot;&gt;PhantomJS wiki&lt;/a&gt; to find out how this works and what other things are possible.&lt;/p&gt;
&lt;h3&gt;Using the webserver module&lt;/h3&gt;
&lt;p&gt;To expose this script with the &lt;a href=&quot;https://github.com/ariya/phantomjs/wiki/API-Reference-WebServer&quot;&gt;webserver module&lt;/a&gt;, you have to add a few things:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// import the webserver module, and create a server&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; server &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;webserver&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// start a server on port 8080 and register a request listener&lt;/span&gt;
server&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;listen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;8080&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; response&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; page &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;WebPage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  page&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;http://lanyrd.com/places/oxfordshire/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; events &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; page&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;evaluate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;.vevent .summary&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;* &#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;innerText
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;&#92;n&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Rather than console logging, write the data back as a&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// response to the user&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;//&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// console.log(&#39;Upcoming Events in Oxfordshire:&#39;);&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// console.log(events);&lt;/span&gt;

    response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;statusCode &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Upcoming Events in Oxfordshire:&#92;n&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;events&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// We want to keep phantom open for more requests, so we&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// don&#39;t exit the process. Instead we close the page to&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// free the associated memory heap&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;//&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// phantom.exit();&lt;/span&gt;

    page&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This can be run in the same way as the previous script - &lt;code&gt;phantomjs example.js&lt;/code&gt; - then when you visit &lt;a href=&quot;http://localhost:8080&quot;&gt;localhost:8080&lt;/a&gt;, you should see the list of events in your browser.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;img-responsive&quot; src=&quot;https://benjaminbenben.com/img/phantomjs-lanyrd.png&quot; alt=&quot;localhost:8080 - list of events from lanyrd&quot;&gt;&lt;/p&gt;
&lt;p&gt;With phantomjs, you&#39;re not limited to sending plain text back to the client - you can &lt;a href=&quot;https://github.com/ariya/phantomjs/wiki/API-Reference-WebPage#wiki-webpage-render&quot;&gt;render images&lt;/a&gt; of the webpage and send that back (either by reading the file back with the &lt;a href=&quot;https://github.com/ariya/phantomjs/wiki/API-Reference-FileSystem&quot;&gt;File System Module&lt;/a&gt;, or using &lt;a href=&quot;https://github.com/ariya/phantomjs/wiki/API-Reference-WebPage#renderbase64format&quot;&gt;base 64&lt;/a&gt; to send back an embeddable data-uri).&lt;/p&gt;
&lt;h3&gt;Deploying&lt;/h3&gt;
&lt;p&gt;There is a &lt;a href=&quot;https://github.com/stomita/heroku-buildpack-phantomjs&quot;&gt;PhantomJS Buildpack&lt;/a&gt; for heroku which makes deploying lovely.&lt;/p&gt;
&lt;p&gt;To get your app ready for deployment you have to do a few things:&lt;/p&gt;
&lt;h4&gt;Set the port based on environment variable &lt;code&gt;PORT&lt;/code&gt;&lt;/h4&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; port &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;system&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;PORT&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8080&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// default back to 8080&lt;/span&gt;
server&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;listen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;port&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; response&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Add a file named &lt;code&gt;Procfile&lt;/code&gt; containing the command to spin it up:&lt;/h4&gt;
&lt;pre&gt;web: phantomjs example.js&lt;/pre&gt;
&lt;h4&gt;Commit your files to git then create a heroku app with the build pack&lt;/h4&gt;
&lt;pre&gt;&lt;strong&gt;heroku create --stack cedar --buildpack http://github.com/stomita/heroku-buildpack-phantomjs.git&lt;/strong&gt;
&lt;div class=&quot;bumf&quot;&gt;Creating quiet-lowlands-5118... done, stack is cedar
BUILDPACK_URL=http://github.com/stomita/heroku-buildpack-phantomjs.git
http://quiet-lowlands-5118.herokuapp.com/ | git@heroku.com:quiet-lowlands-5118.git
Git remote heroku added&lt;/div&gt;&lt;/pre&gt;
&lt;h4&gt;Push your code up to heroku&lt;/h4&gt;
&lt;pre&gt;&lt;strong&gt;git push heroku master&lt;/strong&gt;
&lt;div class=&quot;bumf&quot;&gt;Counting objects: 10, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (7/7), done.
Writing objects: 100% (10/10), 1.34 KiB, done.
Total 10 (delta 2), reused 0 (delta 0)

-----&gt; Fetching custom git buildpack... done
-----&gt; PhantomJS app detected
-----&gt; Fetching PhantomJS 1.9.0 binaries at http://stomita-buildpack-phantomjs.s3.amazonaws.com/buildpack-phantomjs-1.9.0.tar.gz
-----&gt; Extracting PhantomJS 1.9.0 binaries to /tmp/build_2idj4c8tadrpx/vendor/phantomjs
-----&gt; Discovering process types
       Procfile declares types     -&gt; web
       Default types for PhantomJS -&gt; console

-----&gt; Compiled slug size: 15.5MB
-----&gt; Launching... done, v5
       http://quiet-lowlands-5118.herokuapp.com deployed to Heroku

To git@heroku.com:quiet-lowlands-5118.git
 * [new branch]      master -&gt; master&lt;/div&gt;
&lt;/pre&gt;
&lt;p&gt;The example app should now be available on the reported url (in this case: &lt;a href=&quot;http://quiet-lowlands-5118.herokuapp.com&quot;&gt;http://quiet-lowlands-5118.herokuapp.com&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;btn btn-primary btn&quot; href=&quot;http://quiet-lowlands-5118.herokuapp.com&quot;&gt;View Deployed Example Site&lt;/a&gt; &lt;a class=&quot;btn btn-default&quot; href=&quot;https://github.com/benfoxall/phantomjs-oxfordshire-events&quot;&gt;GitHub Source&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;A more involved example&lt;/h2&gt;
&lt;p&gt;I&#39;ve put together a &lt;a href=&quot;https://github.com/benfoxall/phantomjs-webserver-example&quot;&gt;more complex&lt;/a&gt; version of this style of app - it allows you to specify any webpage, renders a screenshot and returns some information about the page (a list of links).&lt;/p&gt;
&lt;p&gt;It also serves a static page with a form to submit the requests to the app.  It&#39;s deployed to &lt;a href=&quot;http://phantomjs-webserver-example.herokuapp.com/&quot;&gt;phantomjs-webserver-example.herokuapp.com&lt;/a&gt; and the source code is &lt;a href=&quot;https://github.com/benfoxall/phantomjs-webserver-example&quot;&gt;on github&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I&#39;ve tried to make it an easy project to modify for your own use - so fork away and have a hack!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://phantomjs-webserver-example.herokuapp.com/&quot;&gt;&lt;img class=&quot;img-responsive&quot; src=&quot;https://benjaminbenben.com/img/phantomjs-more.png&quot; alt=&quot;screenshot of example code&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;btn btn-primary btn&quot; href=&quot;http://phantomjs-webserver-example.herokuapp.com&quot;&gt;View Demo&lt;/a&gt; &lt;a class=&quot;btn btn-default&quot; href=&quot;https://github.com/benfoxall/phantomjs-webserver-example&quot;&gt;GitHub Source&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;A few issues / gotchas&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Mongoose (the embedded server) doesn&#39;t parse the POST parameters with the default jQuery &lt;code&gt;contentType&lt;/code&gt; header &#39;application/x-www-form-urlencoded; charset=UTF-8&#39;;  I had to &lt;a href=&quot;https://github.com/benfoxall/phantomjs-webserver-example/blob/master/index.html#L52&quot;&gt;drop the charset&lt;/a&gt; and it seemed to work okay.&lt;/li&gt;
&lt;li&gt;Firefox has trouble parsing large data-uri strings in json objects, so I&#39;ve split the image and json on separate lines and decode them when the request comes back (unfortunately Firefox fails to add the xhr header that fixes the mongoose error)&lt;/li&gt;
&lt;li&gt;GET parameters aren&#39;t parsed.  I&#39;d much sooner use a GET request for this app, as there&#39;s not any state change and it would allow the responses to be cached.  In &lt;a href=&quot;http://css.benjaminbenben.com&quot;&gt;wtcss&lt;/a&gt; I &lt;a href=&quot;https://github.com/benfoxall/wtcss/blob/master/app.js#L59-L61&quot;&gt;fudged&lt;/a&gt; this parsing.&lt;/li&gt;
&lt;li&gt;Sometimes the page render returns a blank image, especially when on heroku and under stress. This is a &lt;a href=&quot;https://groups.google.com/forum/#!searchin/phantomjs/blank/phantomjs/7XIaNEELuuo/b2jH1B_DJP0J&quot;&gt;known issue&lt;/a&gt; - a work around is to &lt;a href=&quot;https://github.com/benfoxall/phantomjs-webserver-example/blob/master/server.js#L61-L67&quot;&gt;wrap the .render in a setTimeout&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Shaker.io</title>
    <link href="https://benjaminbenben.com/2013/07/01/shaker/" />
    <updated>2013-07-01T00:00:00Z</updated>
    <id>https://benjaminbenben.com/2013/07/01/shaker/</id>
    <content type="html">&lt;p class=&quot;lead&quot;&gt;For a couple of releases now - it&#39;s been possible to build a &lt;a href=&quot;https://github.com/jquery/jquery#how-to-build-your-own-jquery&quot;&gt;customised version of jQuery&lt;/a&gt;.  I felt that one of the barriers for using your own version was finding which modules your site actually uses - so I started working on &lt;a href=&quot;http://shaker.io&quot;&gt;shaker.io&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://shaker.io&quot;&gt;&lt;img class=&quot;img-responsive&quot; src=&quot;https://benjaminbenben.com/img/shaker.png&quot; alt=&quot;shaker.io&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://shaker.io&quot;&gt;Shaker.io&lt;/a&gt; is a tool for finding which modules of jQuery you&#39;re using - it does this by providing an instrumented version of the library which tracks which functions you use.&lt;/p&gt;
&lt;h3&gt;Transport&lt;/h3&gt;
&lt;p&gt;Once the script has tracked which modules have been used, the data is shared with the main page where the list of your dependencies can be updated.  Eventually we&#39;ll add a means of sending events between devices (so you can test on a phone, and see the results on a development machine).&lt;/p&gt;
&lt;figure&gt;
	&lt;img class=&quot;img-responsive&quot; src=&quot;https://benjaminbenben.com/img/shaker-transport.png&quot;&gt;
	&lt;figcaption&gt;
		your custom domain is able to share data with shaker.io by embedding a hidden iframe which can share messages with the main window using storage events. See &lt;a href=&quot;http://benjaminbenben.com/2013/04/24/cross-window-communication-1/&quot;&gt;my blog post&lt;/a&gt; for more on those.
	&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3&gt;Early days&lt;/h3&gt;
&lt;p&gt;There&#39;s a lot I want to do with this tool.  I started with the goal of reducing the number of jQuery Mobile plugins I was using on a page (jQuery Mobile has a great &lt;a href=&quot;http://jquerymobile.com/download-builder/&quot;&gt;download builder&lt;/a&gt;), though as I&#39;ve been hacking about with the idea, it feels like it could do a lot more.&lt;/p&gt;
&lt;h3&gt;Openness&lt;/h3&gt;
&lt;p&gt;I&#39;ve recently been working on &lt;a href=&quot;http://certificates.theodi.org&quot;&gt;a project&lt;/a&gt; with the &lt;a href=&quot;http://theodi.org&quot;&gt;Open Data Institute&lt;/a&gt;. One of the (many) things I&#39;ve enjoyed is the open development; working in the public does seem awkward/hard at first,  though I found myself writing better code,  getting useful feedback, and being able to collaborate much more easily.&lt;/p&gt;
&lt;p&gt;With &lt;a href=&quot;http://shaker.io&quot;&gt;shaker.io&lt;/a&gt; - I&#39;m going to make an effort to make development as transparent and open as possible.  My hope is that people will be able to get involved with discussions on issues &amp;amp; pull requests. My dream is that people can get involved with improving the tool and adding functionality that I didn&#39;t think of.&lt;/p&gt;
&lt;p&gt;So far I&#39;ve been trying to make the code as friendly and accessible as possible (no obscure templating languages, no fancy asset processing).  &lt;a href=&quot;https://www.nodejitsu.com/&quot;&gt;Nodejitsu&lt;/a&gt; have provided the hosting under their &lt;a href=&quot;http://opensource.nodejitsu.com/&quot;&gt;&amp;quot;free for open source&amp;quot;&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;White October&lt;/h3&gt;
&lt;p&gt;One of the things I&#39;m most excited about is that &lt;a href=&quot;http://whiteoctober.co.uk&quot;&gt;White October&lt;/a&gt; (my employer) will be putting some time toward this project as part of an ongoing crusade of being totally awesome.&lt;/p&gt;
&lt;p&gt;This week some of us will be looking at the project from a development, ux and design point of view. We&#39;ll be throwing around a lot of ideas and feeding them into the site, so do keep an eye on the project and feel free to jump in on discussions or pull requests.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You can find the project at &lt;a href=&quot;http://shaker.io&quot;&gt;http://shaker.io&lt;/a&gt; and on github under &lt;a href=&quot;http://github.com/benfoxall/shaker&quot;&gt;benfoxall/shaker&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>CSS matches</title>
    <link href="https://benjaminbenben.com/2013/05/09/wtcss/" />
    <updated>2013-05-09T00:00:00Z</updated>
    <id>https://benjaminbenben.com/2013/05/09/wtcss/</id>
    <content type="html">&lt;p&gt;&lt;a href=&quot;http://css.benjaminbenben.com/v1?url=http%3A%2F%2Fgoogle.com&quot;&gt;&lt;img class=&quot;img-responsive&quot; src=&quot;https://benjaminbenben.com/img/wtcss-google.png&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;lead&quot;&gt;I was working with a large css codebase and wanted to see if our rules were becoming more specific as the css source grew, so I built &lt;a href=&quot;http://css.benjaminbenben.com&quot;&gt;css.benjaminbenben.com&lt;/a&gt; to look at how css rules are applied to a page.&lt;/p&gt;
&lt;h3&gt;Active rules&lt;/h3&gt;
&lt;img class=&quot;img-responsive&quot; src=&quot;https://benjaminbenben.com/img/wtcss-active.png&quot;&gt;
&lt;p&gt;This shows how many of the selectors are being used on a page, you can toggle to show only the active ones.&lt;/p&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;The &#39;-&#39; link on the bottom right scales the rules so that they fit the height of the window.  This is to show the how the impact changes as rules are added to the css.&lt;/p&gt;
&lt;p&gt;An example (with notes) of the &lt;a href=&quot;http://css.benjaminbenben.com/v1?url=http%3A%2F%2Fjsoxford.com%2F&quot;&gt;jsOxford&lt;/a&gt; site is below:&lt;/p&gt;
&lt;img class=&quot;img-responsive&quot; src=&quot;https://benjaminbenben.com/img/wtcss-over.png&quot;&gt;
&lt;p&gt;### How it works&lt;/p&gt;
&lt;p&gt;The main part of this is a &lt;a href=&quot;http://phantomjs.org/&quot;&gt;PhantomJS&lt;/a&gt; script which&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;loads the page&lt;/li&gt;
&lt;li&gt;extracts all stylesheet rules&lt;/li&gt;
&lt;li&gt;finds matching elements for each rule and gets the positions of them&lt;/li&gt;
&lt;li&gt;takes a screenshot&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;All this is sent back to the client in a json object (including the image as a data-uri).&lt;/p&gt;
&lt;p&gt;The source code is now online at &lt;a href=&quot;https://github.com/benfoxall/wtcss&quot;&gt;github.com/benfoxall/wtcss&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Example pages&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://css.benjaminbenben.com/v1?url=http%3A%2F%2Fgoogle.com&quot;&gt;google.com&lt;/a&gt; - some styled elements are offscreen&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://css.benjaminbenben.com/v1?url=https%3A%2F%2Fnews.ycombinator.com%2F&quot;&gt;hacker news&lt;/a&gt; - only 31 css selectors!&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://css.benjaminbenben.com/v1?url=http%3A%2F%2Ffacebook.com&quot;&gt;facebook&lt;/a&gt; - only 5% of rules match on landing page&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://css.benjaminbenben.com/v1?url=http%3A%2F%2Fcss.benjaminbenben.com%2F&quot;&gt;css.benjaminbenben.com&lt;/a&gt; - yup, you can do that&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://css.benjaminbenben.com/v1?url=http%3A%2F%2Fwhiteoctober.co.uk&quot;&gt;white october&lt;/a&gt; - we used a custom bootstrap build, though you can see the gaps in the scaffolding sizes we didn&#39;t use&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://css.benjaminbenben.com/v1?url=http%3A%2F%2Fjsoxford.com%2F&quot;&gt;jsoxford&lt;/a&gt; - you can see the rules at the bottom that we added to target specific elements&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Cross window communication</title>
    <link href="https://benjaminbenben.com/2013/04/24/cross-window-communication-1/" />
    <updated>2013-04-24T00:00:00Z</updated>
    <id>https://benjaminbenben.com/2013/04/24/cross-window-communication-1/</id>
    <content type="html">&lt;p class=&quot;lead&quot;&gt;I was part of the &quot;Rising Stars&quot; track at the jQuery UK conference this year where I talked about sending messages between browser windows.  This post covers the first half of my talk - sending events between local windows.&lt;/p&gt;
&lt;!-- _note, I&#39;ve not taken much care to make these cross-browser._ --&gt;
&lt;p&gt;My slides are now &lt;a href=&quot;https://benjaminbenben.com/archive/winwin&quot;&gt;online&lt;/a&gt;, though they are more prompts for me to talk, rather than being full of information.  The demos wouldn&#39;t really work with it being publicly accessible, so I&#39;m going to cover each of the techniques I mentioned on this blog.&lt;/p&gt;
&lt;p&gt;The websockets/binaryJS/webRTC things are on the way - just working on getting the server side part hosted nicely.&lt;/p&gt;
&lt;h3&gt;postMessage&lt;/h3&gt;
&lt;p&gt;When you have a window that you can reference from with js - either by getting an iframe from the DOM, or as returned by window.open() - you can use postMessage to communicate with that window (crucially, even if that window has a different origin).&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Send messages from parent window&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; win &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;http://benjaminbenben.com/pink.html&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;width=200&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;onselectionchange&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	win&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;postMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getSelection&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;*&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// (on the target window) listen for messages&lt;/span&gt;
window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;message&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	echo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;textContent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;&lt;a href=&quot;https://benjaminbenben.com/2013/04/24/cross-window-communication-1/#demo1&quot;&gt;&amp;gt;demo&lt;/a&gt; &lt;small&gt;opens a window and sends it the text selection from this page&lt;/small&gt;&lt;/h4&gt;
&lt;p&gt;For more information about postMessage - check out the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/DOM/window.postMessage&quot;&gt;entry on MDN&lt;/a&gt; and on &lt;a href=&quot;http://ejohn.org/blog/postmessage-api-changes/&quot;&gt;John Resigs blog post&lt;/a&gt; about it.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;Storage Events&lt;/h3&gt;
&lt;p&gt;When you aren&#39;t able to access a window directly,  but it shares the same origin - you can use storage events to synchronise data between windows.&lt;/p&gt;
&lt;p&gt;A storage event is fired when another window changes the localStorage for that page.  By listening to these events - you can keep objects in sync across windows.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// listen for changes from other windows&lt;/span&gt;
window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;storage&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;key &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;example&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;#el&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;css&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;newValue&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// update a local element and notify other windows of the change&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;#el&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;css&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token literal-property property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;red&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
localStorage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;example&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;{color:&quot;red&quot;}&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A nice side effect of this is that you have the state of an element persisted in localStorage, so you could render that on page load.  See &lt;a href=&quot;https://gist.github.com/benfoxall/5477514&quot;&gt;this gist&lt;/a&gt; for a general way of doing this.&lt;/p&gt;
&lt;p&gt;This approach can become particularly interesting when the data being synced is displayed in different ways in different windows - in my talk I showed how the reveal.js slide deck could be viewed in both overview and normal views at the same time (see &lt;a href=&quot;https://gist.github.com/benfoxall/5477620&quot;&gt;this gist&lt;/a&gt; to see how that can be implemented).&lt;/p&gt;
&lt;h4&gt;demo &lt;small&gt;move your mouse over the area below, any other windows open on this page will update&lt;/small&gt;&lt;/h4&gt;
&lt;div id=&quot;demo2&quot;&gt;&lt;!----&gt;&lt;/div&gt;
</content>
  </entry>
  <entry>
    <title>Image processing + web workers</title>
    <link href="https://benjaminbenben.com/2013/04/14/webworker-qr/" />
    <updated>2013-04-14T00:00:00Z</updated>
    <id>https://benjaminbenben.com/2013/04/14/webworker-qr/</id>
    <content type="html">&lt;h3&gt;tl;dr - examples:&lt;/h3&gt;
&lt;h3&gt;&lt;a href=&quot;javascript:window.open(&#39;/qr-worker/web-worker.html&#39;,&#39;scanner&#39;,&#39;width=700,height=600&#39;);&quot;&gt;&amp;gt;with web worker&lt;/a&gt; &lt;small&gt;(should be smoother)&lt;/small&gt;&lt;/h3&gt;
&lt;h3&gt;&lt;a href=&quot;javascript:window.open(&#39;/qr-worker/inline.html&#39;,&#39;scanner&#39;,&#39;width=700,height=600&#39;);&quot;&gt;&amp;gt;without web worker&lt;/a&gt;&lt;/h3&gt;
&lt;hr&gt;
&lt;p class=&quot;lead&quot;&gt;Web workers let you to take JavaScript execution off the main UI thread - which can be really useful if you are doing complex things with video&lt;/p&gt;
&lt;p&gt;I came across a javascript &lt;a href=&quot;https://github.com/LazarSoft/jsqrcode&quot;&gt;qr-code reader&lt;/a&gt; a few days ago.  When I started using it to scan from a getUserMedia stream - it worked fine, but the extra processing was blocking the ui, which was particularly noticable when you&#39;re displaying the video.&lt;/p&gt;
&lt;p&gt;I thought it was a pretty good candidate for taking the processing off to a web worker;  which turned out pretty well.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;img-responsive&quot; src=&quot;https://benjaminbenben.com/img/gum-ww.png&quot; alt=&quot;Scanning QR code with getUserMedia&quot;&gt;&lt;/p&gt;
&lt;p&gt;Once you&#39;ve got the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/HTML/Canvas/Pixel_manipulation_with_canvas&quot;&gt;imageData&lt;/a&gt; from your canvas,  you can run it through &lt;a href=&quot;https://github.com/LazarSoft/jsqrcode&quot;&gt;jsqrcode&lt;/a&gt; by setting attributes of the qrcode object, then call .render():&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;qrcode&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;imagedata &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; imagedata&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
qrcode&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;width &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; imagedata&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;width&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
qrcode&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;height &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; imagedata&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;height&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; content &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; qrcode&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It was &lt;a href=&quot;https://github.com/benfoxall/jsqrcode/blob/master/src/worker.js&quot;&gt;pretty straightforward&lt;/a&gt; to pull the code into a web worker,  I spent a bit of time before I realised that console.logs were making it fall over.  Here&#39;s the interface for responding to messages with the worker:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;onmessage&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; imagedata &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    qrcode&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;imagedata &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; imagedata&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    qrcode&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;width &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; imagedata&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;width&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    qrcode&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;height &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; imagedata&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;height&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; resp&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        resp &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; qrcode&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        resp &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// *mostly* &quot;no code found&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;postMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Back in the original page,  you can creater the worker and deliver messages to it using the &lt;code&gt;.postMessage&lt;/code&gt; function.  You can optionally list &lt;a href=&quot;http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#transferable&quot;&gt;Transferable objects&lt;/a&gt; to efficiently move them to the web worker.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; worker &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Worker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;jsqrcode/worker.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
worker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;onmessage&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;qr code is:&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// imagedata = ctx.getImageData(…)&lt;/span&gt;
worker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;postMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;imagedata&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;imagedata&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Jsqrcode is on &lt;a href=&quot;https://github.com/LazarSoft/jsqrcode&quot;&gt;github&lt;/a&gt;, as is &lt;a href=&quot;https://github.com/benfoxall/jsqrcode&quot;&gt;my fork&lt;/a&gt; with the starts of the worker interface. You can either view source on the examples above, or view them on &lt;a href=&quot;https://github.com/benfoxall/benfoxall.github.com/tree/master/qr&quot;&gt;github&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Tweet Globe</title>
    <link href="https://benjaminbenben.com/2013/04/07/tweet-globe/" />
    <updated>2013-04-07T00:00:00Z</updated>
    <id>https://benjaminbenben.com/2013/04/07/tweet-globe/</id>
    <content type="html">&lt;p class=&quot;lead&quot;&gt;Plotting geocoded tweets on a globe with canvas&lt;/p&gt;
&lt;p&gt;&lt;canvas height=&quot;550&quot; width=&quot;600&quot; class=&quot;cr&quot; data-cr=&quot;tweet-globe&quot; data-cr-defer=&quot;&quot;&gt;Requires Canvas Support&lt;/canvas&gt;&lt;/p&gt;
&lt;p&gt;I gathered a few hours of geocoded tweets from the &lt;a href=&quot;https://dev.twitter.com/docs/streaming-apis&quot;&gt;twitter streaming api&lt;/a&gt; (using the &lt;a href=&quot;http://benjaminbenben.com/2012/12/05/maptime/&quot;&gt;maptime&lt;/a&gt; code as a base).  This was to explore some ideas that we&#39;d been talking about at &lt;a href=&quot;http://whiteoctober.co.uk&quot;&gt;White October&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Drawing the globe is &lt;a href=&quot;https://gist.github.com/benfoxall/5332944#file-tweet-globe-js&quot;&gt;relatively straightforward&lt;/a&gt;.  The lat/long pairs are converted into position vectors, which are then transformed based on the mouse position.  The &lt;a href=&quot;http://sylvester.jcoglan.com/&quot;&gt;Sylvester library&lt;/a&gt; was pretty handy for transforming the points (&lt;a href=&quot;https://twitter.com/intent/user?screen_name=peterjwest&quot;&gt;Pete&lt;/a&gt; talked about Sylvester at &lt;a href=&quot;http://jsoxford.com/&quot;&gt;jsoxford&lt;/a&gt; recently).&lt;/p&gt;
&lt;p&gt;The original plan was to animate this over a period of time,  though it looked quite random/noisy so I went for this static view instead.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://twitter.com/intent/user?screen_name=4foot30&quot;&gt;Gareth&lt;/a&gt; pointed me to a post about &lt;a href=&quot;http://jtnimoy.net/?q=178&amp;amp;utm_source=buffer&amp;amp;buffer_share=254f1&quot;&gt;the effects in tron legacy&lt;/a&gt; which makes me want to make this a lot more awesome!&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>lllocal</title>
    <link href="https://benjaminbenben.com/2013/04/05/lllocal/" />
    <updated>2013-04-05T00:00:00Z</updated>
    <id>https://benjaminbenben.com/2013/04/05/lllocal/</id>
    <content type="html">&lt;p class=&quot;lead&quot;&gt;I built &lt;a href=&quot;http://lllocal.com&quot;&gt;lllocal&lt;/a&gt; - which lets you find and listen to bands that will be playing in your area soon.&lt;/p&gt;
&lt;a class=&quot;cr thumb-gallery&quot; data-cr=&quot;thumb-gallery&quot; data-cr-defer=&quot;&quot; href=&quot;http://lllocal.com&quot;&gt;
	&lt;img class=&quot;img-responsive&quot; src=&quot;https://benjaminbenben.com/img/lllocal4.png&quot;&gt;
	&lt;img class=&quot;img-responsive&quot; src=&quot;https://benjaminbenben.com/img/lllocal1.png&quot;&gt;
	&lt;img class=&quot;img-responsive&quot; src=&quot;https://benjaminbenben.com/img/lllocal2.png&quot;&gt;
	&lt;img class=&quot;img-responsive&quot; src=&quot;https://benjaminbenben.com/img/lllocal3.png&quot;&gt;
&lt;/a&gt;
&lt;p&gt;I&#39;ve been thinking of this idea for a long time and I put up a public version a couple of months ago.  It&#39;s brilliant to get feedback from people and I&#39;ve also got tickets to two events while testing it out for myself (&lt;a href=&quot;http://www.keatonhenson.com&quot;&gt;Keaton Henson&lt;/a&gt; was great and we&#39;re off to see &lt;a href=&quot;http://4ad.com/artists/daughter&quot;&gt;Daughter&lt;/a&gt; in a couple of weeks).&lt;/p&gt;
&lt;p&gt;My motivation for lllocal came from:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;my personalised &lt;a href=&quot;http://last.fm&quot;&gt;last.fm&lt;/a&gt; &#39;&lt;a href=&quot;http://www.last.fm/events/+place/United+Kingdom/6955797+Oxford&quot;&gt;events near Oxford&lt;/a&gt;&#39; are almost all in London.  Granted, these bands are ones who I&#39;d really like to see and Oxford is pretty close to London - though I wanted to see more live music without spending evenings on a bus.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.wegottickets.com/&quot;&gt;we got tickets&lt;/a&gt; send out &lt;a href=&quot;http://open.spotify.com/user/wegottickets/playlist/4W27ngSpRwYqBPF6OcER0L&quot;&gt;spotify playlists&lt;/a&gt; to their &lt;a href=&quot;http://www.wegottickets.com/#_mailinglist&quot;&gt;mailing lists&lt;/a&gt;.  I love this style of suggesting people to go and listen to.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img class=&quot;img-responsive&quot; src=&quot;https://benjaminbenben.com/img/lllocal_insp.png&quot; alt=&quot;Lllocal inspiration&quot;&gt;&lt;/p&gt;
&lt;p&gt;The gig listings come from the &lt;a href=&quot;http://www.last.fm/api&quot;&gt;last.fm api&lt;/a&gt; and the &lt;a href=&quot;https://developer.spotify.com/&quot;&gt;Spotify web apis&lt;/a&gt; are used to find and play the bands on spotify.&lt;/p&gt;
&lt;p&gt;There is still a huge amount to do - though I&#39;m really happy to have something online.  If you have any feedback or suggestions I&#39;d love if you got in touch or left a message on the &lt;a href=&quot;https://lllocal.uservoice.com/&quot;&gt;feedback page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Lllocal is online at &lt;a href=&quot;http://lllocal.com&quot;&gt;lllocal.com&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Maptime</title>
    <link href="https://benjaminbenben.com/2012/12/05/maptime/" />
    <updated>2012-12-05T00:00:00Z</updated>
    <id>https://benjaminbenben.com/2012/12/05/maptime/</id>
    <content type="html">&lt;p class=&quot;lead&quot;&gt;In time for our first &lt;a href=&quot;https://twitter.com/intent/user?screen_name=jsoxford&quot;&gt;JS Oxford&lt;/a&gt; meet - I put together a small node app which reads geocoded tweets from the twitter streaming api and pushes them to the browser to display on a map.&lt;/p&gt;
&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;http://www.youtube.com/embed/vZ9XZNHP7Sk?showinfo=0&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;true&quot;&gt; &lt;/iframe&gt;
&lt;p&gt;This is a stripped down version of a project that I worked on at &lt;a href=&quot;http://www.whiteoctober.co.uk/&quot;&gt;White October&lt;/a&gt; this summer.  This version is not at all for production use (your browser will grind to a halt if you leave it running for a while!), though I hope it&#39;s a good/interesting example of linking up server and client js.&lt;/p&gt;
&lt;p&gt;The code is all up at the &lt;a href=&quot;https://github.com/jsoxford/maptime&quot;&gt;jsoxford github account&lt;/a&gt;, I&#39;ll go over a few bits of it:&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://github.com/jsoxford/maptime/blob/master/app.js&quot;&gt;app.js&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This is the main node.js file it brings in some external packages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://npmjs.org/package/ntwitter&quot;&gt;ntwitter&lt;/a&gt; - for accessing the twitter streaming api&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://npmjs.org/package/express&quot;&gt;express&lt;/a&gt; - to serve some static files&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://npmjs.org/package/faye&quot;&gt;faye&lt;/a&gt; - for sending messages between the server and the browser&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Once these have been brought in, you can connect to the streaming api &lt;a href=&quot;https://github.com/AvianFlu/ntwitter#streaming-api&quot;&gt;using ntwitter&lt;/a&gt;. This gives you access to a &lt;code&gt;stream&lt;/code&gt; object, which you can add listeners for new tweets using the &lt;code&gt;stream.on()&lt;/code&gt; function (see &lt;a href=&quot;http://nodejs.org/api/events.html#events_emitter_on_event_listener&quot;&gt;eventEmitter&lt;/a&gt; docs for more details).&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;twit&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;statuses/filter&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; filterParams&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// stream.on(&#39;data&#39;, yayFn)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We then want to serve some static files for our client side pages/scripts, you can use &lt;a href=&quot;http://expressjs.com/&quot;&gt;express&lt;/a&gt; to do this (express can do a whole lot more - if you want to have a look, I&#39;d recommend using the &lt;a href=&quot;http://expressjs.com/guide.html#executable&quot;&gt;executable&lt;/a&gt; to generate a basic app).&lt;/p&gt;
&lt;p&gt;We also want to send data to the browser using &lt;a href=&quot;https://npmjs.org/package/faye&quot;&gt;faye&lt;/a&gt;, this has a really nice pubsub api based on the &lt;a href=&quot;http://svn.cometd.com/trunk/bayeux/bayeux.html&quot;&gt;bayeux&lt;/a&gt; protocol.  Attaching this to the http server will listen for websocket/ajax long-polling requests and serve a client js wrapper at /faye.js.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; app &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;express&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;express&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;__dirname &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/public&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; bayeux &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;faye&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;NodeAdapter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token literal-property property&quot;&gt;mount&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/faye&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; server &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createServer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;app&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
bayeux&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;attach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;server&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
server&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;listen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, to link it all together - you can listen for events on the twitter stream, then publish them to a faye channel with the following code.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;stream&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;data&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;geo&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    bayeux&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getClient&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;publish&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;/tweet&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;geo&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;geo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;text
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;&lt;a href=&quot;https://github.com/jsoxford/maptime/blob/master/public/markers.html&quot;&gt;markers.html&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Moving clientside (this code is in ./public and will be served to the browser), we first want to connect to the faye pubsub.  To do this, we include the faye client library and connect to the endpoint that we mounted faye at on the server using &lt;code&gt;Faye.Client&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;text/javascript&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;/faye.js&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;text/javascript&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; client &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Faye&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Client&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;/faye&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We&#39;re using the google maps api to display the map and place the markers.  The majority of the code for this is straight from the &lt;a href=&quot;https://google-developers.appspot.com/maps/documentation/javascript/examples/marker-simple&quot;&gt;simple-markers&lt;/a&gt; example. (To get more of an introduction - have a look at the &lt;a href=&quot;https://developers.google.com/maps/documentation/javascript/tutorial&quot;&gt;tutorial&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;To get the tweet data from Faye, you use the &lt;code&gt;client.subscribe&lt;/code&gt; function to listen to a channel - in this case we broadcast them over &#39;/tweet&#39; from node.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; mapOptions &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; map &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;google&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;maps&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;map&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;mapOptions&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

client&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;subscribe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;/tweet&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;geo &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; message&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;geo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;coordinates&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;placeMarker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;geo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;coordinates&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;placeMarker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;coords&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; latlng &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;google&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;maps&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;LatLng&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;coords&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;coords&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;google&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;maps&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Marker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; latlng&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; map&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;p&gt;And that&#39;s it!  Have a look at the code on &lt;a href=&quot;https://github.com/jsoxford/maptime&quot;&gt;github&lt;/a&gt; (I&#39;ve missed out a little bit of the surrounding bumf above) and have a play with it.&lt;/p&gt;
&lt;p&gt;Also, if you are based around Oxford - come along to our next JSOxford meet on the &lt;a href=&quot;http://lanyrd.com/2013/jsoxford-january/&quot;&gt;17th of January&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Lastfm Canvas Streamgraph</title>
    <link href="https://benjaminbenben.com/2012/11/04/lastfm-canvas-streamgraph/" />
    <updated>2012-11-04T00:00:00Z</updated>
    <id>https://benjaminbenben.com/2012/11/04/lastfm-canvas-streamgraph/</id>
    <content type="html">&lt;p class=&quot;lead&quot;&gt;A browser based last.fm streamgraph using canvas.&lt;/p&gt;
&lt;a href=&quot;https://benjaminbenben.com/archive/projects/lgraph/?user=benjaminf&quot;&gt;
	&lt;img class=&quot;img-responsive&quot; src=&quot;https://benjaminbenben.com/img/lgraph.png&quot; width=&quot;843&quot; height=&quot;620&quot;&gt;
&lt;/a&gt;
&lt;p&gt;This is based on Lee Byrons &lt;a href=&quot;http://www.leebyron.com/what/lastfm/&quot;&gt;listening histories&lt;/a&gt; project.  I love this project - it&#39;s a really interesting and engaging visualisation, and the &lt;a href=&quot;http://last.fm&quot;&gt;last.fm&lt;/a&gt; data makes it really personal (I can&#39;t think of any other services that give as much personalised data as &lt;a href=&quot;http://last.fm&quot;&gt;last.fm&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;There are services that let you download a pdf streamgraph: &lt;a href=&quot;http://lastgraph.aeracode.org/&quot;&gt;lastgraph.aeracode.org&lt;/a&gt; &amp;amp; &lt;a href=&quot;http://playground.last.fm/demo/listeningtrends&quot;&gt;last.fm playground&lt;/a&gt; (if you&#39;re a subscriber).&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://benjaminbenben.com/archive/projects/lgraph/&quot;&gt;My version&lt;/a&gt; is different as all the api requesting and graph drawing are done in the browser - this lets you see your graph as soon as any data is ready.&lt;/p&gt;
&lt;p&gt;I originally started creating a large svg for the whole chart,  though this became quite slow, so I used separate canvas elements for each week of data and .  This is slightly limiting - I couldn&#39;t sort or colour the artists based on when they appear in your history (as the original does).&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Out With The Old</title>
    <link href="https://benjaminbenben.com/2012/09/25/out-with-the-old/" />
    <updated>2012-09-25T00:00:00Z</updated>
    <id>https://benjaminbenben.com/2012/09/25/out-with-the-old/</id>
    <content type="html">&lt;p class=&quot;lead&quot;&gt;After more than a year of no posts - I&#39;ve left my old blog behind.&lt;/p&gt;
&lt;p&gt;This new one is built with &lt;a href=&quot;http://jekyllrb.com&quot;&gt;Jekyll&lt;/a&gt; and put it online with &lt;a href=&quot;http://pages.github.com&quot;&gt;GitHub Pages&lt;/a&gt;.  The source is &lt;a href=&quot;https://github.com/benfoxall/benfoxall.github.com&quot; title=&quot;this blog source code&quot;&gt;on github&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It seems that a lot of Jekyll sites start with a post about the interesting way that they have been deployed.  So, for the record, I kept it simple and went for the &lt;a href=&quot;https://help.github.com/articles/using-jekyll-with-pages&quot; title=&quot;Using Jekyll with Pages&quot;&gt;github jekyll generator&lt;/a&gt;.&lt;/p&gt;
&lt;a href=&quot;http://bfoxall.com&quot;&gt;
	&lt;img class=&quot;img-responsive&quot; src=&quot;https://benjaminbenben.com/img/bfoxall.png&quot; width=&quot;766&quot; height=&quot;619&quot;&gt;
&lt;/a&gt;
</content>
  </entry>
</feed>