Features Of ES6 Part 7: Template Literals

Thursday, September 18, 2014 by K. Scott Allen
2 comments

Template literals provide JavaScript with some basic string formatting capabilities. Just like many template technologies, template literals in JavaScript consist of literal text, and placeholders where the runtime can evaluate an expression to poke data into the text.

let name = "Scott";
let message = `Hello, ${name}!`;

expect(message).toBe("Hello, Scott!");

Backtick characters (`) enclose the entire template literal, while $ and {} denote the substitutions. Inside a substitution, you can use identifiers and expressions.

let showTheMath = function(x,y ){
    return `${x} + ${y} is ${x + y}';
};

let result = showTheMath(3,4);

expect(result).toBe("3 + 4 is 7");

Template literals can even span multiple lines.

let message = `This is
               a short, but multi-line message`;

Note that message will contain a newline character because newlines (and trailing spaces) are significant inside of a template literal.

Template literals are a useful addition to the language. However, template literals become exceptionally interesting when using them with a tag. We’ll look at tagged template literals next week.

Declarative Physics with PhysicsJS and AngularJS

Wednesday, September 17, 2014 by K. Scott Allen
0 comments

PhysicsJS + AngularJS One of the reasons for Angular’s success is the flexibility in the building blocks the framework provides. There is a delicate balance between productivity and flexibility. A heavily opinionated framework can be make a team highly productive, but the opinions can also make it harder to mix in additional features that conflict with the opinions, or sit outside the vision for the framework. Angular strikes a nice balance.

When I first thought about mixing PhysicsJS into an AngularJS application, I couldn’t see how a library based on timer ticks, frame rates, and a canvas could work with a framework like Angular, with its digest cycle and directives.

But, after 30 minutes I discovered that not only could these two work together, but Angular was flexible enough to provide some nice enhancements to the PhysicsJS experience.

Go to PhysicsJS + AngularJS to see the following code in action. The code is based on the tutorial “Creating a scene of colliding polygons”. 

Services

The first order of business is wrapping PhysicsJS components with services. Physics is the primary export of PhysicsJS, and this object provides factory methods to create shapes and behaviors. We can inject Physics into other components of the application that need to create shapes, but we’ll also create some additional services that use Physics to setup the “game loop” ticker and the world that contains all the shapes and behaviors for a scene.

var app = angular.module("app", []);

app.value("Physics", Physics);

app.factory("world", function (Physics) {
    var world = Physics();
    world.on("step", function () {
        world.render();
    });
    return world;
});

app.factory("ticker", function (Physics, world) {
    var start = function () {
        Physics.util.ticker.on(function (time) {
            world.step(time);
        });
        Physics.util.ticker.start()
    };

    return {
        start: start
    };
});

Directives

Directives can transform a PhysicsJS scene from imperative code and into a declarative language.  Here are a few simple directive definitions.

app.directive("physicsBehavior", function (Physics, world) {
    return {
        restrict: "E",
        scope: {
            name: "@"
        },
        link: function (scope) {
            world.add(Physics.behavior(scope.name));
        }
    };
});

app.directive("physicsBody", function (Physics, world) {
    return {
        restrict: "E",
        scope: {
            options: "=",
            body: "=",
            type: "@"
        },
        link: function (scope) {
            scope.body = Physics.body(scope.type, scope.options);
            world.add(scope.body);
        }
    };
});

These types of directives will let us write markup like the following.

<physics-canvas width="500" height="500">

    <physics-body type="rectangle" body="main.box1"
                  options="{x:450, y:10, vy:-0.3, width:5, height:5}">
    </physics-body>

    <physics-body type="rectangle" body="main.box2"
                  options="{x:250, y:210, vy:-0.3, width:5, height:5}">
    </physics-body>

    <physics-edge-detection min-x="0" min-y="0" max-x="500" 
                            max-y="500" restitution="0.3">
    </physics-edge-detection>

    <physics-behavior name="constant-acceleration"></physics-behavior>
    <physics-behavior name="body-impulse-response"></physics-behavior>
    <physics-behavior name="body-collision-detection"></physics-behavior>
    <physics-behavior name="sweep-prune"></physics-behavior>

</physics-canvas>

Controllers

Controllers can build models that interact with objects in the PhysicsJS world. The API allows us to apply forces and change the geometry of objects. One difficulty I did have is seeing the updated appearance of a shape after changing attributes. The code needs to set the view property of a shape to null for changes to attributes like width and height to appear. PhysicsJS will recreate the view on the next tick. 

model.kick = function () {
    model.box1.applyForce({x: 0.1, y: -0.2});
    model.box2.applyForce({x: -0.1, y: -0.2});
};

