A year ago I was working on a project.It was a standard HTML and CSS project.Since it was side project I had about an hour to work on it every day.

The first few weeks the project CSS was fairly large each file with about ~1000 lines of hate.But after a couple of weeks the CSS was now about 2000 lines and reusing CSS had become cumbersome.

Wow it’s 2013 and I was not using a build process for my saas files.I got so tired of running compass manually on the files and waiting for it complete so I could refresh the browser tab.

I took a stab at grunt.Grunt is a task runner for JavaScript.It has a huge collection of plugins which can be installed and used to create your build pipeline.

Grunt is cross platform and it runs on nodes.So the first thing I had to set up was node.I suggest getting the latest version of node.With every node project you need to use a package manger as it takes care of downloading and dependency management for the packages.

Grunt includes a command line tool which has to be installed globally

npm install -g grunt-cli

You need to create a package .json file by running the npm init command in your shell.You will also need to create a Gruntfile.js file in the project root directory.

Add the following dependencies to package.json file.

{
  "name": "Demo site",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "author": "",
  "devDependencies": {
    "grunt": "^0.4.5",
    "grunt-contrib-compass": "^1.0.1",
    "grunt-contrib-watch": "^0.6.1",
    "grunt-express": "^1.4.1",
    "grunt-open": "^0.2.3",
    "matchdep": "^0.3.0"
  }
}

 

You then need to add the following tasks to Gruntfile.

module.exports = function(grunt){
  require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);
  grunt.initConfig({
    express: {
    all: {
        options: {
          bases: ['/Users/surajshirvankar/Desktop/vk.ae/'],
          port: 8080,
          hostname: "0.0.0.0",
          livereload: true
        }
      }
    },
    compass:{
      dev:{
        options: {
          sassDir: 'sass',
          cssDir: 'css'
        }
      }
    },
    watch: {
      compass: {
        files: ['sass/*'],
        tasks: ['compass:dev']
      },
      all: {
          files: ['*.html', 'css/*.css'],
          options: {
              livereload: true
        }
      }
    },
    open: {
      all: {
        path: 'http://localhost:8080/index.html'
      }
    }
  });
  grunt.registerTask('default', ['express','open','watch']);
}

 

You are now done.Just run grunt and it takes care of starting a local server,live-reloading if you change files and build your CSS.



Grunt is an awesome javascript tool to automate your build process.The best part about gruntjs is how quickly you can build tasks.I came across this project which lets me build html email templates which work well with most browser.

The most important feature of this project is that it automatically builds and inlines the css.Emails need to have inline css because all of the email client in existence do not allow external stylesheets especially outlook.

This project is great once you create an email template you have it sent to your inbox to test.It also supports cloudfront cdn to have your email attachments in the cloud.

I am a big fan of mailchimp and their email service,I wanted to mailchimp’s smtp server to send the email to me rather than the built in mailgun(Mailgun is awesome too).I looked around for a grunt plugin for mailchimp.After a couple of minutes searching,I decided to write my own grunt plugin to send the email.

Since mailchimp calls it’s email service mandrill.I did the logical thing and named the plugin grunt-mandrill(I suck at naming things)

The plugin is pretty simple.You add the configs in your Gruntfile and add the grunt-mandrill task to it.

Back to grunt-email-design.
I have integrated the plugin with the email design repo,pull request is still pending.But if you want to use mandrill head over to my github repo to use it.



Map is another important functional paradigm where you iterate over a object and perform some changes to the original objects.
The way underscore implements the map function is pretty simple.

  _.map = _.collect = function(obj, iterator, context) {
    var results = [];
    if (obj == null) return results;
    if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
    each(obj, function(value, index, list) {
      results.push(iterator.call(context, value, index, list));
    });
    return results;
  };

The map(aliased as collect) takes the object to interate over as a parameter and the iteration function as the parameter.

