Getting WebSockets working with Node, Socket.io and Elastic Beanstalk

This is something that took me nearly a year to get working. Not full time obviously, but every now and then I would make another attempt at getting it working after the trauma of the previous attempt had faded. None of the examples that people had provided worked for me, and some were out dated and no longer applied. And of course the AWS documentation provided no help whatsoever.

I decided to share my configuration in the hope that it will help someone else. Here is a list of the technologies I am using:

  • The app is a NodeJS app running on 6.11.X, soon to be 8.4.X
  • Using the Express server framework and Socket.io for WebSockets
  • Using AWS Elastic Beanstalk
  • Nginx with reverse proxy to NodeJS
  • Using the newer Application Load Balancer
  • HTTPS is enabled
  • Front and back end running on same domain

READ MORE

Sorting strings with JS (properly)

It seems like such a basic task – how to sort a list of strings alphabetically.

The easiest way, and what you’d probably stumble across first, is a simple sort function:

1
arr.sort();

Or using the sort() function and passing a compare function:

1
arr.sort((a, b) => a > b);

Or sorting on object property:

1
2
3
4
5
arr.sort(function(a, b){
    if(a.name < b.name) return -1;
    if(a.name > b.name) return 1;
    return 0;
})

This is the most common answer when searching Google/Stack Overflow on how to sort an array. It works for simple strings, however you can quickly run into issues when numbers get involved where 10 can appear before 2 etc. And then there are special characters and languages other than English – what determines where they appear in an alphabetical list?

It’s not easy to find this answer – is it assumed knowledge? I quickly discovered a bunch of highly complicated sorting functions that people had glued together on Stack Overflow. But I thought surely there is a simpler way for such a basic and common task.

Intl.Collator to the rescue

JavaScript has an Internationalisation API called Intl (MDN) which provides tools for sorting text (among many other things) in a specific language, and taking into account letter case, numbers and special characters.

You first need to create a Collator object using Intl.Collator:

1
let collator = new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' });

A locale can be provided as the first argument (where I have used ‘undefined’) to specify a language other than the default (see Collator in MDN)

Once we have the collator we can use its ‘compare’ function in the Array.sort:

1
2
3
4
5
6
let arr = [
  "First item",
  "The second item",
  "Item 3"
];
arr.sort(collator.compare);

Or if you need to compare a property on an object:

1
2
3
4
5
6
let arr = [
  {name: "First item" },
  {name: "The second item" },
  {name: "Item 3" }
];
arr.sort((a, b) => collator.compare(a.name, b.name));

Using ES6 template strings to generate unique strings

The following technique is something that I found template strings in ES6 to be quite useful for. I needed to generate XML chunks (as a string) where each node had a unique ID every time the XML was generated.

Most examples of template strings I see around the web just use simple variables inside template strings. I found that you can also use functions that return a value, making the string even more dynamic.

I ended up writing a function that creates the string and inserts unique IDs in specific locations every time the function is called:

1
2
3
4
5
6
7
8
9
const generateID = () => {
  // ... some code to generate and return an ID
}

const getStringTemplate = () => {
  return `<element uid="${generateID()}">
            <child uid="${generateID()}"></child>
          </element>`
}

You can place ${generateID()} any number of times in the template string and in each location a unique ID will be inserted.

Now I can call getStringTemplate() and get a unique chunk of XML every time.

Using Cardboard Camera and A-Frame to create a simple WebVR scene

I have been playing around with VR a bit lately after getting a new Android phone (Nexus 6P), and I thought I’d share a simple experiment I did using Google’s Cardboard Camera app, and the WebVR library A-Frame.

The result of this will be a simple WebVR scene that displays the photo captured from Cardboard Camera in a scene that you can look around.

1. Take a 360 photo

First off you will need to download and install the Cardboard Camera app, then take a photo using it.

Then choose ‘Open in gallery’ from the menu and share the image (I just emailed it to myself).

Save the photo to a new folder on your computer.

2. Create an HTML file

Next create an empty HTML file in the same folder as the image:

1
2
3
4
5
6
7
8
<!DOCTYPE html>
<html>
<head>
    <title></title>
</head>
<body>
</body>
</html>

3. Get the A-Frame library

Now visit the A-Frame website and download the library and save it the same folder as the HTML file, or use the hosted version. Then include it in the head of your HTML page using a script tag:

1
<script type="text/javascript" src="https://aframe.io/releases/latest/aframe.min.js"></script>

4. Create the WebVR scene

In the body of you HTML page you now need to construct the WebVR scene using the components provided by A-Frame. We need to make a scene to display it. We do that by adding an a-scene component and adding our objects inside.

1
2
3
4
<a-scene>
     <a-sky src="name_of_your_image.vr.jpg" segments-width="1000"></a-sky>
     <a-camera  cursor-visible="false"></a-camera>
</a-scene>

In the above example I have added an ‘a-sky’ component and an ‘a-camera’ component. Thy sky component renders a large sphere around the scene as a background, and it is using the image that we captured with Cardboard Camera. The camera component adds a new camera object at the centre of the scene (0, 0, 0).

5. Result

So the final HTML file should look this this:

1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html>
<head>
    <title></title>
    <script type="text/javascript" src="https://aframe.io/releases/latest/aframe.min.js"></script>