model.grow = function () {
    model.box1.geometry.width *= 1.5;
    model.box1.geometry.height *= 1.5;
    model.box1.mass *= 1.5;
    model.box1.view = null;
    model.box1.recalc();
};

But What About The Digest?

Anyone who has worked with jQuery widgets or native events knows that Angular needs to know when model data changes in order to update the DOM with new model values. Generally we accomplish this goal by wrapping code inside a scope’s $apply method.

The interesting thing about working with PhysicsJS is that the physics engine is constantly updating a canvas based on a timer, so it is not necessary for Angular to know about changes in shape properties, like position and acceleration. It just works.

Summary

Although there would be a lot more work needed to make a complete and general purpose wrapper for PhysicsJS, the integration with an Angular app works in a straightforward manner. 

C# 6.0 Features Part 3: Declaration Expressions

Monday, September 15, 2014 by K. Scott Allen
8 comments

In C# we’ve always had declaration statements for declaring variables, and expression statements to produce values.

In C# 6 we can mix a declarations with an expression to declare a new variable and produce a value.

The canonical example is the int.TryParse method, which requires an out parameter. In previous versions of C# the parameter would be declared in a distinct statement before the invocation of TryParse.

int result;
if(int.TryParse(input, out result))
{
    return result;
}
return 0; // note: result still in scope

With C# 6.0, the same result is achievable with a declaration expression. The declaration statement also limits the scope of the variable passed as an out parameter.

if (int.TryParse(input, out var result))
{
    return result;
}
return 0; // result is out of scope

We could also transform the above code into a one-liner. . .

return int.TryParse(input, out var result) ? result : 0;

. . . and then package it into an extension method for string.

public static int ParseIntSafe(this string input, int @default = 0)
{
    return int.TryParse(input, out var result) ? result : @default;
}

With declaration expressions we can also declare variables inside if statements . . .

if ((var address = user.HomeAddress) != null)
{
    // work with address ...

    return address.City;
}

. . . and the various looping statements.

int result = 0;
foreach (var n in var odd = numbers.Where(n => n % 2 == 1).ToList())
{ 
    result += n + odd.Count();
}
return result;

Declaration are a small addition to the C# language, but will come in useful in a few scenarios.

Features Of ES6 Part 6: Destructuring

Thursday, September 11, 2014 by K. Scott Allen
3 comments

To destructure an object is to dismantle or tear apart an object.

In ES6, a destructuring assignment allows us to tear apart an array or object into individual pieces that we can assign to variables. The square brackets [ and ] are used to destructure an array, while { and } will destructure an object.

The following code will destructure an array so that x contains 22 and y contains 44.

let values = [22, 44];
let [x, y] = values;

expect(x).toBe(22);
expect(y).toBe(44);

You can think of [ and ] in the first line of code as the symbols used to construct an array. The [ and ] on the second line of code tear apart the array and declare two variables to hold the pieces.

Destructuring objects follows the same pattern, but will use { and }.

var person = { firstName: "Scott", lastName: "Allen" };
var {firstName, lastName} = person;

expect(firstName).toBe("Scott");
expect(lastName).toBe("Allen");

You do not need to use let or var with destructuring to create new variables, you can also destructure into existing variables.

let x = 10, y = 20;

// swap!!
[x,y] = [y,x];

expect(x).toBe(20);
expect(y).toBe(10);

You can also destructure arrays and objects returned from a function call.

var doWork = function() {
    return [1, 3, 2];
};

let [, x, y, z] = doWork();

expect(x).toBe(3);
expect(y).toBe(2);
expect(z).toBeUndefined();

Note a couple special properties in the destructuring of doWork’s result. First, the opening comma will skip the first array element, and you can use additional commas anywhere to skip additional elements. Secondly, if there are not enough array elements to satisfy all the variables required by the destructuring, the extra variables will receive the value undefined.

You can also destructure in a function parameter list.

let doWork = function({firstName, lastName, role="developer"}) {
    return role + " " + firstName + " " + lastName;
};

let person = {firstName: "Scott", lastName: "Allen"};
let result = doWork(person);

expect(result).toBe("developer Scott Allen");

The above example also uses a default parameter value to assign “developer” to the role parameter in case the incoming object does not have a role property (otherwise, role would receive the value undefined). Default parameters are not restricted to function declarations when using destructuring.

let address = { state:"Maryland" };
let { state="New York", country="USA"} = address;

expect(state).toBe("Maryland");
expect(country).toBe("USA");

Rest parameters can also capture the remaining elements of an array.

