Using eslint with Webpack

This morning I realized my eslint configuration was not running. I had set up the wrong command in the pretest script of my package.json and as a result none of the files were being run through eslint – it was just silently failing. My old gulp configuration had a gulp.src() definition that used globbing to find the files, so eslint was always fed a list of files rather than having to do a recursive search. I discovered this quite by accident. I had added a stage-1 proposal for static class properties to my BabelJS configuration and not updated by eslint configuration to compensate for this. I expected an error – I didn’t get one. What doesn’t happen is relevant too.

Wouldn’t it be nice if Webpack could do some pre-tests on my files prior to loading them?

Well, it turns out that this is possible. Like many things in Webpack, it turned out to be really easy. First of all, I needed a new loader for eslint:

npm install --save-dev eslint-loader

This should be fairly common now. There is an extensive list of pluggable loaders available for Webpack, just like there are plugins for grunt, gulp and browserify. It seems every single tool must be extensible these days – something I really like about the ecosystem. Now, on to the configuration within webpack.config.js:

var ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
    entry: {
        grumpywizards: './client/src/app.jsx'
    },
    devtool: 'source-map',
    module: {
        preLoaders: [
            // Javascript
            { test: /\.jsx?$/, loader: 'eslint', exclude: /node_modules/ }
        ],
        loaders: [
            // Javascript
            { test: /\.jsx?$/, loader: 'babel', exclude: /node_modules/ },
            // Stylesheets
            { test: /\.css$/, loader: ExtractTextPlugin.extract( 'style', 'css?sourceMap') },
            { test: /\.scss$/, loader: ExtractTextPlugin.extract( 'style', 'css?sourceMap!sass?sourceMap') },
            // Font Definitions
            { test: /\.svg$/, loader: 'url?limit=65000&mimetype=image/svg+xml&name=public/fonts/[name].[ext]' },
            { test: /\.woff$/, loader: 'url?limit=65000&mimetype=application/font-woff&name=public/fonts/[name].[ext]' },
            { test: /\.woff2$/, loader: 'url?limit=65000&mimetype=application/font-woff2&name=public/fonts/[name].[ext]' },
            { test: /\.[ot]tf$/, loader: 'url?limit=65000&mimetype=application/octet-stream&name=public/fonts/[name].[ext]' },
            { test: /\.eot$/, loader: 'url?limit=65000&mimetype=application/vnd.ms-fontobject&name=public/fonts/[name].[ext]' }
        ]
    },
    externals: {
        'react': 'React',
        'react-dom': 'ReactDOM'
    },
    output: {
        filename: 'public/[name].js'
    },
    eslint: {
        failOnWarning: false,
        failOnError: true
    },
    sassLoader: {
        includePaths: [ 'client/style' ]
    },
    plugins: [
        new ExtractTextPlugin('public/grumpywizards.css')
    ]
};

Lines 9-12 pull in a new section called preloaders. These are still a list of loaders but they are run before the loaders section. There is another section called postLoaders – you can guess what that does. I also needed to configure what happens when eslint fails. By default, things just carry on. I want to ensure that the build carries on if there is a warning (the warnings will still be printed), but an error stops the build. Unfortunately, loaders operate on a per-file basis, so this is really “stop on the first error”.

There was one other change to support Webpack I needed to make – to my .eslintrc.js. I use require() to bring in the stylesheets within my JSX files. I could switch them all over to use import (the ES6 method) but I like the require method as it puts a visual distinction for me within my code. I needed to add the commonjs environment to the .eslintrc.js file in client/src:

var OFF = 0, WARN = 1, ERROR = 2;

module.exports = exports = {
    env: {
        'es6': true,        // We are writing ES6 code
        'browser': true,    // for the browser
        'commonjs': true    // and use require() for stylesheets
    },
    ecmaFeatures: {
        'jsx': true,
        'modules': true
    },
    plugins: [
        'react'
    ],

Don’t forget to also set up your eslint settings for stage-1 proposals. You can get the code so far from my GitHub Repository.

An ECMAScript 6, CommonJS and RequireJS Project

I’ve been writing a lot of CommonJS code recently – the sort that you would include in Node projects on the server side. I’ve recently had a thought that I would like to do a browser-side project. However, how do you produce a browser library that can be consumed by everyone?

The different styles of modules

Let’s say I have a class Client(). If I were operating in Node or Browserify, I’d do something like this:

var Client = require('my-client-package');

var myclient = new Client();

This is called CommonJS format. I like it – it’s nice and clean. However, that’s not the only way to potentially consume the library. You can also bring it in with RequireJS:

define(['Client'], function(Client) {
    var myclient = new Client();

});

Finally, you could also register the variable as a global and bring it in with a script HTML tag:

<script src="node_modules/my-client-package/index.js"></script>
<script>
    var client = new Client();
</script>

You can find a really good writeup of the differences between CommonJS and AMD in an article by Addy Osmani.

Three different techniques. If we were being honest, they are all valid and have their place, although you might have your favorite technique. As a library developer, I want to support the widest range of JavaScript developers which means supporting three different styles of code. This brings me to UMD format. I named it “Ugly Module Definition”, and you can see why when you look at the code:

(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define(['b'], function (b) {
            return (root.returnExportsGlobal = factory(b));
        });
    } else if (typeof module === 'object' && module.exports) {
        // Node. Does not work with strict CommonJS, but
        // only CommonJS-like enviroments that support module.exports,
        // like Node.
        module.exports = factory(require('b'));
    } else {
        // Browser globals
        root.returnExportsGlobal = factory(root.b);
    }
}(this, function (b) {
    // Use b in some fashion

    return {// Your exported interface };
}));