</head>
<body>
    <a-scene>
        <a-sky src="name_of_your_image.vr.jpg" segments-width="1000"></a-sky>
        <a-camera  cursor-visible="false"></a-camera>
    </a-scene>
</body>
</html>

Now if you preview in your browser (Chrome) you should get a scene that you can spin around in using your mouse. If you view the page on a WebVR compatible mobile device your will be able to enter VR mode and put the device into a VR headset such as Google Cardboard.

Chrome:
vr1

Or on Android:

Screenshot_20160205-125631

You may need to add some extra pixels to the top and bottom of the image to prevent any distortion as the image is stretched around the sphere.

Paint stencilling with HTML5 canvas

I have recently been playing around with re-writing my Spray paint stencils in Flash using JavaScript and HTML5’s canvas element. One thing I discovered is that since SVGs are natively supported in browsers I can have stencils scaled to any size and remain crisp, unlike the Flash version which used transparent PNGs.

I have implemented stencils, including having a muck layer, and stickers – graphics that you can place and cut out through stencils. When I first started playing around I was writing it all plain JavaScript, but eventually I converted everything over to TypeScript which allowed me to easily separate everything out into their own classes with event listening/dispatching capabilities. Almost mimicking the way things were written in AS3.

Below is a video of the early prototype, I will provide a live demo when it is more ready for public use.

Automatic typography substitution

After reading the series of Death to Typewriters articles on Meduim, I decided to have a go at implementing their automatic character substition rules in JavaScript. Following the guide provided at Death to Typewriters: Automatic replacement and clean-up, I created a simple function that can be called as you type, or when text is pasted, into a text area. Certain character combinations and locations are looked for and replaced with other characters such as correct quotes, arrows and ellipsis. I have put the code up on GitHub with a little bit of documentation.

READ MORE

Recreating the Apple Watch UI using a hexagonal grid

Building on the hexagonal grid from earlier, I have added a little JavaScript and have created an effect similar to the Apple Watch home screen UI.

Below is a video of it in action, I am using IE11 (metro version) on a Surface Pro 2 which I found to be the most performant for this effect. Chrome was janky as hell, and Safari on the iPad doesn’t like to do things while scrolling.

And an embedded demo, it works best on a touch screen although not an iPad:

The code can be found at this CodePen.

Triggering a ‘finish’ event on an external video with Storyline HTML5

If you have at some point needed to use Articulate Storyline – you have probably come to a point where you want to murder everyone around you (not literally of course!) due to its ridiculous, quirky limitations. More often than not I find myself hacking the published code to make things works how I want.

One of the big limitations in Storyline is video – if you want to trigger something when the video starts or finished you must use the built in player. But the built in player cannot load videos from an external site (such as a streaming server – a common requirement) so you are left with using the ‘video embed code’ option, which doesn’t seem to allow custom embed codes – all I could get to work was YouTube and Vimeo. And even if you can get this to work you can’t add triggers to it for when the video ends.

I found a little hack which uses the Web Object and a custom video player in a HTML page. You can listen for the video complete event in the custom player then change a variable in the Storyline player. Then in Storyline add a trigger for when that particular variable changes, which will be when the video finishes.

Here’s how to do it.
READ MORE

Accessing command line arguments with Grunt

I needed to be able to set up a watch task with Grunt to only watch a specific client sub directory. This directory would change depending on the client I was working on and new clients were constantly added so I need a way to watch the specific client that I was working on only, without hard coding all the clients into separate tasks. The only thing I could think of doing this was to pass some sort of parameters when starting the watch task.

This is how I set it up. It might not be the best method but it works for me.

First I had to set a value in the grunt configuration, which would be taken from the command line args. With Grunt you can get them them using:

1
grunt.option('someCommandLineArg');

You can also set a configuration value using:

1
grunt.config.set('myValue', 'someValue');

So combining those two methods, the following will get a command line arg called “watchDir” (and assign a default value of src if it was not specified) and set it in the grunt config. I added this line after initConfig in my Gruntfile:

1
grunt.config.set('watchDir', grunt.option('watchDir') || 'src');

You can then access this property using a template string in your task:

1
2
3
4
5
6
watch: {
      less: {
        files: ['clients/<%= watchDir %>/**/*.less'],
        tasks: ['less']
      }
}

When running the Grunt task, we can specify the option “watchDir” by adding two dashes in front and setting it equal to the desired value:

1
grunt watch --watchDir="clientX"

The watch task above would in this case watch the following directory:

1
'clients/clientX/**/*.less'

This allows you to set up a generic task that can be pointed to different directories when it is started.

Local AJAX calls with IE11

Here is a little snippet to get local AJAX (with jQuery) working when running content locally in IE 11. Local content is not allowed to use the XMLHttpRequest but it can use the proprietary ActiveXObject, so this tells jQuery to always use the ActiveXObject if it’s available.

I needed to use this to run local content on a Surface RT which doesn’t have IIS or any other browsers. This allowed me to run content that relied on AJAX from the desktop in IE modern.

1
2
3
4
5
6
7
8
9
10
11
$.ajaxSetup({
    xhr: function()  {
        if ('ActiveXObject' in window) {
            return new ActiveXObject("Microsoft.XMLHTTP");
        }
        else
        {
            return new XMLHttpRequest();
        }
    }
});