let odds = [1,3,5,7,9];
let [first, second, ...rest] = odds;

expect(first).toBe(1);
expect(second).toBe(3);
expect(rest).toEqual([5,7,9]);

Destructuring can also drill into complex objects, even objects with collections inside.

let employee = {
    firstName: "Scott",
    address: {
        state: "Maryland",
        country: "USA"
    },
    favoriteNumbers: [45,55,32,13]
};

let { firstName, address: {state}, favoriteNumbers: [,second]} = employee;

expect(firstName).toBe("Scott");
expect(state).toBe("Maryland");
expect(second).toBe(55);
The Significance of Destructuring

One area where destructuring will lead to more maintainable code is in the use of configuration objects, like the configuration objects you typically pass to HTTP communication methods like jQuery’s ajax method. Finding the available options and their defaults is often difficult when using such a method, and maintaining the options and defaults can be tricky as an author. With destructuring, configuration options and defaults become more explicit.

let httpPost = function(
        url, {
        cache = true,
        contentType = "application/json",
        timeout = 2500,
        headers = {},
        // ...
    }) {
        // ...
};

We’ll also see other uses for destructuring as we move through additional features of ES6, like modules.

A Journey With Trusted HTML in AngularJS

Wednesday, September 10, 2014 by K. Scott Allen
2 comments

AngularJSAngularJS  provides protection against cross-site scripting attacks by default.  Let’s look at some examples.

HTML Entity Encoding With ngBind

Consider the following controller which maintains a collection of strings with HTML inside. Perhaps the strings arrived in the controller as the result of an HTTP call, or perhaps the controller built the strings dynamically. In either case, the controller wants the links to display as clickable navigation links in a browser.

app.controller("mainController", function() {
    var main = this;

    main.links = [
        "<a href='http://google.com'>Google</a>",
        "<a href='http://odetocode.com'>OdeToCode</a>",
        "<a href='http://twitter.com'>Twitter</a>",
    ];
});

In the view, we’ll use a {{bind expression}} to display the links.

<section ng-controller="mainController as main">

    <nav>
        <ul>
            <li ng-repeat="link in main.links">{{link}}</li>
        </ul>
    </nav>

</section>

HTML Encoded with ngBind The links will appear as inert text (see the figure to the right), because interpolation with ngBind will produce encoded text.

Technically, this isn’t because of any special code inside of the ngBind directive, but because ngBind uses jqLite’s .text method, which ultimately sets the textContent property of the associated element.

Render HTML with ngBindHtml

Instead of using ngBind, the view can use ngBindHtml to render the links as real, clickable anchor tags.

<ul>
    <li ng-repeat="link in main.links"
        ng-bind-html="link">
    </li>
</ul>

However, making only this change in the view will result in an error.

Error: [$sce:unsafe] Attempting to use an unsafe value in a safe context.

Angular will only render “safe” HTML into the DOM. If you are looking for a quick fix to this error, just read the “Sanitized HTML” section below.

From a developer’s perspective, there are two general categories of “safe” HTML in Angular.

  1. Explicitly trusted HTML is safe
  2. Sanitized HTML is safe

Let’s look at #2 first.

Sanitizing HTML

Synonyms for sanitize include “sterilize”, “disinfect”, “clean”, “cleanse”, and “purify”. All of these synonyms are capable words for describing the process of making HTML “safe” for display. Being “safe” means the HTML won’t carry script code into the DOM, because script code is dangerous if the script comes from the wrong place.

AngularJS includes a $sanitize service that will parse an HTML string into tokens and only allow safe and white-listed markup and attributes to survive, thus sterilizing a string so the markup contains no scripting expressions or dangerous attributes.

Angular will consider HTML processed by $sanitize as trusted.

The ngBindHtml directive will use the $sanitize service implicitly, however, the $sanitize service is not part of the core ng module, so an additional script needs to be added into the page.

<script src="angular.js"></script>
<script src="angular-sanitize.js"></script>
<script src="app.js"></script>

Then when registering the application module, the code must list ngSantize as a dependency.

var app = angular.module("app", ["ngSanitize"]);

Render sanitized HTML with ngBindHtml With these changes in place, the app will now render proper links.

So what was sanitized?

Watching $sanitize

One way to see how and when $sanitize works is to decorate the $sanitize service (which is a function object).

var app = angular.module("app", ["ngSanitize"]);

app.config(function($provide){
    $provide.decorator("$sanitize", function($delegate, $log){
        return function(text, target){

            var result = $delegate(text, target);
            $log.info("$sanitize input: " + text);
            $log.info("$sanitize output: " + result);

            return result;
        };
    });
});

