Using Highland.js with jide.js

Highland.js is an interesting library for working with node-like Streams that can be used within the Browser. While most of what it does is
not really necessary with jide.js, I still thought that it might be interesting to see how it can be used together with jide.js.

The example we’re going to create could very well be solved using simple jide.js data binding but one can easily imagine how streams of events could be quite beneficial from time to time.
It also highlights how easy it is to convert a jide.js EventEmitter to a Stream using Highland.js.

What we’re going to do is this: We want to offer a TextField to the user where he can insert a color value (using hex syntax to save me from typing more logic than necessary) that is then
displayed by a ColorField (or ColorSwatch or whatever). We’ll also want to use Browserify for this project since I didn’t take the time to check if and how Highland.js can be used with
AMD.

Let’s get started by installing the required dependencies using npm.

npm install --save-dev highland jide browserify-jide-template gulp gulp-browserify deamdify

Note that I have added gulp to the list of dependencies so that we can create a nice little build script that continually compiles our sources for us.
To do that, you should create a Gulpfile.js file with something like this:

var gulp = require('gulp');
var browserify = require('gulp-browserify');

gulp.task('browserify', function() {
    gulp.src('src/js/app.js')
        .pipe(browserify({
          insertGlobals : true,
          transform: ['browserify-jide-template', 'deamdify']
        }))
        .pipe(gulp.dest('./build/js'))
});

gulp.task('watch', ['browserify'], function() {
  gulp.watch('src/**/*', ['browserify']);
});

Make sure that you have gulp installed globally (npm install -g gulp) before you proceed.

Now, let’s create our index.html file:

<!DOCTYPE html>
<html>
<head>
    <title>jide.js &amp; Highland</title>
    <link type="text/css" rel="stylesheet" href="./node_modules/jide/style/default.css">
    <style>
    .color-field {
      display: inline-block;
      width: 37px;
      height: 37px;
      border: 1px solid black;
    }
    </style>
</head>
<body>
  <script src="./build/js/app.js"></script>
</body>
</html>

Nothing that really matters. We’re importing the stylesheet directly from the node_modules directory of jide.js so that we have at least some styling and we load the
browserified build/js/app.js file instead of our actual source file.

Now, let’s create quickly create the ColorField control and it’s template. I won’t go into any details here, check out the
developer guide or take a look at some of my earlier articles about how to create custom jide.js controls.

src/js/ColorField.js

var Class = require('jide/base/Class'),
  ObservableProperty = require('jide/base/ObservableProperty'),
  Control = require('jide/ui/Control'),
  Skin = require('jide/ui/Skin'),
  ColorFieldTemplate = require('./template.html');

function ColorField(config) {
  installer(this);
  Control.call(this, config || {});
}
Class(ColorField).extends(Control);

var installer = ObservableProperty.install(ColorField, 'color');

ColorField.Skin = Skin.create(Skin, {
  template: ColorFieldTemplate
});

module.exports = ColorField;

src/js/template.html

<template>
  <div class="color-field" bind="
    style: {
      'background': component.color
    }
  "></div>

</template>

Okay, now that we have all the controls we need, let’s create the src/js/app.js which puts it all together.

// Import some dependencies
var TextField = require('jide/ui/control/TextField'),
  HBox = require('jide/ui/layout/HBox'),
  ColorField = require('./ColorField'),
  _ = require('highland');

// create the UI
var colorField, colorEditor;
document.body.appendChild(new HBox({
  children: [
    colorEditor = new TextField({promptText: 'Please enter a valid CSS hex color (i.e. #000052)'}),
    colorField  = new ColorField({color: '#000000'})
  ]
}).element);

// now use highland - just because we can!
// convert the "change:text" event to a Stream
_('change:text', colorEditor)
  // we map each event so that we can continue to work only with
  // the new value
  .map(function(event) {
    return event.value;
  })
  // filter out any event that is not a valid hex color
  .filter(function(x) {
    return x && x.match(/#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})/);
  })
  // only fire if the user hasn't done anything for 300ms
  .debounce(300)
  // we only need the latest event
  .latest()
  // and set it
  .each(function(x) {
    colorField.color = x;
  });

Now, what I love about this is how we can transform, filter and drop events with a very nice API. Obviously, you could do the same with just jide.js but sometimes it is nice to know
that there is an alternative. I imagine this would could be especially useful when your input comes from a Stream-like object or you want to output something to such a Stream-like
object.

Oh, and just in case you’re wondering how to run this, type gulp watch into your command line (quit with Control+C) and open the HTML file in your browser. You can even do that
locally (no server required) since Browserify generates just one Javascript file containing all your code and doesn’t need any later request.

Leave a Reply

Your email address will not be published. Required fields are marked *