Seriously, could this code be any uglier? I like writing my code in ECMAScript 2015, also known as ES6. So, can I write a class in ES6 and then transpile it to the right format? Further, can I set up a project that has everything I need to test the library? It turns out I can. Here is how I did it.

Project Setup

These days, I tend to create a directory for my project, put some stuff in it and then push it up to a newly created GitHub repository. I’m going to assume you have already created a GitHub user and then created a GitHub repository called ‘my-project’. Let’s get started:

mkdir my-project
cd my-project
git init
git remote add origin https://github.com/myuser/my-project
npm init --yes
git add package.json
git commit -m "First Commit"
git push -u origin master

Perhaps unshockingly, I have a PowerShell script for this functionality since I do it so often. All I have to do is remember to check in things along the way now and push the repository to GitHub at the end of my work.

My Code

I keep my code in the src directory, The tests are in the test directory. The distribution file is in the dist directory. Let’s start with looking at my src/Client.js code:

export default class Client {
    constructor(options = {}) {
    }
}

Pretty simple, right? The point of this is not to concentrate on code – it’s about the build process. I’ve also got a test in the test/Client.js file:

/* global describe, it */

// Testing Library Functions
import { expect } from 'chai';

// Objects under test
import Client from '../src/Client';

describe('Client.js', () => {
    describe('constructor', () => {
        it('should return a Client object', () => {
            let client = new Client();
            expect(client).to.be.instanceof(Client);
        });
    });
});

I like to use Mocha and Chai for my tests, so this is written with that combination in mind. Note the global comment on the first line – that prevents Visual Studio Code from putting green squiggles underneath the mocha globals.

Build Modules

I decided some time along the way that I won’t use gulp or grunt unless I have to. In this case, I don’t have to. My toolset includes:

Let’s take a look at my package.json:

{
    "name": "my-project",
    "version": "0.1.0",
    "description": "A client library written in ES6",
    "main": "dist/Client.js",
    "scripts": {
        "pretest": "eslint src test",
        "test": "mocha",
        "build": "babel src --out-file dist/Client.js --source-maps"
    },
    "keywords": [
    ],
    "author": "Adrian Hall <adrian@shellmonger.com>",
    "license": "MIT",
    "devDependencies": {
        "babel-cli": "^6.3.17",
        "babel-plugin-transform-es2015-modules-umd": "^6.3.13",
        "babel-preset-es2015": "^6.3.13",
        "babel-register": "^6.3.13",
        "chai": "^3.4.1",
        "eslint": "^1.10.3",
        "mocha": "^2.3.4"
    },
    "babel": {
        "presets": [
            "es2015"
        ],
        "plugins": [
            "transform-es2015-modules-umd"
        ]
    }
}

A couple of regions need to be discussed here. Firstly, I’ve got two basic npm commands I can run:

  • npm test will run the tests
  • npm run build will build the client library

I’ve got a bunch of devDependencies to implement this build system. Also note the “babel” section – this is what would normally go in the .babelrc – you can also place it in your package.json file.

The real secret sauce here is the build script. This uses a module transform to create a UMD format library from your ES6 code. You don’t even have to worry about reading that ES5 code – it’s ugly, but it works.

Editor Files

I use Visual Studio Code, so I need a jsconfig.json file in the root of my project:

{
    "compilerOptions": {
        "target": "ES6"
    }
}

This tells Visual Studio Code to use ES6 syntax. I’m hopeful the necessity of this will go away soon. I’m hoping that I’m not the only one who is contributing to this repository. Collaboration is great, but you want to set things up so that people coming newly in to the project can get started with your coding style straight away. I include a .editorconfig file as well:

root = true

[*]
charset = utf-8
indent_style = space
indent_size = 4
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

[*.json]
insert_final_newline = false

You can read about editorconfig files on their site. This file is used by a wide variety of editors – if your editor is on the list, you should also install the plugin.

ESLint Configuration

I have a .eslintrc.js file at the root of the project. I’ve got that in a gist since it is so big and I just cut and paste it into the root directory.

Test Configuration

My test directory is different – it expects to operate within mocha, so I need an override to tell eslint that this is all about mocha. Here is the test/.eslintrc file:

module.exports = exports = {
    "env": {
        "es6": true,
        "mocha": true
    }
};

I also need a mocha.opts file to tell mocha that the tests are written in ES6 format:

--compilers js:babel-register

Wrapping up

You will need a dist directory. I place a README.md file in there that describes the three use cases for the library – CommonJS, AMD and globals. That README.md file is really only there to ensure the dist directory exists when you clone the repository.

I also need to add a README.md at the root of the project. It’s required if I intend to publish the project to the NPM repository. Basic instructions on how to install and use the library is de rigeur, but you can put whatever you want in there in reality.

I have not addressed jsdoc yet – you should be doing it in your source files, and it should be a postbuild step in your package.json file.

You can now run the tests and build through the npm commands and get a library that can be used across the board.

Managing Coding Style in JavaScript with eslint

I’m a big fan of linters, especially in the case of JavaScript.  Most languages are statically typed and have fairly well known and rigid formatting.  This allows consumers of the language to read source code and easily digest what it is doing.  Not so JavaScript.  Some of the code is so badly written that you have to run it to figure it out. Naturally, I want to avoid writing bad code, so the use of linters is mandatory.