Now let’s use the following link collection inside the controller. Notice each link has some attribute present.

app.controller("mainController", function() {

    var main = this;
    main.links = [
        "<a onmouseover='...' href='http://google.com'>Google</a>",
        "<a class='...' href='http://odetocode.com'>OdeToCode</a>",
        "<a ng-click='...' href='http://twitter.com'>Twitter</a>"
    ];
});

With the decorator, we can see exactly what goes into $sanitize, and what comes out. The mouseover attributes disappear, as does the ng-click directive.

$sanitize input: <a onmouseover='...' href='http://google.com'>Google</a> 
$sanitize output: <a href="http://google.com">Google</a> 

$sanitize input: <a class='...' href='http://odetocode.com'>OdeToCode</a>
$sanitize output: <a class="..." href="http://odetocode.com">OdeToCode</a>

$sanitize input: <a ng-click='...' href='http://twitter.com'>Twitter</a>
$sanitize output: <a href="http://twitter.com">Twitter</a> 

While $sanitize can provide trusted HTML for Angular to render, it does so by modifying the HTML. If we really want to render HTML without encoding and without sanitization, we have to turn to what I referred to as category #1 earlier – explicitly marking the HTML as “trusted”.

Explicitly Trusting HTML With $sce

When you want Angular to render model data as HTML with no questions asked, the $sce service is what you’ll need. $sce is the Strict Contextual Escaping service – a fancy name for a service that can wrap an HTML string with an object that tells the rest of Angular the HTML is trusted to render anywhere.

In the following version of the controller, the code asks for the $sce service and uses the service to transform the array of links into an array of trusted HTML objects using $sce.trustAsHtml.

app.controller("mainController", function($sce) {

    var main = this;
    main.links = [
        "<a onmouseover='alert(\"careful!\")' href='http://google.com'>Google</a>",
        "<a href='http://odetocode.com'>OdeToCode</a>",
        "<a href='http://twitter.com'>Twitter</a>"
    ];

    for (var i = 0; i < main.links.length; i++) {
        main.links[i] = $sce.trustAsHtml(main.links[i]);
    }
});

The only difference between this version of the controller code and the previous version is the for loop to mark the strings as trusted. When binding to each trusted link using ngBindHtml, the HTML will no longer go through the $sanitize service. This means the first link will now enter the DOM with an onmouseover attribute and carry along executable JavaScript code. Be careful!

Bonus: Compiling Trusted HTML

Instead of using onmouseover or onclick attributes, let’s say we have some strings on our controller that want to follow the “Angular Way” and use ngClick or ngMouseover.

app.controller("mainController", function($sce, $log) {

    var main = this;
    main.links = [
        "<a ng-click='main.go(\"google\")' href=''>Google</a>",
        "<a ng-click='main.go(\"otc\")' href=''>OdeToCode</a>",
        "<a ng-click='main.go(\"twitter\")' href=''>Twitter</a>"
    ];

    for (var i = 0; i < main.links.length; i++) {
        main.links[i] = $sce.trustAsHtml(main.links[i]);
    }

    main.go = function(name){
       $log.info("Goto: " + name);
    };
});

If these links pass through the $sanitize service, the sanitizer will remove ng-click and other attribute directives. Fortunately, the controller marks the HTML as trusted so they will render with ngClick. However, clicking will not work since Angular doesn’t compile the markup after it enters the DOM with ngBindHtml.

The solution is to use a custom directive in combination with $sce and trusted HTML.

app.directive("compileHtml", function($parse, $sce, $compile) {
    return {
        restrict: "A",
        link: function (scope, element, attributes) {

            var expression = $sce.parseAsHtml(attributes.compileHtml);

            var getResult = function () {
                return expression(scope);
            };

            scope.$watch(getResult, function (newValue) {
                var linker = $compile(newValue);
                element.append(linker(scope));
            });
        }
    }
});

Now the view looks like:

<ul>
    <li ng-repeat="link in main.links"
        compile-html="link">
    </li>
</ul>

Features Of ES6 Part 5: The Spread

Tuesday, September 2, 2014 by K. Scott Allen
2 comments

The spread operator shares the same syntax we saw with rest parameters, a series of three dots (...). However, a rest parameter will collect individual parameters into an array when you use the dots in a function parameter definition, while the spread operator expands an array into individual parameters when using the dots in a function call.

let doWork = function(x, y, z) {
    return x + y + z;
}

var result = doWork(...[1, 2, 3]);
expect(result).toBe(6);

In the above code, the spread operator will “spread” the array of three values across the parameters x, y, and z.

