Undo with Object.observe

18 Jul 2014 | By Alex Young | Comments | Tags libraries browser dom

Polgár András sent in LazyJsonUndoRedo (GitHub: azazdeaz / LazyJsonUndoRedo, npm: lazy-json-undo-redo, Bower: LazyJsonUndoRedo), which uses ES6’s Object.observe to bless undo and redo support on arbitrary JavaScript objects. That means if you’ve got a rich UI component you can add intuitive undo support.

There’s a demo that shows a graphical maze which supports undo and redo that illustrates the concept nicely. It sets the maze’s map object to use LazyJsonUndoRedo, and whitelists some special objects:

var ljur = new LazyJsonUndoRedo();
ljur.setWhitelist(map, ['data', 'objectMap', 'objectData', 'width', 
  'height', 'name', 'gridSize', 'showGrid', 'showWalls']);
ljur.observeTree(map);

var gui = new dat.GUI();
gui.add({ undo: function() { ljur.undo(); } }, 'undo');
gui.add({ redo: function() { ljur.redo(); } }, 'redo');

Object.observe is supported in the latest stable Chrome, and there’s a Polymer shim for older browsers. The shim should work in IE 9 and above.

Internally, LazyJsonUndoRedo uses an array to store changes and a pointer so objects can be fetched as required.

DOM Manipulation with Cash

17 Jul 2014 | By Alex Young | Comments | Tags libraries browser dom

Cash (GitHub: sudo-js / cash, License: MIT) by Rob Robbins at TaskRabbit, is a lightweight library for working with the DOM. It uses $ to provide access to an abstracted NodeList. It’s chainable, and supports events, CSS manipulation, and attributes.

For example, given var things = document.querySelectorAll('div'), you could change the class attributes like this:

$(things).q.forEach(function(el) { el.classList.remove('example'); });

Or add an event handler:

$(things).on('click', function() {
  // One of the things was clicked
});

The init method that runs whenever you call $() checks to see if the argument is an array, NodeList, or HTMLCollection. When it’s not an array, slice.call is used to map the elements to an array. The idea is to make this method as fast as possible so it’s safe to call it whenever you need access to a list of elements.

The new TaskRabbit site has been developed using micro libraries, and this is the library they used make working with the DOM more succinct. If you go to taskrabbit.com you should be able to run something like $(document.querySelectorAll('p')).q to see it in action.

If you’re avoiding larger frameworks and trying to find the perfect DOM querying and manipulation library, then take a look at the source – it’s fairly easy to see what’s going on. There’s annotated source, and the project itself is fairly easy to read because it uses a Node build script to generate the final framework from separate files. There are even detailed tests in the spec directory.

Node Roundup: npm CLI Roadmap, Nodemailer, Jasmine-Utils

16 Jul 2014 | By Alex Young | Comments | Tags node npm modules libraries jasmine testing email

npm CLI Roadmap

On the npm blog, there’s a post about the command-line tool’s roadmap:

The first piece of redesign work we’re tackling is the npm cache. … The next goal is to turn it into a module with no dependencies on the rest of npm or npmconf and to test the heck out of it. As npm moves to being a part of the toolchain of front-end developers (who are more interested in shipping features than figuring out what’s going on with their OS), it’s time to work on making npm easier to understand when things go wrong.

The article also mentions a better search interface, which I’d like to see because the current CLI search implementation is inflexible. It’s interesting to read about how the project is evolving away from Isaac’s original lightweight implementation intended for experts – the team behind the project has recognised that npm is used by a diverse range of developers.

Nodemailer

Nodemailer (GitHub: andris9 / Nodemailer), License: MIT, npm: nodemailer 1.0 is out! This is a complete rewrite, and partly breaks backwards compatibility so you may need to upgrade carefully:

The new version allows you to write custom plugins for manipulating the outgoing messages. It is also possible to send huge attachments with ease (in the size of tens of gigabytes) thanks to the Streams2 support - even though no one probably needs to send such attachments since probably no e-mail server would accepts these.

Jasmine-Utils

Jasmine-Utils (GitHub: mjeanroy / jasmine-utils, License: MIT, npm: jasmine-utils) by Mickael Jeanroy is a set of custom matchers for Jasmine. They’re grouped around types, like toBeABoolean and toBeDateBefore. Methods are included for booleans, strings, arrays, dates, objects and functions:

it('should check that an object contains keys', function() {
  var obj = {
    id: 1,
    name: 'foo'
  };

  expect(obj).toHaveKeys('id', 'name');
  expect(obj).not.toHaveKeys('foo', 'bar');
});

It also includes some handy spy methods, like jasmine.spyAll and jasmine.spyIf. These allow objects to be watched to ensure the expected methods are run.

The project includes a huge amount of matchers, so if you’re using Jasmine you may want to check it out.

VanillaMasker, jsTag

15 Jul 2014 | By Alex Young | Comments | Tags jquery angularjs ui

VanillaMasker

VanillaMasker (GitHub: BankFacil / vanilla-masker, License: MIT) by Caio Ribeiro Pereira is a small library for masking input elements with formats. It supports money, numbers, and custom patterns.

For example, a simple date mask would look like this:

masker.toPattern(12122000, "99/99/9999");

It doesn’t have any dependencies (hence “vanilla”), unless you want to build it locally.

jsTag

jsTag (GitHub: eranhirs / jsTag, License: MIT, Bower: jsTag) by Eran Hirsch is an AngularJS library for handling rich tag input fields. To use it, add a js-tag element to your HTML, and then add the js-tag-options directive for specifying a placeholder and default tag values.

You can also access it in JavaScript like this:

demoApp.controller('CustomizedController', ['$scope', function($scope) {
  // Export jsTag's options
  $scope.jsTagOptions = {
    'texts': {
      'inputPlaceHolder': 'Type text here'
    },
    'defaultTags': ['Default Tag #1', 'Default Tag #2']
  };
}]);

The documentation includes an example of using it with Twitter’s typeahead.js project.

An Alternative to AMD: CMD

14 Jul 2014 | By Alex Young | Comments | Tags modules amd harmony

By now most of us use AMD or CommonJS as our module API. With Harmony on the horizon, there doesn’t seem to be much need to innovate where libraries like RequireJS have established a niche. Despite this, John Wu sent me his module loader that can be found in his project wd.js.

This approach uses a chainable API which allows modules to be loaded asynchronously in a browser-friendly way, without AMD’s less fluent syntax:

wd.module('core.util')
  .require('core.bar')
  .require('core.foo')
  .body(function() {
    // foo and bar are now loaded
  });

John calls this style CMD, which stands for Chainable Module Definition. Although it seems like an obvious idea, it’s new to me and I think it fits in well with other modern JavaScript libraries.

Route360, ngVideo

11 Jul 2014 | By Alex Young | Comments | Tags maps video angularjs

Route360

Route360

The Route360 JavaScript API (GitHub: route360 / r360-js, License: MIT, Bower: route360) by Henning Hollburg and Daniel Gerber is a library for Leaflet that adds some cool features:

  • Generate polygons for reachable areas based on a point on the map
  • Supported for walk, car, bike and transit routing
  • Map controls: travel time slider, date and time chooser, and travel type chooser
  • Routing information from source to destination, including travel time and transit trips
  • Support for elevation data

This is a snippet of the polygon API:

var cpl = r360.route360PolygonLayer();
map.addLayer(cpl);

var travelOptions = r360.travelOptions();
travelOptions.addSource(marker);
travelOptions.setTravelTimes([300, 600,900, 1200, 1500, 1800]);