JavaScript linters, including JSLint, JSHint and my favorite – ESLint, provide many functional benefits to you by statically analyzing your code.  They can uncover a slew of issues before you even run the code.  ESLint breaks down the rules (there are over 200 rules in the default set) into three major areas – potential errors, best practices and style. I use eslint because it supports ES2015 and React/JSX out of the box.

If you use an alternative, then you have:

There really is no good reason to NOT use a linter.

Let’s take a quick step back and go through how you use this.  Firstly, you need to install eslint:

npm install -g eslint

Then you need to create a configuration file.  I prefer my configuration file to be in JavaScript – it allows me to document the configuration so that I remember why I put a particular setting in there.  The filename of the configuration file is .eslintrc.js.  You can find my as a gist on github.com. The basics of this file are here:

var OFF = 0, WARN = 1, ERROR = 2;

module.exports = exports = {
    "env": {
        "es6": true,
        "browser": true,
        "commonjs": true
    },

    "ecmaFeatures": {
        // env=es6 doesn't include modules, which we are using
        "modules": true
    },

    "extends": "eslint:recommended",

    "rules": {
        // Put your overrides here
    }
};

You can use the keywords OFF, WARN and ERROR instead of the numeric values in the rule overrides, as we will see later.
You can then override the default handling of any rules in
the rules section. You can run this by using:

eslint src

The eslint program looks for several config files, but the JavaScript version is the first one that it looks for. It will also look in parent directories for a suitable file, so you can set up your rules at the top of your project and have the settings work for all files. I tend to place my .eslintrc.js file in the src directory as my Gulpfile.js, tests and so on require different rules.

Back to those three areas. The first area is Possible Errors. Most of these are enabled as errors in the recommended set. You will probably want to override the ones that aren’t in the recommended set – they are useful.

The second set is Best Practices. I read the description of each rule in the set and made a judgement call on whether the rule would be an error or a warning or turned off. Most rules are simple. For example, I don’t want to ship a product with alert() calls, so I have the following override:

"no-alert": ERROR,

Some rules have additional information and you have to read the rule details for that information. An example of this is the accessor-pairs rule. This covers getters and setters. One of the things I like to do is have class properties written as accessors. This allows me to provide a “read-only” property by only specifying a getter. Thus my rule is:

"accessor-pairs": [ ERROR, {
    "getWithoutSet": false,
    "setWithoutGet": true
}],

This says that I can have just a getter or a getter and a setter. I cannot have a setter without a getter. I prefer best practices to be errors by default and need to justify to myself why something should be a warning.

The final section is Stylistic. Pretty much every development group has a coding style guide. It goes into things about where curly-braces should be, what sort of quotes to use, how to name variables, whether to use tabs or spaces for indents and so on. This section (which is the bulk of the rules) allow you to enforce this coding style. In this section, I prefer things to be warnings and have to justify errors. The difference here is that the code will still work – it’s just coding style.

I run eslint before I do anything else on a compilation. I have two mechanisms for handling builds. In the first mechanism, I use the package.json to build the code and eschew a task runner. This is generally for smaller projects. In this case, I put the eslint call in the package.json scripts section, like this:

  "scripts": {
    "pretest": "eslint src test",
    "test": "mocha"
  },

If I am doing a build, I’m usually using a task runner – gulp is my task runner of choice. In this case, I have a task to do the eslint for me:

var gulp = require('gulp'),
    eslint = require('gulp-eslint');

var config = {
    paths: {
        src: './src/**/*.js',
        dest: './dist'
    }
};

gulp.task('lint', function () {
    return gulp.src([ config.paths.src, '!**/.eslintrc.js' ])
        .pipe(eslint())
        .pipe(eslint.format())
        .pipe(eslint.failAfterError());
});

gulp.task('build', [ 'lint' ], function () {
    // my build process here
});

The gulp.src line explicitly ignores your .eslintrc file – it’s a circular reference and tends to not follow style, surprisingly.

There will come a time when you want to override a rule for a specific case. I always do something like the following when I do this:

// lint-disable: foobar is an external library (new-cap)
var x = new foobar(); //eslint-disable-line new-cap

Note two things here. Firstly, I say why the rule was disabled. This prevents any guessing on the part of people that come after me. I also prefix the the line with lint-disable so that I can easily grep the entire source tree for lint-disable to get all the lines. Secondly, I only disable the rule on one line. This is the preferred method.

Sometimes I need to disable a rule for a whole function; I use a block disable. This has to be even rarer and again needs to be documented:

/* eslint-disable id-length */
/* lint-disable id-length - the library foobar has this identifier */
function myfoo() {
  foobar.aReallyLongIdentifierUsedByFooBarIsObnoxiousButRequired = false;
}
/* eslint-enable id-length */

You should (and can easily) audit all the lint-disable lines and blocks on a regular basis.

So, how do I use eslint?

  • eslint the source before every build and test – fix errors
  • eslint the source before every check in – fix warnings
  • audit the source for lint-disable before every release

There are a few things more important than static analysis of your code, but it’s right up there with testing. You need to be linting your JavaScript code on a very regular basis. Automate your usage of eslint (or another JavaScript linter) so that it’s a part of your build process.

Visual Studio Code and Trimming Whitespace

Have you noticed that eslint doesn’t like trailing whitespace. It has a rule for it: the no-trailing-spaces rule.

