Animating an element’s visibility using AngularJS

There was a question on StackOverflow about animating an element and I wanted to give it a shot, so here goes:

http://jsfiddle.net/wiredprairie/5tFCZ/1/

image

 

Imagine nearly the simplest Angular JS application possible:

<div ng-app="App">
    <div ng-init="checked=true">
        <div>
            <label>
                <input type="checkbox" ng-model="checked" />Is Visible...</label>
        </div>
        <div class="sample" ng-class="{ hidden: !checked }">Visible...</div>
    </div>
</div>

There is only a single property called checked as part of the data model. There’s a checkbox that when unchecked, will cause the text “Visible” to be hidden.

I’m going to use jQuery as the simple animation engine, but you could use what ever you’d like. The latest versions of jQuery, angular, and angular-animate are needed:

<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script src="http://code.angularjs.org/1.2.10/angular.min.js"></script>
<script src="http://code.angularjs.org/1.2.10/angular-animate.min.js"></script>

Using the ng-class directive (reference), a CSS class named hidden is added when the checkbox is not checked.

The application module and animation API are defined:

angular.module('App', ['ngAnimate']).animation('.sample', function () {
    return {
        addClass: function (element, className, done) {
            if (className === 'hidden') {
                jQuery(element)
                    .css({
                    opacity: 1
                })
                    .animate({
                    opacity: 0
                }, 500, done);
            } else {
                done();
            }
        },
        removeClass: function (element, className, done) {
            if (className === 'hidden') {
                jQuery(element)
                    .css({
                    opacity: 0
                })
                    .animate({
                    opacity: 1
                }, 500, done);
            } else {
                done();
            }
        }
    }
});

 

The only element animated on the page is using a CSS class name of sample. Whenever Angular adds or removes a CSS class from a matching HTML element, the corresponding code is executed. As it’s possible for multiple class names to be passed to the functions, per the guidelines, I’ve made sure that the code only executes when appropriate by filtering on the class name of hidden. As it’s toggling the state, the first action taken is to fully make opaque or transparent, then animate to zero or one depending on whether the class is being added or removed.

And that’s it! Of course, the code could have been more sophisticated, but it was all I needed.

By the way, there’s no need for a CSS class named hidden that has any CSS properties (it can be undefined completely). The animation code handles the visibility properly.

Sending a socket to a forked process in Node.JS

If you want to fork a process in Node and pass a socket, the current Node documentation has a rather odd example, so I’ve simplified it here for my own sanity (further complicated by the fact that the WebStorm debugger can’t debug a forked Node.JS process, which confused me for too long). Hopefully someone else finds this useful at some point.

Step 1, in a file called app.js:

var child = require('child_process').fork('socket_handler.js');

// Open up the server and send sockets to child
var server = require('net').createServer();

server.on('connection', function (socket) {
    child.send('socket', socket);
    server.getConnections(function(err, count) {
        console.log("Connections: " + count);
    });
});
server.listen(1337);


And then, in a file called socket_handler.js which is located in the same directory as app.js:

process.on('message', function(message, socket) {
    socket.on('data', function(data) {
        // really poor echo ... 🙂
        socket.write(data);
    });
});

In this case, the fork happens upon application startup by calling the fork method of the child_process module. It starts by executing the code in socket_handler.js. As this is a new instance of the V8 engine used by Node.JS, remember there’s a sizable overhead to a forked process.

After creating the server and listening on port 1337, when a connection is made (which can be tested by a terminal emulator or telnet), the socket is passed to the forked process. In fact, it’s not really the object as much as it’s the handle to the new socket.

The send method takes two parameters, a string message which can be any identifier you want, and the the handle, or socket in this case.

The forked process receives the message via the message event on the process. If you’re sending more than one message, you can add conditional logic to handle the type of message in the event handler. As part of the call to fork, you can also pass command line arguments and read them using process.argv.

Using Windows CSCRIPT to compile a Handlebar.js template

I was looking for an alternative to using Node.JS for a JavaScript build process today on a Windows machine. I wanted something that relied as much on natively installed elements of a modern Windows PC as possible so that the build process would be portable.

So, I broke out my rusty Windows Script Host skills.

First, I created a file called, compile.wsf with the following contents:

image

When using cscript.exe, you can execute a more complex combination of scripts and include other script files by using a Windows Script File. The content of the file is an XML definition of jobs. A job represents a unit of work. If you only have one job in a file, the name won’t matter as the script engine will select it by default. If you do have more than one job you’d like to store in a single WSF file, you can use the /Job:{id} parameter of cscript.exe to run a single job.

Using the WSF file, you can include other script files using a script element (much like the script tag in HTML). In the example above, I’ve referenced a local copy of handlebars.js and a custom script called compile.js.

You can also inline script as shown above. After doing a basic check on the number of arguments provided to the script, compile is called, which is from the compile.js script reference.

Compile.js is simple:

image

Using an instance of the FileSystemObject, first the input file is verified to exist. Next, both the input and output files are opened. The Handlebars object is available globally by including it in the WSF definition and is used to precompile the contents of the input file’s template definition. Once compiled, it’s written to the output file and both files are closed.