r360.PolygonService.getTravelTimePolygons(travelOptions, function(polygons) {
  cpl.addLayer(polygons);
  map.fitBounds(cpl.getBoundingBox()
});

ngVideo

ngVideo (GitHub: Wildhoney / ngVideo, License: MIT) by Adam Timberlake is a set of AngularJS directives for working with video. Videos are wrapped in an ng-video container:

<section class="video" ng-video>

And should contain a video element. It includes a service which you can use to attach videos:

myApp.controller('VideoController', ['$scope', 'video', function($scope, video) {
  video.addSource('mp4', 'http://www.example.com/alice-in-wonderland.mp4');
}]);

The project includes a lot of other directives for handling buffering, UI controls, data about play position and elapsed time, full screen support, and playlists.

TweetNaCl.js

10 Jul 2014 | By Alex Young | Comments | Tags cryptography modules libraries

TweetNaCl.js (GitHub: dchest/tweetnacl-js, npm: tweetnacl) is a JavaScript port of TweetNaCl – a cryptography library in 100 tweets.

NaCl in this case isn’t Google Native Client or sodium chloride, but a library for fast cryptographic operations. TweetNaCl builds on it to implement an auditable high-security cryptographic library. There’s a paper on it with more details.

TweetNaCl.js is interesting because it ports all of this to JavaScript, using the new 64-bit TypedArray APIs, like Float64Array. It implements secret-key authenticated encryption, public-key authenticated encryption, hashing, and public-key signatures.

One of the authors, Dmitry Chestnykh, said this about the library:

It’s not a toy crypto library: the underlying primitives are djb’s (https://en.wikipedia.org/wiki/Daniel_J._Bernstein) XSalsa20, Poly1305, Curve25519, and Ed25519, which are used OpenSSH and draft TLS (http://googleonlinesecurity.blogspot.com/2014/04/speeding-up-and-strengthening-https.html5).

You can install it with npm or Bower. As far as usage goes, I’ve been looking at the code in the tests to get a feel for how it works, but there’s documentation in the readme as well:

test('nacl.sign and nacl.sign.open specified vectors', function(t) {
  specVectors.forEach(function(vec) {
    var keys = nacl.sign.keyPair.fromSecretKey(dec(vec[0]));
    var msg = dec(vec[1]);
    var goodSig = dec(vec[2]);

    var sig = nacl.sign(msg, keys.secretKey);
    t.equal(enc(sig), enc(goodSig), 'signatures must be equal');
    var openedMsg = nacl.sign.open(msg, sig, keys.publicKey);
    t.equal(enc(openedMsg), enc(msg), 'messages must be equal');
  });
  t.end();
});

Node Roundup: newspeak, CatchMe, Catnap

09 Jul 2014 | By Alex Young | Comments | Tags node npm modules email REST

newspeak

newspeak (GitHub: yoshuawuyts / newspeak, License: MIT, npm: newspeak) by Yoshua Wuyts is a module inspired by Mozilla’s L20n project:

L20n is a new localization framework developed by Mozilla for the Web. It allows localizers to put small bits of logic into localization resources to codify the grammar of the language.

The following example is a small pluralisation helper:

var newspeak = require('newspeak');
l20n.currentLanguage('nl');
var l20n = newspeak({ language: 'nl', gender: 'male' });

var data = {
  users: function(obj) {
    if (0 === obj.count) return 'nobody';
    if (1 === obj.count) return 'someone';
    return ' people';
  }
};

l20n.register({ nl: data });
l20n.get('users', { count: 3 });

CatchMe

CatchMe (GitHub: Pentiado / catch-me, License: MIT, npm: catch-me) by Paweł Wszoła is another Node SMTP server that captures emails. This one has a nice web interface, and can validate email with Campaign Monitor.

It accepts command-line arguments for defining the web and SMTP ports: catchme --mailPort 1234 --appPort 4321

Catnap

Catnap (GitHub: mikaa123 / catnap, License: MIT, npm: catnap) by Michael Sokol is an Express-compatible module for generating REST resources:

var makeResource = require('catnap').makeResource;

var userResource = makeResource('user', '/users/:userId')
  .representation(function(user) {
    // The default representation. Returns a full representation of user
    return user;
  })
  .representation('partial', function(user) {
    // A named representation that returns a partial representation
    return pick(user, 'username', 'email');
  })
  .get(function(req, res) {
    // Action methods take standard middleware.
    User.findOne({ _id: req.params.userId }, function(err, user) {
      user && res.send(200, userResource(user));
    });
  })
  .attachTo(app);

There’s a wiki with documentation that explains how the module relates to Roy Fielding’s dissertation:

So in other words, a resource is some service that lives at a URI and that has one or more representations. In order to interact with a resource, we need to use an HTTP request method, you know, GET, POST, PUT, PATCH and DELETE. These methods have a lot of semantics baked in! For example, when we GET /users/123, we are asking for the representation of the user who’s id is ‘123’. This HTTP transaction (request-response) is called an action.

Autobahn|JS

08 Jul 2014 | By Alex Young | Comments | Tags events pubsub servers node

Autobahn

Autobahn|JS (GitHub: tavendo / AutobahnJS, License: MIT, npm: autobahn) is an implementation of a protocol that supports RPC and PubSub that runs over WebSocket, with fallbacks for older browsers.

The PubSub model supports topics, and uses a promise-based API:

// Subscribe to a topic
session.subscribe('com.myapp.topic1', onEvent).then(
  function(subscription) {
    console.log('Subscribed:', subscription);
    currentSubscription = subscription;
  },

  function(error) {
    console.error('Error:', error);
  }
);

The support for RPC is based on a router, where routes are represented as strings. Registering a remote procedure also uses a promise:

// Define the remote procedure
function utcnow() {
  var now = new Date();
  return now.toISOString();
}

// Register the remote procedure with the router
session.register('com.timeservice.now', utcnow).then(
  function(registration) {
    console.log('Procedure registered:', registration.id);
  },
  function(error) {
    console.error('Registration failed:', error);
  }
);

You can call this remote procedure with session.call('com.timeservice.now'), which again returns a promise.

To use Autobahn, you also need an application router. The documentation mentions Crossbar.io. This allows you to create distributed server applications, so you could route between backends running on different platforms. Authorization is supported, so you can limit access to server-side resources.

The project is based on an open protocol called WAMP (Web Application Messaging Protocol). Other WAMP implementations include Autobahn|Android and wampy.js.

Registering Angular.js Components, ChainyJS

07 Jul 2014 | By Alex Young | Comments | Tags angularjs articles modules libraries data flow-control

Registering Angular.js Components

In Registering Angular.js Components without Hassle, Konstantin Raev discusses a way to automate component registration in AngularJS. The solution is based around Require.js and gulp.js, and he even has examples in TypeScript.

It goes against AngularJS’s design a little bit, but the author is obviously experienced with inversion of control containers so he’s adopted an approach that might be more familiar to Java or C# developers.

ChainyJS

ChainyJS (GitHub: chainyjs / chainy, License: MIT, npm: chainy) is a library for handling data in a similar way to jQuery’s DOM API. The author has published an introductory talk, and the GitHub wiki has documentation for each of the main features.

Chainy supports some built-in data flow actions: set, action, done, and map. You can use them like this:

require('chainy').create().require('set map')
  // Set the chain's data to an array of two items
  .set(['some', 'data'])
  .map(function(itemValue) {
    // Capitalize each item
    return itemValue.toUpperCase();
  })
  .action(function(currentChainValue) {
    // Join the chain's data and add an exclamation
    return currentChainValue.join(' ') + '!';
  })
  // Handle an error (if applicable), and log the output
  .done(function(err, resultChainValue) {
    if (err) throw err;
    console.log('result:', resultChainValue);
  });

The map and action methods can be asynchronous – just include an extra argument to get a callback.

The map method is actually a plugin. Plugins are extensions that extend API calls. You can bundle plugins using the Chainy command-line tool, and npm peerDependencies can be used as well.

Powered by JavaScript Conference

04 Jul 2014 | By Alex Young | Comments | Tags events

Powered by JavaScript

Powered by JavaScript is a conference organised by Manning, the publisher of my book Node.js in Practice. My co-author, Marc Harter, is speaking, along with Tim Caswell and Ben Acker. For a full list of speakers see http://www.manning.com/poweredbyjavascript/.

The conference will be held in St. Louis on September 17, 2014. Early bird tickets are $250, and tickets at the door will be $500.

Manning are looking for sponsors, and there’s a PDF with more details.

Moving Atom To React

03 Jul 2014 | By Alex Young | Comments | Tags reactive atom

There’s a post on the Atom blog about some performance improvements that you can optionally enable: Moving Atom To React. It discusses how Facebook’s React library was used to improve the performance of the text editing component:

Right out of the box, React’s virtual DOM got us a long way toward our goal of treating the DOM with kid gloves. Though we worked with raw DOM nodes in a few places for performance and measurement reasons, it offered a declarative abstraction that relieved us of the tedious state management typically associated with DOM updates. In addition, React’s well-defined reconciliation strategy and lifecycle hooks made it easy to reason about the sequencing of the manual DOM interactions we did have to perform.

With the React editor, these kinds of changes can now be performed with the new decorations API. Decorations allow metadata to be associated with markers, instructing the editor to render classes on lines and line numbers, or draw highlight regions. Using decorations is faster and more convenient than manual DOM interactions, and we plan on introducing more APIs for common DOM interactions going forward.

This highlights several things that React is good at:

  • It’s relatively small and self-contained, so you can drop it into an existing project
  • The virtual DOM is fast
  • It helps to improve managing state

I’ve been using Knockout for a while now, and I’m even thinking about using RxJS for some projects. However, after reading this I think a combination of Knockout and React might work well for the messier parts in my Knockout view models that deal with the DOM.

Node Roundup: SocketCluster, i18n-generator, generator-gulp-angular

02 Jul 2014 | By Alex Young | Comments | Tags modules node internationalisation WebSocket

SocketCluster

SocketCluster (GitHub: TopCloud / socketcluster, npm: socketcluster) is a WebSocket server designed with clustering in mind. The developers have tested for memory leaks and included benchmarks. It handles client reconnection if a server crashes, and has a clustered memory store for temporary session data.

SocketCluster lets you store session data using the socket.session object. This object gives you access to a cluster of in-memory stores called nData. You can effectively invoke any of the methods documented here to store and retrieve session data: https://github.com/topcloud/ndata

Basic usage looks like this:

var SocketCluster = require('socketcluster').SocketCluster;

var socketCluster = new SocketCluster({
  workers: [9100, 9101, 9102],
  stores: [9001, 9002, 9003],
  balancerCount: 1,
  port: 8000,
  appName: 'myapp',
  workerController: 'worker.js',
  rebootWorkerOnError: false,
  addressSocketLimit: 50
});

The project is built with iocluster and loadbalancer, by the same authors.

i18n-generator

i18n-generator (GitHub: huei90 / i18n-generator, License: MIT, npm: i18n-generator) by Huei Tan is a library for converting i18n text files into JSON.

For example, given this input:

i18n=> | en | zh_TW | de | my
you | you | 你 | Du | kamu
I | I | 我 | ich | Saya
love | love | 喜歡 | liebe | cinta
eat | eat | 吃 | essen | makan
ilovegithub | i love github | 我愛 Github | ich liebe Github | Saya cinta pada Github

It would generate this:

{"you":"you","I":"I","love":"love","eat":"eat","ilovegithub":"i love github"}

for each language. It comes with tests and browser support.

generator-gulp-angular

I find it difficult to work on MVVM projects without some sort of build system so I can at least structure the project with CommonJS or AMD. generator-gulp-angular gives you a Yeoman generator that uses Gulp, Bowser, and AngularJS.

This generator aims to takes the best from others generators like generator-angular, ngTailor and generator-gulp-webapp to offers the best workflow to start an application with AngularJS powered by Gulp!

generator-gulp-angular scaffolds out an AngularJS application with a full featured gulpfile.js which offers all the tasks for modern web development.

It seems like a good way to get started with Gulp and AngularJS, which can actually be a little bit daunting.

WebRTC Video Mixing with Mixology

01 Jul 2014 | By Alex Young | Comments | Tags webrtc video streaming

Gearcloud Labs has open sourced their Mixology project under an MIT license. The source is available on GitHub: gearcloudlabs / Mixology.

This project allows video streams to be combined using a Node server. It uses WebRTC, the W3C standard for browser video, audio, and P2P. Google recently switched Google Hangouts over to WebRTC, which you can try in developer builds of Chrome:

Google+ Hangouts no longer requires a separate plugin to be installed in Chrome for video and voice chat to work. Using the Web Real-Time Communication API (WebRTC) and Native Client (NaCl) Google is able to provide a native video chat experience out of the box in Chrome.

Mixology uses collections of web pages that communicate using WebRTC. There’s an additional manifest file written with JSON that defines how streams are mixed:

{
  "channelName": "Your mix name",
  "topology": ["filename-basename.output-streamname | filename-basename.input-streamname", ...],
  "partitionSize": integer
}

The Node project uses Express and Socket.IO. It’s currently a monolithic file with no dependencies, so it expects you to have Express and Socket.IO installed globally. Refactoring it into a more modular Express application might be a nice exercise for someone looking to contribute to an open source project…

You are a Robot...

30 Jun 2014 | By Alex Young | Comments | Tags tutorials javascript games
That smiling face is you.

You are a robot, that smiling face represents you.

My digital residual self image isn’t what it once was, but surely I’m more than a smiling face glyph! JS Robot by Pavel Evsegneev an open source game for learning JavaScript. The GitHub repository is here: Ahineya / jsrobot.

The levels are unit tested with Mocha, and the author accepts pull requests for new levels. Levels are defined as text files, like this:

########
#_  $f #
########

The _ is the start position, $ and # are walls, and f is the finish. The player must write JavaScript that pushes the robot to the f position. The full list of symbols is defined in map.js:

var SYMBOL_TYPES = {
  '#': 'wall',
  '$': 'wall',
  'space': 'space',
  '_': 'start',
  'f': 'finish'
};

It’s a fun game that may have a few surprises for beginners learning JavaScript, and the code is clean. You could easily extend it to have fancier graphics or a different narrative, but I like the text-based interface. It would be nice to optionally play it in a terminal by installing it with npm.

s/Ampersand.js/Backbone and Express/

27 Jun 2014 | By Alex Young | Comments | Tags frameworks node

Ampersand.js from &yet is a new web framework. It follows the trends that I’ve been using for my own applications:

  • Everything is CommonJS
  • Client-side dependencies use npm (for a list of modules, see http://tools.ampersandjs.com)
  • State and data binding is Backbone-inspired

It has a heavy focus on client-side development, so it leans on the MVVM approach. Most of these ideas come together in the form documentation:

The quickest way to build out a starting point for a form in your project is to point ampersand-cli at a model file to generate a form for editing it. We’ll eventually make more “official” input views types. But the idea is, if you want to write a color picker, or a date input view, or a username-checker-input that does server-side validation, or a password field with a strength indicator, you can write a view for that and as long as it follows the form view conventions in the list above and it will still work happily with the rest of the form.

This is further explained explained in what is a view?

It doesn’t matter if your “view” is an instance of ampersand-view or not. Any object can be a view if it follows a few rules.

The example on that page looks like Backbone as well.

When generating a new Ampersand application, it prompts for the server-side module. You can use either Express or hapi. It makes a demo app, which almost entirely client-side JavaScript. The payload that gets served is just this:

<!DOCTYPE html>
<link href="/dailyjs.nonCached.css" rel="stylesheet" type="text/css">
<script src="/dailyjs.nonCached.js"></script>

It runs using a livereload module, so you can edit files and the client will be updated. As the documentation says, it treats the browser as a runtime.

Ampersand seems like a way to unify Node and Backbone development. I don’t yet know how well Ampersand works in production on services like Heroku, or how easy it is to test, but I’m definitely enthusiastic about the idea of blending Node and libraries like Backbone or AngularJS.

V8 Optimization Killers

26 Jun 2014 | By Alex Young | Comments | Tags node v8 performance

Bluebird gets a lot of respect for its performance and API style, and reading Optimization killers on the Bluebird wiki reinforced my own inclination to use it over the dozens of other competent promise libraries.

Dug up by diggan on Hacker News, this wiki page explores some ways seemingly innocent JavaScript can cause V8 to avoid optimisation. It contains a code sample that allows you to detect if a function has been optimised, which I’ve been playing with:

// Function that contains the pattern to be inspected (using with statement)
function codeToTest(a, b) {
  if (arguments.length < 2) b = 5;
}

function printStatus(fn) {
  switch(%GetOptimizationStatus(fn)) {
    case 1: console.log('Function is optimized'); break;
    case 2: console.log('Function is not optimized'); break;
    case 3: console.log('Function is always optimized'); break;
    case 4: console.log('Function is never optimized'); break;
    case 6: console.log('Function is maybe deoptimized'); break;
  }
}

// Fill type-info
codeToTest(1, 2);

%OptimizeFunctionOnNextCall(codeToTest);
// The next call
codeToTest(1, 2);

// Check
printStatus(codeToTest);

%OptimizeFunctionOnNextCall causes V8 to to check if a function can be optimised, and then marks it for optimisation. Running it and then calling %GetOptimizationStatus will get debugger information so you can see if a given function can be optimised.

To run this example, the Bluebird wiki suggests using the following Node options:

node --trace_opt --trace_deopt --allow-natives-syntax test.js

The --trace_opt option logs the names of optimised functions, and --trace_deopt logs “deoptimisations”. The --allow-natives-syntax option allows you to use the V8 functions that start with a percent, like %OptimizeFunctionOnNextCall.

If this all sounds interesting but you’re focused on client-side development, then you might like to look at the Web Tracing Framework from Google. It can use some of V8’s extra tracing options, and has both Chrome and Firefox extensions with rich instrumentation features. You’ll need to enable some flags to use it.

Node Roundup: husky, grunt-npmcopy

25 Jun 2014 | By Alex Young | Comments | Tags node modules npm grunt git

husky

husky (GitHub: typicode / husky, License: MIT, npm: husky) by typicode is a module for helping to avoid bad commits being pushed using Git hooks.

It basically sets up Git hooks for your Node projects:

So what makes husky different?

First, other modules often replace or delete existing hooks. husky won’t ever replace or modify an existing hook, so it’s a safer choice for a team or an open source project. In other terms, people who have set up their own hooks won’t be impacted by husky.

I think also that husky is more easier and straightforward to use compared to others. husky’s README is just a few lines and setting up hooks should be simple.

And last, usually other modules introduces unconventional package.json fields, husky uses only valid package.json fields.

grunt-npmcopy

grunt-npmcopy (GitHub: timmywil / grunt-npmcopy, License: MIT, npm: grunt-npmcopy) by Timmy Willison allows you to use the same package manager for Node and client-side projects. It helps place client-side dependencies in the right directory by using a Grunt task called npmcopy.

The npmcopy task takes source and destination options so you can avoid copying lots of extra files into your publicly accessible asset directories.

Have you ever wondered why we have so many package managers? NPM, Bower, Component. Why don’t we just pick one? Well, after much deliberation with developers like you, I’ve decided to support the idea that NPM might just be able to handle it all.

Small and Reusable Browser Modules: npm-dom

24 Jun 2014 | By Alex Young | Comments | Tags npm dom modules libraries

npm-dom (GitHub: npm-dom) by Azer Koçulu, Damon Oehlman, Max Ogden, Jake Verbaten, and Tim Oxley is a GitHub organisation that publishes DOM-related modules through npm.

So far there are small modules like new-element (https://github.com/npm-dom/new-element) and siblings (https://github.com/npm-dom/siblings), but also larger modules like domquery (https://github.com/npm-dom/domquery).

There are quite a few modules already. If you work with Browserify then you might like the way these modules can be consumed. As an example, take a look at class-list:

var elem = someElement;
var ClassList = require('class-list');
var cl = ClassList(elem);

cl.add('foo');
cl.remove('bar');
cl.toggle('baz');

Azer was inspired to create another organisation called npm-flickr, which is a set of Flickr-related libraries.

Gifffer, Composing Discrete Events with RxJS

23 Jun 2014 | By Alex Young | Comments | Tags gif animation reactive

Gifffer

Gifffer (GitHub: krasimir / gifffer, License: MIT) by Krasimir Tsonev is a small library for adding a play control to animated gifs. It works by drawing a play button over the image, and dynamically inserting an image element when play is clicked. To prevent the gif from playing when the page loads, the data-gifffer attribute is used instead of the src attribute.

Krasimir has a blog with gifs that illustrate browser features, so he wanted to be able to handle playing gifs more elegantly than the default behaviour. Here’s an example: Gifffer example. You can click it to toggle playback.

Composing Discrete Events with RxJS

Composing Discrete Events with RxJS by Sergey Bolshchikov is a post that compares addEventListener with RxJS. If you’ve ever used Reactive Extensions then you should be at home with the use of selectMany, combineLatest, and so on.

Here’s the full example:

var mouseDowns = Rx.Observable.fromEvent(document, 'mousedown');
var mouseMoves = Rx.Observable.fromEvent(document, 'mousemove');
var mouseUps = Rx.Observable.fromEvent(document, 'mouseup');

var moves = mouseDowns.selectMany(function(md) {
  var start = {
    x: md.clientX,
    y: md.clientY
  };
  return mouseMoves.combineLatest(mouseUps, function(mm, mu) {
    var stop = {
      x: mu.clientX,
      y: mu.clientY
    };
    return {
      start: start,
      stop: stop
    };
  }).takeUntil(mouseUps);
});

moves.subscribe(function(res) {
  var body = document.querySelector('body');
  body.innerHTML = 'Start: x = ' + res.start.x + ', y = ' + res.start.y + '; Stop: x = ' + res.stop.x + ', y = ' + res.stop.y;
});