Normally, this wouldn’t be a problem. I’m normally using Visual Studio 2015. Visual Studio takes care of it. Firstly, when you are typing JavaScript, the editor properly indents and doesn’t give you blank lines with spaces on it. Secondly, I have a plug-in called the Trailing Spaces Visualizer – it’s an extension that highlights trailing spaces.

This is all well and good, but I’m using Visual Studio Code now since it actually supports ECMAScript 2015. When you hit enter twice (to create a blank line), the blank line has spaces up to the indent level of the prior line and eslint complains of trailing spaces.

Fortunately, there are a good couple of options here. Option 1 is to trim the lines. Press Ctrl + Shift + X in the editor and the current buffer will be trimmed. You can rebind this to something else by editing your keybindings.json to something like this:

[{ 
  "key": "shift+f12",
  "command": "editor.action.trimTrailingWhitespace",
  "when": "editorTextFocus"
}]

You can open up your personal keybindings.json using File -> Preferences -> Keyboard Shortcuts.

Option 2 is to automatically trim the white space on save. Do this by editing your user preferences (under File -> Preferences -> User Settings). Add the following to the file:

{
  "files.trimTrailingWhitespace": true
}

Your final option is to disable the rule in question. You can do this on a per-file basis or via the .eslintrc file in your top level directory, like this:

{
  "env": {
    "node": true,
    "es6": true
  },
  "ecmaFeatures": {
    "modules": true
  },
  "rules": {
    "no-trailing-spaces": 0,
    "global-strict": 0,
    "strict": [ 2, "global" ]
  }
}

If you are coding in ECMAScript 2015, don’t forget to also configure VS Code to recognize the new language constructs. You can do this by creating a jsconfig.json file in your project root. It should have the following contents:

{
	"compilerOptions": {
		"target": "ES6",
		"module": "commonjs"
	}
}

Once you have created the file and saved it, restart VS Code and the new language constructs will be recognized.

ASP.NET MVC6 Identity Part 4 – AJAX Authentication

In the last few articles, I’ve covered the following:

  1. Creating an ASP.NET Identity Database
  2. Data Annotations and Custom Validators for Models
  3. A WebAPI Authenticator
  4. An ECMAScript 6 Modal Dialog

Four articles and I still haven’t logged in to my application. Today that is going to change because I’m writing the front-end AJAX code to do the authentication handling.

Doing AJAX Request Promises

Some months ago, I wrote about doing ECMAScript 6 HTTP Requests with Promises. I have a library for that now and I’m going to use it in this project. It’s stored in Static/js/ajax.js. Let’s walk through it:

/**
 * Routines for dealing with AJAX
 */
/*eslint no-console:0 */
"use strict";

function callAjax(method, url, query, body, headers) {
    console.debug("[callAjax] method=%s url=%s query=%o body=%o headers=%o", method, url, query, body, headers);

One method is all it takes to handle all the AJAX functionality. Note that I’m using an eslint directive at the top to say “I’m going to use console statements, so be quiet about it”. When I change over to a non-debug version, I’ll remove that line and all the console statements.

    let uri = url;
    if (query != null) {
        console.debug("[callAjax] query has been specified - processing");
        if (typeof query === "object") {
            console.debug("[callAjax] query is an object");
            let qs = Object.keys(query).map(k =&gt; encodeURIComponent(k) + "=" + encodeURIComponent(query[k]));
            uri = uri + "?" + qs.join("&amp;");
        }
        else if (typeof query === "string") {
            // Assume the query string is already encoded
            console.debug("[callAjax] query is a string (adding unmodified)");
            uri = uri + "?" + query;
        }
        console.debug("[callAjax] New URI is %s", uri);
    }

The next block turns an object, say {"Email":"foo","Password":"bar"} into the appropriate URI encoded query string Email=foo&Password=bar. If the function got passed a string instead of an object, it just uses the string that is provided. It constructs the new URI based on this query string.

    let requestBody = "";
    if (body != null) {
        console.debug("[callAjax] Body has been specified - processing");
        if (typeof body === "object") {
            console.debug("[callAjax] body is an object");
            requestBody = JSON.stringify(body);
            headers["Content-type"] = "application/json";
        } else if (typeof body === "string") {
            console.debug("[callAjax] body is a string (adding unmodified)");
            requestBody = body;
        }
        console.debug("[callAjax] BODY = %s", requestBody);
    }

Next up is the body – used in POST and PUT REST calls. I’m using the JSON methods that are built into pretty much every browser these days. If the method is passed an object, I turn it into JSON and then update the headers to include a Content-type header. As with the query parameters, if I pass a string then I just include it and assume the caller knows what they are doing.

    return new Promise(function (resolve, reject) {
        console.debug("[callAjax] Creating new XMLHttpRequest");
        let request = new XMLHttpRequest();
        console.debug("[callAjax] Open a %s request to %s", method, uri);
        request.open(method, uri);
        for (var p in headers) {
            if (headers.hasOwnProperty(p)) {
                console.debug("[callAjax] Add header %s: %s", p, headers[p]);
                request.setRequestHeader(p, headers[p]);
            }
        }

        console.debug("[callAjax] Set resolve to the onload object");
        request.onload = function() {
            resolve(request);
        };

        console.debug("[callAjax] Set reject to the onerror object");
        request.onerror = function() {
            reject(request);
        };

        console.debug("[callAjax] Send requested body");
        request.send(requestBody);
    });
}

Finally, I construct the XMLHttpRequest wrapped in a promise. Since I expect that different codes are going to get returned, I’m not going to assume that 200 is the only valid code. I did this in the prior version of the library. Instead I say “success is when the server responds and failure is when the server does not response”.