I threw the three files in a folder called lib, and created a simple batch file called handlebars.bat which called the cscript executable with the Windows Script File shown above as the first parameter and then the values of the other parameters passed along:

image

While this solution only works on Windows, it doesn’t hurt to keep the Windows Script Host in mind when throwing together general repeatable tasks that you:

  • consider too complex for a batch file
  • consider too simple for a full .NET application
  • require usage of existing JavaScript libraries, like Handlebars.js for some work

How to debug an underscore.js template

Given a simple template like this:

<div class="solution" data-question-id="<%= model.get('Id') %>">    
    <div class="title"><%= model.get('Name') %></div>
    <div class="company"><%= model.get('Company') %></div>
    <div class="version"><%= model.get('Version') %></div>
    <div class="detail"><%= model.get('Summary') %></div>
    <div class="actions">
        <a href="/#solution/<%= Id %>/<%= model.get('Id') %>">Detail</a>
    </div>
</div>

And using your favorite JavaScript interactive debugger (Visual Studio 2012 is my favorite when I’m doing MVC 4 Razor development), just add a debugger statement within your template temporarily:

<div class="solution" data-question-id="<%= model.get('Id') %>">
    <% debugger; %>
    <div class="title"><%= model.get('Name') %></div>

Assuming debugging is enabled, this will break (in Visual Studio for example) on the debugger line whenever your code template is executed.

The emitted template code thankfully has line feeds embedded so it’s readable:

function anonymous(obj,_) {
var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};
with(obj||{}){
__p+='<div class="solution" data-question-id="'+
((__t=( model.get('Id') ))==null?'':__t)+
'">\r\n    ';
 debugger; 
__p+='\r\n    <div class="title">'+
((__t=( model.get('Name') ))==null?'':__t)+
'</div>\r\n    <div class="company">'+
((__t=( model.get('Company') ))==null?'':__t)+
'</div>\r\n    <div class="version">'+
((__t=( model.get('Version') ))==null?'':__t)+
'</div>\r\n    <div class="detail">'+
((__t=( model.get('Summary') ))==null?'':__t)+
'</div>\r\n    <div class="actions">\r\n        <a href="/#solution/'+
((__t=( Id ))==null?'':__t)+
'/'+
((__t=( model.get('Id') ))==null?'':__t)+
'">Detail</a>\r\n    </div>\r\n</div>\r\n';
}
return __p;

}

You’ll see the debugger emitted in-line. It’s very handy for inspect the values of variables, objects, etc. In the example above, I wanted to confirm that the model being passed was in the proper format.

I’ve used it many times to help debug a template that wasn’t working the way I’d expected.

This also works well in Chrome’s debugger.

Smarter queuing of files using jQuery deferred and when

I had a somewhat simple need …a single web page style application using Backbone.JS had multiple template files it needed to download, if and only if the files hadn’t already been downloaded before.

While I suppose I could have relied on browser caching, I wanted to manage the requests in JavaScript. The trick was that at any given time, a request might include one or more template files, and some of the request might have already been made, or in progress.

Here’s the queuing function:

(function() {
    var allFiles = {};
    var allResults = {};

    var queueRequest = function (path, files, options) {
        options = options || {};
        files = $.isArray(files) ? files : [files];
        
        // this will contain all of the deferreds that will be 
        // wrapped with a `when` deferred
        var when = [];
        // might want to override some defaults...
        var ajaxOpt = $.extend({
            dataType: 'json',
            type: 'GET'
        }, options.ajax || {});

        // go thru each file
        $.each(files, function (i, file) {
            var xhr;
            // if we've not seen it before
            if (typeof allFiles[file] === 'undefined') {
                // kick it off
                xhr = $.ajax(path + file, ajaxOpt).done(function (data) {
                    // store the file results in the hash index
                    allResults[file] = data;
                });
                // keep the deferred for later use
                allFiles[file] = xhr;
                // and keey this for later
                when.push(xhr);
            } else {
                // already seen this, so just pack it on
                when.push(allFiles[file]);
            }
        });
        // return all of the built up deferreds as a 
        // single when. this will then wait until 
        // all are satisfied
        return $.when.apply(this, when).done(function () {
            if ($.isFunction(options.done)) {
                options.done.call(this, allResults);
            }
        }).fail(options.error);
    };

    window.Queue = queueRequest;
})();

Queuing is easy enough:

Queue(app_url("api/template/"), templates, {
    done: function (allFiles) {
        _.each(templates, function (n) {
            // compile only if needed
            if (typeof allTemplates[n] === 'undefined') {
                allTemplates[n] = _.template(allFiles[n]);
            }
        });
        if (typeof callback === 'function') {
            callback.call(context, allTemplates);
        }
    }
});

allTemplates is a list of compiled underscore templates stored elsewhere.

The first parameter to the Queue function is the full path to the templates. I’ve got a simple MVC controller that responds with a template given a key, so that’s the path that is provided in the example above. The list of templates (as an array) is passed.

The Queue code returns a jQuery deferred when. The function returns both active and completed ajax requests … which means that the jQuery when function may immediately fire … or not. When simply waits for all of the async operations to complete, and then calls the callback passed to done.

When complete, the code passes all results back to the requesting function. It’s not filtered as I trusted the caller (no reason to unnecessarily clone the array and waste CPU time). :)