_.map = _.collect = function(obj, iterator, context) {

We create an empty array to store the computation per iteration.We do a simple null check and return the empty error if null.

  var results = [];
  if (obj == null) return results;

We then check if native map is present.If it is present we delegate the map job to the native implementation.
We then run our own iterator using the previously implemented each method and then store the values into the array defined before.Finally we return the array.

  each(obj, function(value, index, list) {
    results.push(iterator.call(context, value, index, list));
  });
  return results;



Functional programming is the paradigm of programming where the functions are passed as arguments to methods and operations are performed on the function.Underscore makes use of this in a very clean and generic way.

The goal for the each method is to iterate over array or object provided as arguments in the function call.

var each = _.each = _.forEach = function(obj, iterator, context) {
    if (obj == null) return obj;
    if (nativeForEach && obj.forEach === nativeForEach) {
      obj.forEach(iterator, context);
    } else if (obj.length === +obj.length) {
      for (var i = 0, length = obj.length; i < length; i++) {
        if (iterator.call(context, obj[i], i, obj) === breaker) return;
      }
    } else {
      var keys = _.keys(obj);
      for (var i = 0, length = keys.length; i < length; i++) {
        if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return;
      }
    }
    return obj;
  };

The object/array to be iterated is passed as the first argument.A basic null check is performed and the obj is returned ie null.

if (obj == null) return obj;

We then check if the ecmascript 5's native forEach is present, if it is present we use it instead of implementing our version for each.

if (nativeForEach && obj.forEach === nativeForEach) {
      obj.forEach(iterator, context);
    } 

Javascript has neat way to check to check if a variable is a number object

3===+3

Return true

The way it works is it passes the + message to the object and === does a equality and type check.

obj.length === +obj.length

Since obj.length is a number ,we perform a check if it a number.which in turn checks if obj is array.
We then loop over each of the items in the array and pass the value to the interator function and call it.

for (var i = 0, length = obj.length; i < length; i++) {
        if (iterator.call(context, obj[i], i, obj) === breaker) return;
      }

If obj is an object we get the keys of the objects using underscore's builtin _.keys method.

var keys = _.keys(obj);
      for (var i = 0, length = keys.length; i < length; i++) {
        if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return;
      }

We call the iterator sending the values of the key in the object.



When every you include underscore into your code,it does a certain number of checks to make sure that there is no conflict and dependency issues.It also does a check and setup of the parameters that are required to use underscore.

  var root = this;
  var previousUnderscore = root._;
  var breaker = {};
  var ArrayProto = Array.prototype, ObjectProto = Object.prototype, FuncProto = Function.prototype;

  var 
    push = ArrayProto.push,
    slice = ArrayProto.slice,
    concat = ArrayProto.concat,
    toString = ObjectProto.toString,
    hasOwnProperty   = ObjProto.hasOwnProperty;

  var
    nativeForEach      = ArrayProto.forEach,
    nativeMap          = ArrayProto.map,
    nativeReduce       = ArrayProto.reduce,
    nativeReduceRight  = ArrayProto.reduceRight,
    nativeFilter       = ArrayProto.filter,
    nativeEvery        = ArrayProto.every,
    nativeSome         = ArrayProto.some,
    nativeIndexOf      = ArrayProto.indexOf,
    nativeLastIndexOf  = ArrayProto.lastIndexOf,
    nativeIsArray      = Array.isArray,
    nativeKeys         = Object.keys,
    nativeBind         = FuncProto.bind;

  var _ = function(obj) {
    if (obj instanceof _) return obj;
    if (!(this instanceof _)) return new _(obj);
    this._wrapped = obj;
  };

  if (typeof exports !== 'undefined') {
    if (typeof module !== 'undefined' && module.exports) {
      exports = module.exports = _;
    }
    exports._ = _;
  } else {
    root._ = _;
  }

  _.VERSION = '1.5.2';
var root = this;

Underscore sets root as this ie it sets the root as the windows of the javascript context.

var previousUnderscore = root._;

We save the previous underscore in previousUnderscore.

var breaker = {};

Creates an empty object used later to break out out a loop.

var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;

Creates an empty Array object and function to work on later.

 var
    push             = ArrayProto.push,
    slice            = ArrayProto.slice,
    concat           = ArrayProto.concat,
    toString         = ObjProto.toString,
    hasOwnProperty   = ObjProto.hasOwnProperty;

Create references for the function so that we dont have to recreate one every time we have to use it.

var
    nativeForEach      = ArrayProto.forEach,
    nativeMap          = ArrayProto.map,
    nativeReduce       = ArrayProto.reduce,
    nativeReduceRight  = ArrayProto.reduceRight,
    nativeFilter       = ArrayProto.filter,
    nativeEvery        = ArrayProto.every,
    nativeSome         = ArrayProto.some,
    nativeIndexOf      = ArrayProto.indexOf,
    nativeLastIndexOf  = ArrayProto.lastIndexOf,
    nativeIsArray      = Array.isArray,
    nativeKeys         = Object.keys,
    nativeBind         = FuncProto.bind;

Create references for the native Ecmascript 5 implementation.

var _ = function(obj) {
    if (obj instanceof _) return obj;
    if (!(this instanceof _)) return new _(obj);
    this._wrapped = obj;
  };

Create a variable _ function.if underscore is already loaded we return it.If _ is not the same as the one loaded.we return a new instance of underscore.

Required to use underscore with node.js.

_.VERSION = '1.5.2'

Sets the version of underscore.



Underscore is a set of utility functions written in underscore.With more than 80 different functions to make our lives easier.Its time to dissect them and understand how they work.

Underscore includes some setup code along with the functions below in the raw source of the library.The rest of the 80+ functions are mentioned below:

Underscore SetupĀ 

  1. Each method
  2. Map method
  3. Reduce method
  4. ReduceRight method
  5. Find method
  6. Filter method
  7. Reject method
  8. Every method
  9. Any method
  10. Contains method
  11. Invoke method
  12. Pluck method
  13. Where method
  14. FindWhere method
  15. Max method
  16. Min method
  17. Shuffle method
  18. Sample method
  19. SortBy method
  20. GroupBy method
  21. IndexBy method
  22. Countby method
  23. SortedIndex method
  24. ToArray method
  25. Size method
  26. First method
  27. Initial method
  28. Last method
  29. Rest method
  30. Compact method
  31. Flatten method
  32. Without method
  33. Uniq method
  34. Union method
  35. Intersection method
  36. Difference method
  37. Zip method
  38. Object method
  39. IndexOf method
  40. LastIndexOf method
  41. Range method
  42. Bind method
  43. Partial method
  44. BindAll method
  45. Memoize method
  46. Delay method
  47. Defer method
  48. Throttle method
  49. Debounce method
  50. Once method
  51. Wrap method
  52. Compose method
  53. After method
  54. Keys method
  55. Values method
  56. Pairs method
  57. Invert method
  58. Functions method
  59. Extend method
  60. Omit method
  61. Defaults method
  62. Clone method
  63. Tap method
  64. Isequal method
  65. isempty method
  66. isElement method
  67. isArray method
  68. isObject method
  69. isFinite method
  70. isNaN method
  71. isBoolean method
  72. isNull method
  73. isUndefined method
  74. has method
  75. isFinite method
  76. identity method
  77. times method
  78. random method
  79. result method
  80. mixin method
  81. template method
  82. chain method