/**
 * Helper Functions for each method
 */
function ajaxDelete(url, query, headers) { //eslint-disable-line no-unused-vars
    return callAjax("DELETE", url, query || {}, null, headers || {});
}

function ajaxGet(url, query, headers) { //eslint-disable-line no-unused-vars
    return callAjax("GET", url, query || {}, null, headers || {});
}

function ajaxPost(url, args, headers) { //eslint-disable-line no-unused-vars
    return callAjax("POST", url, null, args, headers || {});
}

function ajaxPut(url, args, headers) { //eslint-disable-line no-unused-vars
    return callAjax("PUT", url, null, args, headers || {});
}

export { ajaxDelete, ajaxGet, ajaxPost, ajaxPut };

Finally, I set up a number of functions that send the right arguments to the callAjax() method. GET and DELETE calls use a query method. POST and PUT calls use a body method. This way every method uses the same arguments and the right format gets sent to the backend.

Feel free to co-opt this library file for yourself.

Calling the WebAPI

Now, how do we use this library? In the last article I created a LoginModal class for handling the login modal. Let’s take a look at the new code:

/**
 * Handler for the Login Modal
 */
/*eslint no-console:0 */
"use strict";

import { ajaxPost } from "./ajax";

class LoginModal {
    /**
     * Constructor - store the ID that activates us and then
     * wire up the activator.
     */
    constructor(activatorEl, modalEl) {
        // Store all the elements for later
        this.activator = activatorEl;
        this.modal = modalEl;
        this.modalClose = modalEl.querySelector(".modalClose");
        this.submitButton = modalEl.querySelector("button#loginButton");

        // Make the activator cursor a pointer to show it is clickable
        this.activator.style.cursor = "pointer";

        // Wire up the click event handlers for the activator and modal close
        this.activator.addEventListener("click", (e) =&gt; { return this.activate(e); });
        this.modalClose.addEventListener("click", (e) =&gt; { return this.close(e); });

        // Wire up the submission button for the form
        this.submitButton.addEventListener("click", (e) =&gt; { return this.submit(e); });

        // Ensure the modal is hidden
        this.modal.style.display = "none";
        this.modal.style.opacity = "0";

        return;
    }

As with the AJAX library, I’m using the eslint directive to disable complaints about the console. I then bring in the ajaxPost method (the only one I need in this file) from the AJAX library above.

In the constructor, I’ve added information about the submit button and wired up an event handler for when the user clicks on the submit button.

   /**
     * Someone hit the submit button.
     */
    submit(e) {
        let modal = this.modal,
            submitButton = this.submitButton,
            spinner = "<i class='fa fa-spinner fa-pulse'></i> ",
            submitContent = this.submitButton.innerHTML;

        // Deactivate the form
        submitButton.disabled = true;
        submitButton.innerHTML = spinner + submitContent;

The first thing we do when going into the submit button event handler is to deactivate the form. Sometimes you will have a slow link – you don’t want someone clicking repeatedly on the submit button and having that kick off tons of requests to the backend – the idea is to reduce the load on the backend, not increase it. To indicate that the form is busy, I’ve added a spinner to the button content.

        // Validation goes here (eventually)

        // Submit AJAX Request
        let requestArgs = {
            "Email": this.modal.querySelector("input[name=Email]").value,
            "Password": this.modal.querySelector("input[name=Password]").value
        };
        console.debug("[LoginModal#submit] requestArgs = %o", requestArgs);

I’m not doing client side validation (yet). I’ll get to it. From the WebAPI work, I know that my request has to be a JSON request with the Email and Password fields, so I need to construct an object that I can pass along. Next step is the actual AJAX call:

        ajaxPost("/api/login", requestArgs)
            .catch(function(error) {
                console.error("[LoginModal#submit] Error in AJAX Call to /api/login: %o", error);
            })
            .then(function (response) {
                console.debug("[LoginModal#submit] AJAX Call to /api/login: Response = %o", response);
                if (response.status === 200) {
                    // We got a 200 Success back, so refresh the page
                    location.reload();
                } else if (response.status === 400) {
                    let r = JSON.parse(response.response);

                    // If there were errors, then add them to the appropriate areas on
                    // the form.  If there weren't errors, make sure those same areas
                    // don't have errors (handles multiple submissions)
                    if (r[""]) {
                        modal.querySelector("#errorForSignInModal").innerHTML = r[""][0];
                    } else {
                        modal.querySelector("#errorForSignInModal").innerHTML = "";
                    }
                    if (r.Email) {
                        modal.querySelector("#errorForEmail").innerHTML = r.Email[0];
                    } else {
                        modal.querySelector("#errorForEmail").innerHTML = "";
                    }
                    if (r.Password) {
                        modal.querySelector("#errorForPassword").innerHTML = r.Password[0];
                    } else {
                        modal.querySelector("#errorForPassword").innerHTML = "";
                    }

                    // Re-activate the form
                    submitButton.innerHTML = submitContent;
                    submitButton.disabled = false;
                }
            });

        e.stopPropagation();
        return false;
    }

If you remember from my discussion on ES6 Promises, I can catch errors and handle responses asynchronously. The catch statement says “there is an error” – right now, I’m just logging the error in the console and not re-activating the form. This isn’t very friendly and I should probably do something about that.

In the then clause, I handle the response. There are two possible responses from the WebAPI – a 200 Success with a few cookies or a 400 Bad Request with some JSON. If the response is Success then the browser already knows about the cookies and all I have to do is reload the page.

If the response is a 400 Bad Request, then I turn the JSON response into an object and look for things I’m interested in, placing the response in prepared locations in the modal dialog. Once that is done, I restore the button content (which removes the spinner) and re-enable the submit button.

Running the Code

If you run this code and click on the Sign In button, the modal will pop up. At this point you can bring up the F12 Developer Tools and hop over to the Console window. Enter some information and see what comes up:

blog-code-0606-1

I’ve added a number of console.debug statements so you can see what is happening. You can also click on any of the objects with a triangle beside them to see the actual contents. Here I’ve entered “admin@” as the username, so I’m expecting a 400 Bad Request, which is exactly what I get.

Problems Still to be Solved

There are two problems to be solved. Firstly, users like to be able to press Enter in the text boxes to submit the form. I’m not capturing key presses within the form so I can’t emulate that functionality. Right now, the only submission possibility is clicking on the button.

Secondly, if there is an error in transmission then there is no indication. The form will continue to spin. This is an easy fix and I’ll do it before I check in the code.

Finally, I don’t do any client-side validation. I leave the validation to the server-side. This means that there are extra round-trips happening when it’s not really necessary. I’ll fix that in the next article.

ASP.NET MVC6 Identity Part 3 – An ECMAScript 6 Modal Login Dialog

I’ve recently been recoding my ASP.NET Identity tutorial to use WebAPI and conform to any changes introduced in the beta-4 release of ASP.NET5 MVC6. In the last article I introduced the WebAPI for logging in, but I was testing it with Postman. I don’t expect my users to use Postman to log in so I need a dialog.

Today I am concentrating on the modal dialog. When I click on the Sign In link, I want a modal dialog with the login form to appear. The modal dialog will have a close button and when I click that, I want the modal dialog to go away. I want all the code to be in ECMAScript 6 and ideally not rely on jQuery so I can potentially re-use the code without too much bother.

Signing Out

Before I start, I noticed that I was signed in permanently from the work during the last article. I need to be able to sign out as well. To do this, I’m going to add a normal MVC action to the AccountController that signs the user out and then redirects to the home page:

        /// <summary>
        /// Sign out of the web application
        /// </summary>
        /// redirect to the home page
        [HttpGet]
        public IActionResult Logout()
        {
            signInManager.SignOut();
            return RedirectToAction("Index", "Home", new { area = "Public" });
        }

Don’t forget to add the [Area("Public")] to the class to ensure that the routing happens properly. Once this is done, you should be able to click on the Sign Out link on the top banner.

The Login Dialog HTML

My Areas/Public/Views/Shared/Header.cshtml contains the menu links along the top of the page. I want to introduce another Partial View to include my login dialog HTML at the right place:

<header>
    <h1>
        <a href="@Url.Action("Index","Home", new { area = "Public" })">Grumpy Wizards</a>
    </h1>
    <nav>
        <ul>
            @if (User.Identity.IsAuthenticated)
            {
                <li id="sign-out">
                    <a href="@Url.Action("Logout","Account", new { area = "Public" })">
                        <i class="fa fa-sign-out"></i> Sign Out
                    </a>
                </li>
            }
            else
            {
                <li id="signInActivator">
                    <i class="fa fa-sign-in"></i> Sign In
                    @Html.Partial("~/Areas/Public/Views/Account/LoginModal.cshtml")
                </li>
            }
        </ul>
    </nav>
</header>

I’ve included the Partial View right in line with the link, and it is going to be included in a file called LoginModal.cshtml. The directory Areas/Public/Views/Account doesn’t exist yet, so make sure you create it. Here is the LoginModal.cshtml file:

<div  id="loginModal" class="modalWrapper">
    <div class="modalForm">
        <div class="modalClose">X</div>
        <h1>Enter Credentials</h1>
        <form>
            <div class="modalFormError" id="errorForSignInModal"></div>
            <div class="modalFormGroup">
                <span class="modalFormLabel">
                    <i class="fa fa-envelope"></i>
                </span>
                <span class="modalFormControl">
                    <input type="text" name="Email" placeholder="Email Address">
                </span>
            </div>
            <div class="modalFormError" id="errorForEmail"></div>
            <div class="modalFormGroup">
                <span class="modalFormLabel">
                    <i class="fa fa-key"></i>
                </span>
                <span class="modalFormControl">
                    <input type="password" name="Password">
                </span>
            </div>
            <div class="modalFormError" id="errorForPassword"></div>
            <div class="modalFormGroup">
                <button type="button" id="loginButton">Login</button>
            </div>
        </form>
    </div>
</div>

Note that I am not using a view modal nor am I using the Razor HTML helpers here. This is all pure HTML. That is because I am going to be handling everything client side and only submitting the form once I’ve got everything validated. Also, I’m not using a submit button. I’m using a regular button. This will mean that my form doesn’t get submitted when I click on the button and that means I can handle the request with Javascript instead.

Styling the Modal

I’ve created a new file Static/less/modal.less with the modal dialog styling in it. I’ve included the styling in the main site.less like this:

@import (reference) "inc/utils.less";
@import (less) "settings.less";

html {
    .fullsize();

    body {
        .fullsize();
        padding-top: @header-h;
    }
}

@import (less) "modal.less";
@import (less) "header.less";
@import (less) "signin.less";

The signin.less file contains the styling for the login form. I’m going to produce some common styling in modal.less since I probably will be doing a few other modal dialogs. Here is the modal.less file:

@import (reference) "settings.less";

/*
    Modal Dialog Overlay
*/
.modalWrapper {
    // The modal wrapper covers the entire page
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    background: rgba(0,0,0,0.8);
    z-index: 99999;
    transition: opacity 400ms ease-in;
    pointer-events: none;

    // The form is a 400px wide block in the center
    .modalForm {
        width: 400px;
        position: relative;
        margin: 10% auto;
        border-radius: 10px;
        background: @color-5;
        pointer-events: auto;

        // The close button appears in the top left corner
        .modalClose {
            background: @color-3;
            color: @color-4;
            line-height: 25px;
            position: absolute;
            right: -12px;
            top: -10px;
            text-align: center;
            width: 24px;
            text-decoration: none;
            font-weight: bold;
            border-radius: 12px;
            box-shadow: 1px 1px 3px #000;
            cursor: pointer;

            &:hover {
                background: @color-2;
                color: @color-4;
            }
        }
    }
}

The modal wrapper (that is, the outer most DIV of the modal) takes up the entire screen and traps any pointer events. The modal inner (class="modalForm") is restores the pointer events and is styled to look like a modal. Finally, I’ve got a close button that will appear in the top left corner of the dialog. It is positioned absolutely but relative to its parent.

The Login Dialog Javascript

I’ve already got an app-main.js file that gets run when the application initializes, so I’m going to bring the login dialog during that phase:

/**
 * Main Application Code
 */
/*eslint no-console:0 */

"use strict";

import { LoginModal } from "./loginModal";

$(document).ready(function() {
    var elements = [];

    /**
     * Initialize the login modal dialog
     */
    function initializeLoginModal() {
        let modalActivator = document.getElementById("signInActivator"),
            modalDialog = document.getElementById("loginModal");

        if (modalActivator == null || modalDialog == null) {
            console.info("[app-main] Login Mode is not available - skipping Login Modal Initialization");
            return;
        }

        console.info("[app-main] Initializing Login Modal");
        var loginModal = new LoginModal(modalActivator, modalDialog);
        elements.push(loginModal);
    }


    console.info("[app-main] Initializing Application...");
    initializeLoginModal();
});

This relies on jQuery to do wrap the code so that it doesn’t execute until the page is loaded. The main piece of initialization is in the initializeLoginModal() function. First off, it finds the activator link (the Sign In block in the top header) and the modal dialog DIV. If they are both available, then it creates a new LoginModal object and pushes it onto the elements stack (which is just an array of things I create). If the two elements are not available, then the routine just returns.

The major ECMAScript 6 code is in the loginModal.js code, which contains a LoginModal class that it exports:

/**
 * Handler for the Login Modal
 */

"use strict";

class LoginModal {
    /**
     * Constructor - store the ID that activates us and then
     * wire up the activator.
     */
    constructor(activatorEl, modalEl) {
        // Store all the elements for later
        this.activator = activatorEl;
        this.modal = modalEl;
        this.modalClose = modalEl.querySelector(".modalClose");

        // Make the activatorcursor a pointer to show it is clickable
        this.activator.style.cursor = "pointer";

        // Wire up the click event handlers for the activator and modal close
        this.activator.addEventListener("click", (e) => { this.activate(e); }, false);
        this.modalClose.addEventListener("click", (e) => { this.close(e); }, false);

        // Ensure the modal is hidden
        this.modal.style.display = "none";
        return;
    }