The spread operator can also expand an array to create individual elements in an array literal.

var a = [4, 5, 6]; 
var b = [1, 2, 3, ...a, 7, 8, 9]; 

expect(b).toEqual([1,2,3,4,5,6,7,8,9]);

Although the examples here are all using the spread operator with an array, the spread operator also works with any iterable object. We’ll look at iterable objects in a future post.

The Impact of the Spread

Before rest parameters and the spread operator came along, Function.apply and the implicit arguments variable were widely used to accept an unknown number of arguments to a function and pass the arguments along to another function, like in the example below.

var doWork = function(x, y, z){
    return x + y + z;
}

var doSomething = function(){
    return doWork.apply(null, arguments);
}

var result = doSomething(...[1,2,3,4,5]);
expect(result).toBe(6);

The implementation of doSomething is cleaner and more obvious when using a rest parameter and the spread.

var doWork = function(x, y, z){
    return x + y + z;
}

var doSomething = function(...args){
    return doWork(...args);
}

var result = doSomething(...[1,2,3,4,5]);
expect(result).toBe(6);

Notice that when using the spread (or apply), you can have more values in the array than the destination function requires. The spread will start from the beginning of the array to populate parameters, so in the above example, doWork will see the first three values in the array.

Karma Is Not Just For AngularJS

Tuesday, August 19, 2014 by K. Scott Allen
4 comments

The AngularJS team created Karma, but Karma isn’t tied to AngularJS. As a test runner, I can use Karma to run tests against any JavaScript code using a variety of testing frameworks in a variety of browsers. All I need is Node.js.

Pretend I am writing code to represent a point in two dimensional space. I might create a file point.js.

var Point = function(x,y) {
    this.x = x;
    this.y = y;
}

I’ll test the code using specifications in a file named pointSpecs.js.

describe("a point", function() {
    it("initializes with x and y", function() {
        var p1 = new Point(3,5);
        
        expect(p1.x).toBe(3);
        expect(p1.y).toBe(5);
    });
});

What Karma can do is:

- Provide web browsers with all of the HTML and JavaScript required to run the tests I’ve written.

- Automate web browsers to execute all the tests

- Tell me if the tests are passing or failing

- Monitor the file system to re-execute tests whenever a file changes.

Setup

The first step is using npm to install the Karma command line interface globally, so I can run Karma from anywhere.

npm install karma-cli –g

Then I can install Karma locally in the root of my project where the Point code resides.

npm install karma --save-dev

Karma requires a configuration file so it knows what browsers to automate, and which files I’ve authored that I need Karma to load into the browser. The easiest way to create a basic configuration file is to run karma init from the command line. The init command will walk you through a series of questions to create the karma.conf.js file. Here is a sample session.

>karma init 

Which testing framework do you want to use ?
Press tab to list possible options. Enter to move to the next question.
> jasmine 

Do you want to use Require.js ?
This will add Require.js plugin.
Press tab to list possible options. Enter to move to the next question.
> no 

Do you want to capture any browsers automatically ?
Press tab to list possible options. Enter empty string to move to the next question.
> PhantomJS
> Chrome
> 

What is the location of your source and test files ?
You can use glob patterns, eg. "js/*.js" or "test/**/*Spec.js".
Enter empty string to move to the next question.
> js/**/*.js
> specs/**/*.js
> 

Should any of the files included by the previous patterns be excluded ?
You can use glob patterns, eg. "**/*.swp".
Enter empty string to move to the next question.
> 

Do you want Karma to watch all the files and run the tests on change ?
Press tab to list possible options.
> yes 

Config file generated at "C:\temp\testjs\karma.conf.js".

I can open the config file to tweak settings and maintain the configuration in the future. The code is simple.

module.exports = function(config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine'],
    files: [
      'js/**/*.js',
      'specs/**/*.js'
    ],
    exclude: [
    ],
    preprocessors: {
    },
    reporters: ['progress'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['PhantomJS', 'Chrome'],
    singleRun: false
  });
};

Note that when I enter the location of the source and test files, I want to enter the location of the source files first. It’s helpful if you can organize source and test files into a directory structure so you can use globbing (**) patterns, but sometimes you need to explicitly name individual files to control the order of loading.

At this point I can start Karma, and the tests will execute in two browsers (Chrome, which I can see, and PhantomJS, which is headless). I’d probably tweak the config file to only use Phantom in the future.

Karma in action!

Now, Karma will continuously run tests in the background while I work.

Easy!

by K. Scott Allen K.Scott Allen
My Pluralsight Courses
The Podcast!