    /**
     * Someone clicked on the activator - toggle the visibility
     */
    activate(e) {
        this.modal.style.display = "block";
        e.stopPropagation();
    }

    /**
     * Someone clicked on the close icon - hide the modal
     */
    close(e) {
        this.modal.style.display = "none";
        e.stopPropagation();
    }
}

export { LoginModal }

This is an ECMAScript 6 class inside an ECMAScript 6 module, using ECMAScript 6 fat arrows to preserve the object reference during an event handler. There are two event handlers – one to activate (or show) the dialog and one to close it. I’ve wired up the activate event handler to the click event of the Sign In link and the close event handler to the click event of the close icon in the top-left hand corner of the dialog.

Adjusting ESLint for ES6 Modules

If you run all this code, you will notice a failure on transpiling the ES6 code in ESLint. It will say something like “Illegal import declaration” or “Illegal export declaration”. I haven’t told ESLint I am using ES6 modules. This is, surprisingly, not done in the gulp-eslint module. Rather, it is done in package.json with the following declaration:

  "eslintConfig": {
    "ecmaFeatures": {
      "modules": true
    }
  },

Once you have this in your package.json, the transpile step should not produce any errors.

Finishing Up

I also added a signin.less file to style the actual sign-in form. Once that is included, you should be able to click on the Sign In link and get the modal dialog, then click on the close icon and see it close again. Since it’s modal, you should not be able to click on anything other than the modal piece.

ESLint: Improving the ECMAScript 6 Search Box (Part 4)

In the past 3 posts I have discussed upgrading my search box project to ECMAScript 6, building with Gulp and styling with LESS. It’s now working. However, I also said I needed to run eslint frequently and test the component using automated techniques. It’s a little late in the process but let’s get those integrated too. I will cover linting today and testing tomorrow.

ESLint

My first step is to integrate eslint. There is a gulp-eslint package, so I added that to my package.json and required it at the top of my Gulpfile.js – just like all the other plugins. My rule for running eslint is fairly simple:

gulp.task('source:lint', function () {
    return gulp.src(['src/js/init.js', 'src/js/**/*.js'])
        .pipe(eslint())
        .pipe(eslint.format())
        .pipe(eslint.failOnError());
});

Run this rule using the right-click->Run in the Task Runner Explorer of Visual Studio and you will see the following:

eslint-errors

There are a bunch of errors in init.js that we can just fix – things like double-quotes for strings and a new line at the end. However handling the non-obvious ones will take some work. Let’s cover them now:

1. Require is not defined

Require is a global and is defined within our HTML page, so I need to tell ESLint that this is ok. While I am at it, I also need to tell ESLint that jQuery is ok, but only in the $ form – not in the long form. I can do this with this task configuration by including an options object and specifying a globals option:

gulp.task('source:lint', function () {
    return gulp.src(['src/js/init.js', 'src/js/**/*.js'])
        .pipe(eslint({
            globals: {
                "require": true,
                $: true,
                "jQuery": false
            }
        }))
        .pipe(eslint.format())
        .pipe(eslint.failOnError());
});

2. Document is not defined

The browser defines document. You may also see references to ‘window’ is not defined, which is the same problem. I need to tell ESLint my application runs in a browser. I do this by specifying an environment declaration in the configuration like this:

gulp.task('source:lint', function () {
    return gulp.src(['src/js/init.js', 'src/js/**/*.js'])
        .pipe(eslint({
            globals: {
                "require": true,
                $: true,
                "jQuery": false
            },
            envs: {
                browser: true
            }
        }))
        .pipe(eslint.format())
        .pipe(eslint.failOnError());
});

3. Use Strict is Required

Most people suggest that you use strict when writing ECMAScript 5. This alters my init.js to the following:

require.config({
    baseUrl: "/js",
    paths: {
        "jquery": "/lib/jquery/jquery.min",
        "bootstrap": "/lib/bootstrap/js/bootstrap.min",
        "require-css": "/lib/requirejs/css.min"
    },
    shim: {
        "bootstrap": {
            deps: [
                "jquery"
            ]
        }
    }
});

require([
    "jquery",
    "classes/MySearchBox",
    "bootstrap",
    "require-css!/lib/bootstrap/css/bootstrap.min"
], function ($) {
    "use strict";

    $(function () {
        $("#nav-search").searchbox();
    });
});

4. Invalid import declaration

You’ve probably guessed by now that this is because of ECMAScript 6 support. I need to enable this and the configuration is a little more extensive and certainly not documented well. I need to add an environment to our config to tell ESLint that I write es6 code and then add eslint configuration inside of package.json to tell it which features I use that are non-standard:

{
    "version": "1.0.0",
    "name": "BubbleSearch",
    "private": true,
    "bin-links": true,
    "dev": true,
    "dependencies": {
        "bootstrap": "3.3.2",
        "jquery": "2.1.3",
        "requirejs": "2.1.16",
        "require-css": "0.1.5"
    },
    "devDependencies": {
        "gulp": "3.8.11",
        "del": "1.1.1",
        "merge-stream": "0.1.7",
        "gulp-babel": "4.0.0",
        "gulp-sourcemaps": "1.5.0",
        "gulp-less": "3.0.1",
        "gulp-pleeease": "1.2.0",
        "gulp-concat": "2.5.2",
        "gulp-eslint": "0.6.0"
    },
    "eslintConfig": {
        "ecmaFeatures": {
            "modules": true
        }
    }
}

The extra eslintConfig section tells ESLint that I am using ECMAScript 6 modules. The configuration of the environment is done in the Gulpfile.js task definition in a similar way to the browser definition earlier:

gulp.task('source:lint', function () {
    return gulp.src(['src/js/init.js', 'src/js/**/*.js'])
        .pipe(eslint({
            globals: {
                "require": true,
                "$": true,
                "jQuery": false
            },
            envs: {
                browser: true,
                es6: true
            }
        }))
        .pipe(eslint.format())
        .pipe(eslint.failOnError());
});

When I run eslint now I get more errors but at least I am syntax checking the entire ES6 class file now. Note also that because I am running in ES6 mode, the use strict I added earlier is no longer required.

That’s 66 errors to go! In doing all the obvious ones, note the error on line 76:

  76:22  error  Expected '===' and instead saw '=='  eqeqeq

That’s actually a major style problem that ESLint found. I’m doing this all the time as a habit, so getting ESLint to break me of this habit is a good thing.

5. Unexpected console statement

There are a bunch of errors around the console statement. I left them in because I can programmatically remove them when I am minifying my code for production. I really want to make ESlint ignore them. That’s a two step process. Firstly I need to tell ESLint that console is a global – I do that the same way I did with require earlier. Once I did that and re-ran eslint, I noticed that I had a mis-spelling of console, so I corrected that (thank you eslint!) The other error eslint is throwing is Unexpected console statement. It is best to disable this rule since I use a lot of console statements. To do this, I have to alter the eslintConfig inside of package.json:

    "eslintConfig": {
        "ecmaFeatures": {
            "modules": true
        },
        "rules": {
            "no-console": 0
        }
    }

The rule name is printed on the eslint output next to the error message. If you’ve done everything correctly, you can rejoice now because you have a clean lint run. However, make sure you always do the following:

  1. Run eslint before you check in your code
  2. Run eslint whenever you complete a class or major piece of functionality
  3. Care about the errors enough to deal with them

I’ve uploaded this code to my GitHub Repository for you to review. Note that it is the complete code, so check out the other articles in the series that cover everything.