Ultimate AngularJS and Ionic performance cheat sheet

As a lot of persons have asked me about how to improve AngularJS and/or Ionic performance. To avoid repeating myself on forums or on Slack I decided to create this ultimate cheat sheet list!

AngularJS

$watch

If you ever need to use $watch to listen to scope changes, you better use the right one. Indeed watched properties are examined on every call to $digest(), and therefore influence your application performance. There are three different ways to $watch scope properties:

$watch(watchExpression, listener, [objectEquality]);

Registers a listener callback to be executed whenever the watchExpression changes.

This is the basic $watch, it can be used like this:

$scope.$watch('watchExpression', function(newVal, oldVal){
    if(newVal){
        // watchExpression has changed.
    }
});

If watchExpression is an object that contains objects you can use objectEquality as true to deep watch watchExpression. While this is a super feature to have, it has a huge impact on your application performance:

$scope.$watch('watchExpression', function(newVal, oldVal){
    if(newVal){
        // watchExpression has changed.
    }
}, true);

My advice is to avoid using objectEquality when possible.

$watchGroup(watchExpressions, listener);

A variant of $watch() where it watches an array of watchExpressions. If any one expression in the collection changes the listener is executed.

Introduced in AngularJS 1.3, $watchGroup allows to watch several expressions at once.

$scope.$watchGroup([
    'watchExpression',
    'watchExpression2',
    'watchExpression3'
], function(newVals, oldVals) {
    if (newVals[0]) {
        // watchExpression has changed.
    }
    if (newVals[1]) {
        // watchExpression2 has changed.
    }
    if (newVals[2]) {
        // watchExpression3 has changed.
    }
});

While $watchGroup might not improve your application performance compare to $watch, it has the advantage to be more synthetic when watching several scope expressions.

$watchCollection(obj, listener);

Shallow watches the properties of an object and fires whenever any of the properties change (for arrays, this implies watching the array items; for object maps, this implies watching the properties). If a change is detected, the listener callback is fired.

$watchCollection can be considered in between the $watch and the $watch with objectEquality (deep watch). It also works comparing object references but with the advantage to also shallow watches the properties of your object.

For instance adding an element to an array that you watch will not trigger the normal $watch but trigger the $watch with objectEquality and the $watchCollection.

I recommend using the $watchCollection over the $watch with objectEquality when necessary. It is less expensive and therefore better for performance.

To go further on $watch and $watchCollection differences I recommend this article by Ben Nadel: http://www.bennadel.com/blog/2566-scope-watch-vs-watchcollection-in-angularjs.htm


One-time binding

An expression that starts with :: is considered a one-time expression. One-time expressions will stop recalculating once they are stable, which happens after the first digest if the expression result is a non-undefined value.

One-time binding :: was also introduced in Angular 1.3. It has a real impact on your application performance.

Basically using One-time binding :: on expression will remove it from the $watchers list when populated. It means that the expression will not be able to update even if the data changes.

For instance displaying the user first name on an application is unlikely to be updates, therefore is a good candidate for One-time binding :::

{{::user.first_name}}

My advice is to go through all your applications views and think about what could or could not be updated and use One-time binding :: accordingly. It will be a huge relief for the digest cycle!


Track by

track by is used to avoid useless DOM manipulation when using ng-repeat. Indeed if the digest cycle finds that at least one element of your collection has changed, ng-repeat will re-render all elements. DOM manipulation always has effects on the application performance, the less you have the better. To avoid re-rendering the complete collection and only change the elements that need to be changed use track by with a unique identifier.

Change your code from that:

ng-repeat="user in users"

to:

ng-repeat="user in users track by user.id" (if users have a unique id) or ng-repeat="user in users track by $index" if they don’t. $index is added by ng-repeat to each elements of your collection.


Logs

When using AngularJS do not use console.log, having them on a production application can slow down performances (see this jsperf). Some tools such as gulp-strip-debug automatically removes them from your code but my advice is not use console.log at all. AngularJS has a built in service that just does that: $log. It can be switched off using the $logProvider provider:

angular.module('yourModule').config(function($logProvider) {
    if (/* test if in production */) {
        $logProvider.debugEnabled(false);
    }
});

The $log service has several log levels .info .debug and .error.


Debug

AngularJS by default adds scope references to the DOM for tools such as angularjs-batarang to work. This has an impact on your application performance.

It can be disabled using the $compileProvider provider:

angular.module('yourModule').config(function($compileProvider) {
    if (/* test if in production */) {
        $compileProvider.debugInfoEnabled(false);
    }
});

Loops

Depending on the browser you use, JavaScript performance can be different. I set up 9 loop tests that go through an array of one hundred elements:

var arr = new Array(100);

# while loop
var i = 0;
while (i < arr.length) {
  arr[i];
  i++;
};

# cached while loop
var i = 0,
  len = arr.length;
while (i < len) {
  arr[i];
  i++;
};

# Reverse while loop
var i = arr.length;
while (i--) {
  arr[i];
};

# for loop
for (var i = 0; i < arr.length; ++i) {
  arr[i];
};

# cached for loop
var i = 0,
  len = arr.length
for (; i < len; ++i) {
  arr[i];
};

# Reverse for loop
for (var i = arr.length; i--;) {
  arr[i];
};

# Angular foreach
angular.forEach(arr, function(value, i) {
  arr[i];
});

# Native foreach
arr.forEach(function(value, i) {
  arr[i];
});

# Lodash foreach
_.forEach(arr, function(value, i) {
  arr[i];
});

At the end we can compare the results. What is the most performant way to iterate on an Array? Well apparently the “cached for loop” tend to be the best alternative across browsers. Native and Angular foreach are just 13 times less efficient than the cached loop…

The “cached for loop” does not re-evaluate the arr.length at every iteration, that’s why is it faster than the normal “for loop”.

It is also interesting to notice that lodash performance is four times better than angular foreach. If you do not like to use native for loops I recommend using lodash (I love this lib).


Animations

According to Ben Nadel’s blog post: Enable Animations Explicitly For A Performance Boost In AngularJS it is possible to force ngAnimate to only target elements that have a specific class name instead of checking all elements seeking for elements that could animate.

angular.module('yourModule').config(function($animateProvider) {
    $animateProvider.classNameFilter( /banimatedb/ );
});

I personally have not tested this approach but according to Ben Nadel’s numbers it could make a significant performance enhancement.


Ionic

Native scrolling

Native scrolling was released in May 2015 with Ionic 1.0. Before that Ionic relied on the JavaScript scrolling which was created to have proper events for features such as “Pull To Refresh”, Infinite Scrolling, List Reordering, or Collection Repeat. Browsers evolved to handle native scrolling events but mostly on Android, iOS in Cordova still doesn’t have completely native scroll events.

Native scrolling can be enabled using overflow-scroll=”true” on your ion-content or using the $ionicConfigProvider provider:

angular.module('yourModule').config(function($ionicConfigProvider) {
    $ionicConfigProvider.scrolling.jsScrolling(false);
});

My advice is to always enable it, once you have tested it you cannot live without it!

More information


Collection repeat

The collection-repeat directive is a directive that allows you to render lists with thousands of items and experience little to no performance penalty. It renders into the DOM only as many items as are currently visible.

Collection repeat is good for performance, but not on every cases. Indeed Collection repeat must $watch every item and item properties of your collection (you cannot use the One-time binding or track by with it). Depending on the data you want to display the number of $watchers can slow down your application.

<ion-content>
  <ion-item collection-repeat="item in items">
    {{item}}
  </ion-item>
</ion-content>

Another downside is that you cannot use native scrolling with a collection repeat.

More information


Infinite Scroll

The<ion-infinite-scroll> directive allows you to call a function whenever the user gets to the bottom of the page or near the bottom of the page. It has the advantage to only load the right amount of data that the user needs.

<ion-content ng-controller="MyController">
  <ion-list>
  ....
  ....
  </ion-list>

  <ion-infinite-scroll
    on-infinite="loadMore()"
    distance="1%">
  </ion-infinite-scroll>
</ion-content>

From my experience in a lot of cases using the infinite scroll combined with the One-time binding, track by and the Native scrolling is way better in terms of performance than a collection repeat.

More information


View cache

The view cache is one of Ionic’s killer feature. If enabled it keeps views in the DOM cache with their scope, current state, and scroll position. When navigating you never lose your input or scroll position so you can go back in history without the fear of losing data.

What about performance then? Well when a page is cached its scope is disconnected from the $watch cycle and reconnected when used again. It means that the number of $watchers are the same as if you do not use the view cache. However keeping views in the DOM and saving theirs states in memory have an impact on the application performance. My advice is to use this feature (it is a MUST have) but to cache only a reasonable amount of pages using the $ionicConfigProvider provider:

angular.module('yourModule').config(function($ionicConfigProvider) {
    $ionicConfigProvider.views.maxCache(5);
});

By default, Ionic will cache a maximum of 10 views, and not only can this be configured, but you can also explicitly state which views should and should not be cached using the <ion-view cache-view="false"> directive or the UI router $stateProvider provider.

$stateProvider.state('myState', {
   cache: false,
   url : '/myUrl',
   templateUrl : 'my-template.html'
});

More information


Events

When using AngularJS it is considered a good practice to load your data using the $viewContentLoaded event in controllers. When using Ionic SDK, this event is not usable, instead we have access to more specific events. The Ionic view cache comes with 8 new events, for instance “$ionicView.loaded” is triggered once per view being created and added to the DOM while the “$ionicView.enter” event will fire, whether it was the first load or a cached view.

Using the right event to load your data can improve the usability of the application. Indeed the less HTTP requests you send the better for the usability.

Here is the complete list of events that you can use with Ionic:

$scope.$on('$ionicView.loaded', function(){});
$scope.$on('$ionicView.enter', function(){});
$scope.$on('$ionicView.leave', function(){});
$scope.$on('$ionicView.beforeEnter', function(){});
$scope.$on('$ionicView.beforeLeave', function(){});
$scope.$on('$ionicView.afterEnter', function(){});
$scope.$on('$ionicView.afterLeave', function(){});
$scope.$on('$ionicView.unloaded', function(){});

More information


Native transitions

It is now possible to use native transitions within Ionic applications. I created ionic-native-transitions, a plugin that helps you configuring Telerik’s native transition Cordova plugin.

More information


Cordova

Crosswalk

I highly recommend using Crosswalk. Basically it embedded the latest chromium into the app (adding around 20Mb per apk: ARM and X86) so you have the same experience on every android version/device.

Installing it is as easy as that:

cordova plugin add cordova-plugin-crosswalk-webview@1.2.0

Try it out, for me Crosswalk has been a game changer in the hybrid industry, it makes applications smoother.


That’s all I could come up with on top of my head, if I missed things please let me know by commenting.

Toptal interview process explained

Introduction to toptal

Toptal is platform for Freelancers to meet clients from all over the world. It is similar to freelancer.com, elance.com or upwork.com but with a big difference, Toptal claims to have the best freelancers there are thanks to a high level interview process. Here is a video that will help you better understand Toptal.

It took me two months to go through all the interview steps to become a Toptal Engineer, part of the so called The Top 3%! Here is how things went:

Interview process

Language & Personality (26.4% pass)

The first step in the screening process is a comprehensive language, personality, and communication interview. Candidates must be able to read, write, and speak English extremely well.

You need to show them that you are invested and passionated about your work (maybe you have a blog or you commit on famous open source projects etc.). Find something that makes you an above average developer and start from there.

Be yourself, do not be stressed and everything will be alright.


Timed Algorithm Testing (7.4% pass)

This step checks for computer science fundamentals, problem solving ability, and intellect. I spent days going through old algorithm books and refreshing my memory about famous algorithms time complexity. If you do not have at least the background listed in this article: JavaScript background to have before any job interview with top companies do not even try.

You will have 90 minutes to solve three algorithms on https://codility.com/. To be honest you cannot do all of them in the given time, focus only on two but make them great! Obviously I cannot disclose the content of those tests but let just say that they were really different from each other and therefore required a large algorithm knowledge.

This is the most difficult part of the interview process. If you do not spend some time learning algorithm basics you will fail. My advice is to get back to your university books and train as much as you can. Open Codility and start coding! If you need a little help my solutions are available on this post: Codility efficient algorithm solutions in JavaScript


Technical Screenings (3.6% pass)

Each candidate is screened by at least two certified Toptal engineers. Each screener will provide specific live coding exercises that cover core topics within the candidate’s primary tech stack.

You will have the choice between a back end or a front end test. I obviously selected the front end test. You will have real life problems to solve using a specific technology. For me it was jQuery, and to be honest at the beginning I was a little bit skeptical on my ability to succeed as I did not used jQuery for a while but I sorted things out pretty easily.

If you have the experience you claim to have, you should not have any difficulty with this step.


Test Projects (3.2% pass)

Ok now we are talking! If you arrive here, it means that you are pretty good at what you do but this step is somehow special. It tests your ability to commit to a project and your willingness to become a Toptal engineer! It is a great way to demonstrate technical competence, thoroughness, professionalism, and integrity.

I have heard there are several projects that you can end up with. One of them is a classic Todo list but the one I got was the creation of a Web page form that creates new users dynamically. I received around 20 wireframes that I had to bring to life in two weeks time using the technology that I wanted.

It had to be pixel perfect and fully functional. I am more of a mobile (cordova), single page application kind of guy so I actually learnt stuff doing this project. For example to help you doing pixel perfect pages you can use the Perfect pixel Chrome extension.

What I believe is that they are trying to give you a project that is a little bit far from your comfort zone to test your ability to learn/discover new stuff while delivering high quality projects.

I chose to use Webpack, Bootstrap 3 and jQuery and I spent around 20 hours to finish this project.

Once it is done you will review the project and the code with a recruiter and that’s it, the interview process is now over and if you are lucky enough you will be part of Toptal 🙂

Select only technologies that are mature enough, you do not want to waste time on bugs that are not part of your code.


Acknowledgment

I personally wanted to thank recruiters and engineers that I talked to. They are really professional and are here to help you succeed.

Conclusion

Overall this experience was really good to me, during the process I wrote greats articles JavaScript background to have before any job interview with top companies and Codility efficient algorithm solutions in JavaScript that really helped me reviewing my basics and taught me that in life nothing is impossible as long as your are brave enough.

In case your are interested in my profile: http://www.toptal.com/resume/julien-renaux

JavaScript background to have before any job interview with top companies

Data types and data structures

In JavaScript, there are 6 primitive data types, a primitive (primitive value, primitive data type) is data that is not an object and has no methods.

Primitives

Boolean

In computer science, a boolean is a logical data type that can have only the values true or false.


Null

In computer science, a null value represents a reference that points, generally intentionally, to a nonexistent or invalid object or address.


Undefined

A primitive value automatically assigned to variables that have just been declared or to formal arguments for which there are no actual arguments.


Number

In JavaScript, Number is a numeric data type in the double-precision 64-bit floating point format (IEEE 754). In other programming languages different numeric types can exist, for examples: Integers, Floats, Doubles, or Bignums.


String

In any computer programming language, a string is a sequence of characters used to represent text.


Symbol (new in ECMAScript 6)

A Symbol is a unique and immutable primitive value and may be used as the key of an Object property.

const MY_KEY = Symbol();
let obj = {};
    
obj[MY_KEY] = 123;
console.log(obj[MY_KEY]); // 123

Object

Object refers to a data structure containing data and instructions for working with the data. Objects sometimes refer to real-world things like a user for instance:

var user = {
    "first_name" : "Julien",
    "last_name" : "Renaux"
}

console.log("My name is " + user["first_name"] + " " + user["last_name"]); // My name is Julien Renaux

Algorithm time complexity (Big O)

Complexity is express using big-O notation. For a problem of size N:

  • a constant-time method is “order 1”: O(1)
  • a linear-time method is “order N”: O(N)
  • a quadratic-time method is “order N squared”: O(N2)

big_o


For loop: O(N)

The loop executes N times, so the sequence of statements also executes N times. Since we assume the statements are O(1), the total time for the for loop is N * O(1), which is O(N) overall.

for (var i = 0; i < N.length; i++) {

}

Several For loops: O(max(N,M))

for (var i = 0; i < N.length; i++) {

}

for (var j = 0; j < M.length; j++) {

}

Nested For loops: O(N * M)

The outer loop executes N times. Every time the outer loop executes, the inner loop executes M times. As a result, the statements in the inner loop execute a total of N * M times. If N equal M then the complexity is O(N^2).

for (var i = 0; i < N.length; i++) {
    for (var j = 0; j < M.length; j++) {

    }
}

Sorting: O(N*log(N))

Typical serial sorting algorithms good behavior is O(N*log(N))

N.sort(function(a, b){
    return a - b;
})

Classic Algorithms

Algorithmic questions are a classic especially in Nord American companies. Facebook, Google, Twitter they all.

What interviewers seek is to see if you can logically resolve some of the basic problems known to computer science. The following algorithms will be as clear as they can be so you can understand the logic. It is not about algorithm elegance nor performance.


Binary search

Binary search is one of the fundamental algorithms in computer science. In its simplest form, binary search is used to quickly find a value in a sorted sequence. git bisect uses it to quickly find the commit that introduced a bug.

function binarySearch(haystack, needle) {
    var lo = 0,
        hi = haystack.length - 1,
        mid;
    while (lo <= hi) {
        mid = Math.floor((lo + hi) / 2);
        if (haystack[mid] < needle) {
            lo = mid + 1;
        } else if (haystack[mid] > needle) {
            hi = mid - 1;
        } else {
            return mid;
        }
    }
    return -1;
}
// Unsorted list
var list = [80, 9, 700, 40, 1, 5, 200];

// Now sorted
list.sort(function(a,b){
    return a - b;
});

// In which position is the number 200? Response: 5
binarySearch(list, 200);

Complexity: Since each comparison binary search uses halves the search space, we can assert and easily prove that binary search will never use more than O(log N) comparisons to find the target value.


Prime number

function isPrime(n){
  var divisor = 2;

  while (n > divisor){
    if(n % divisor == 0){
     return false; 
    }
    else
      divisor++;
  }
  return true;
}
// Response: true
isPrime(137);

// Response: false
isPrime(237);

Fibonacci

In mathematics, the Fibonacci numbers or Fibonacci sequence are the numbers in the following integer sequence: 0 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144 …

It is defined by the recurrence relation: Fibonacci recurrence relation

Code Recursive

The below algorithm performs is elegant but not efficient when the sequence grows exponentially,
we get an inefficient solution.

function fibonacci(n){
    if(n < 2) return n;
    return fibonacci(n-1) + fibonacci (n-2);  
}
fibonacci(2); // Response: 1
fibonacci(3); // Response: 2
fibonacci(4); // Response: 3
fibonacci(5); // Response: 5

Complexity: O(2^n) Why?

Code dynamic programming

We can calculate the values F0, F1, . . . , Fn based on the previously calculated numbers (it is sufficient to remember only the last two values).

function fibonacci(n){
    var fiboSequence = [0, 1];
    
    if (n < 2) return n;
    
    for (var i = 2; i <=n; i++ ){
        fiboSequence[i] = fiboSequence[i-1] + fiboSequence[i-2];
    }
    
    return fiboSequence[n];
} 
fibonacci(2); // Response: 1
fibonacci(3); // Response: 2
fibonacci(4); // Response: 3
fibonacci(5); // Response: 5

Complexity: The time complexity of the above algorithm is O(n).


Going further

Once those basic algorithms in mind if you want to go further I suggest you test yourself using Codility’s great challenges.

Some of the solutions in JavaScript are available here: Codility efficient algorithm solutions in JavaScript


Design Patterns

Before an interview you need to know some of the most known design patterns and anti patterns. To do so I highly recommend reading Addy Osmani’s book “Learning JavaScript Design Patterns”. It is available for free http://addyosmani.com/resources/essentialjsdesignpatterns/book under http://creativecommons.org/licenses/by-nc-nd/3.0/.

Creational

Creational design patterns are design patterns that deal with object creation mechanisms, trying to create objects in a manner suitable to the situation.

Some of the patterns that fall under this category are: Constructor, Factory, Abstract, Prototype, Singleton and Builder.

Factory

The Factory pattern is another creational pattern concerned with the notion of creating objects. Where it differs from the other patterns in its category is that it doesn’t explicitly require us use a constructor. Instead, a Factory can provide a generic interface for creating objects, where we can specify the type of factory object we wish to be created.

More info: http://addyosmani.com/resources/essentialjsdesignpatterns/book/#factorypatternjavascript

// A constructor for defining new cars
function Car(options) {
    this.doors = options.doors || 4;
    this.state = options.state || "brand new";
    this.color = options.color || "silver";

}

// A constructor for defining new trucks
function Truck(options) {
    this.state = options.state || "used";
    this.wheelSize = options.wheelSize || "large";
    this.color = options.color || "blue";
}

// Define a skeleton vehicle factory
function VehicleFactory() {}

// Define the prototypes and utilities for this factory

// Our default vehicleClass is Car
VehicleFactory.prototype.vehicleClass = Car;

// Our Factory method for creating new Vehicle instances
VehicleFactory.prototype.createVehicle = function(options) {

    switch (options.vehicleType) {
        case "car":
            this.vehicleClass = Car;
            break;
        case "truck":
            this.vehicleClass = Truck;
            break;
            //defaults to VehicleFactory.prototype.vehicleClass (Car)
    }

    return new this.vehicleClass(options);
};

// Create an instance of our factory that makes cars
var carFactory = new VehicleFactory();
var car = carFactory.createVehicle({
    vehicleType: "car",
    color: "yellow",
    doors: 6
});

// Test to confirm our car was created using the vehicleClass/prototype Car

// Outputs: true
console.log(car instanceof Car);

Prototype

We can think of the prototype pattern as being based on prototypal inheritance where we create objects which act as prototypes for other objects. The prototype object itself is effectively used as a blueprint for each object the constructor creates. If the prototype of the constructor function used contains a property called name for example (as per the code sample lower down), then each object created by that same constructor will also have this same property.

More info: http://addyosmani.com/resources/essentialjsdesignpatterns/book/#prototypepatternjavascript

var myCar = {

    name: "Ford Escort",

    drive: function() {
        console.log("Weeee. I'm driving!");
    },

    panic: function() {
        console.log("Wait. How do you stop this thing?");
    }

};

// Use Object.create to instantiate a new car
var yourCar = Object.create(myCar);

// Now we can see that one is a prototype of the other
console.log(yourCar.name);

Singleton

The Singleton pattern is thus known because it restricts instantiation of a class to a single object. Classically, the Singleton pattern can be implemented by creating a class with a method that creates a new instance of the class if one doesn’t exist. In the event of an instance already existing, it simply returns a reference to that object.

More info: http://addyosmani.com/resources/essentialjsdesignpatterns/book/#singletonpatternjavascript

var mySingleton = (function() {
    // Instance stores a reference to the Singleton
    var instance;

    function init() {
        // Private methods and variables
        function privateMethod() {
            console.log("I am private");
        }

        var privateVariable = "Im also private";

        var privateRandomNumber = Math.random();

        return {
            // Public methods and variables
            publicMethod: function() {
                console.log("The public can see me!");
            },
            publicProperty: "I am also public",
            getRandomNumber: function() {
                return privateRandomNumber;
            }
        };
    };
    return {
        // Get the Singleton instance if one exists
        // or create one if it doesn't
        getInstance: function() {
            if (!instance) {
                instance = init();
            }
            return instance;
        }
    };
})();

var singleA = mySingleton.getInstance();
var singleB = mySingleton.getInstance();
console.log(singleA === singleB); // true

Structural

Structural design patterns are design patterns that ease the design by identifying a simple way to realize relationships between entities.

Patterns that fall under this category include: Decorator, Facade, Flyweight, Adapter and Proxy.

Decorator

Decorators are a structural design pattern that aim to promote code re-use. Similar to Mixins, they can be considered another viable alternative to object sub-classing.

Classically, Decorators offered the ability to add behaviour to existing classes in a system dynamically.

More info: http://addyosmani.com/resources/essentialjsdesignpatterns/book/#decoratorpatternjavascript

function Vehicle(vehicleType) {
    this.vehicleType = vehicleType || "car";
    this.model = "default";
    this.license = "00000-000";
}

// Lets create a new instance of vehicle, to be decorated
var truck = new Vehicle("truck");

// New functionality we're decorating vehicle with
truck.setModel = function(modelName) {
    this.model = modelName;
};

truck.setColor = function(color) {
    this.color = color;
};

// Test the value setters and value assignment works correctly
truck.setModel("CAT");
truck.setColor("blue");

console.log(truck);

// Outputs:
// vehicle:truck, model:CAT, color: blue

// Demonstrate "vehicle" is still unaltered
var secondInstance = new Vehicle("car");
console.log(secondInstance);

Behavior

Behavioral design patterns are design patterns that identify common communication patterns between objects and realize these patterns. By doing so, these patterns increase flexibility in carrying out this communication.

Some behavioral patterns include: Iterator, Mediator, Observer and Visitor.

Iterator

The Iterator is a design pattern where iterators (objects that allow us to traverse through all the elements of a collection) access the elements of an aggregate object sequentially without needing to expose its underlying form.

Iterators encapsulate the internal structure of how that particular iteration occurs. In the case of jQuery’s jQuery.fn.each() iterator, we are actually able to use the underlying code behind jQuery.each() to iterate through a collection, without needing to see or understand the code working behind the scenes providing this capability.

More info: http://addyosmani.com/resources/essentialjsdesignpatterns/book/#iteratorpatternjquery

$.each(["john", "dave", "rick", "julien"], function(index, value) {
    console.log(index + ": " + value);
});

Here we can see the code for jQuery.fn.each():

// Execute a callback for every element in the matched set.
each: function(callback, args) {
    return jQuery.each(this, callback, args);
}

Followed by a simplified version of the code behind jQuery.each()

each: function(object, callback, args) {
    var name, i = 0,
        length = object.length,
        isObj = length === undefined || jQuery.isFunction(object);

    if (isObj) {
        for (name in object) {
            if (callback.call(object[name], name, object[name]) === false) {
                break;
            }
        }
    } else {
        for (; i < length;) {
            if (callback.call(object[i], i, object[i++]) === false) {
                break;
            }
        }
    }
    return object;
};

Sources

Creating an application with AngularJS 1.4, ECMAScript 6, Material Design and Webpack

AngularJS 1.4 has now been released.

It introduces a new Router, a translation system similar to angular-translate created by Pascal Precht, some performance enhancement and a better Webpack, Browserify support (CommonJS) without any “hacks”. You can for example directly import AngularJS like this

import 'angular/angular.js';

instead of this

require('expose?angular!exports?window.angular!angular/angular.js')

Demo

Source available on Github : https://github.com/shprink/angular1.4-ES6-material-webpack-boilerplate


Basic Needs

Dependencies (package.json)

For this tutorial we will need AngularJS, Angular Material, the UI router (The new router is not ready for production yet) and a icon library.

"dependencies": {
    "angular": "~1.4.0",
    "angular-animate": "~1.4.0",
    "angular-aria": "~1.4.0",
    "angular-material": "^0.10.1",
    "angular-ui-router": "^0.2.14",
    "font-awesome": "^4.3.0"
}

Webpack

If you need an explanation on what is Webpack for, I suggest you go check out a previous post of mine: http://julienrenaux.fr/2015/03/30/introduction-to-webpack-with-practical-examples/

We will need the following Webpack loaders to be able to compile ECMAScript 6 code and to process CSS, HTML files.

"devDependencies": {
    "babel-loader": "^5.0.0",
    "css-loader": "^0.12.0",
    "file-loader": "^0.8.1",
    "html-loader": "^0.3.0",
    "html-webpack-plugin": "^1.3.0",
    "style-loader": "^0.12.1"
}

The webpack.config.js cannot be easier:

module.exports = {
    entry: './lib/index.js',
    output: {
        path: './www',
        filename: 'bundle-[hash:6].js'
    },
    module: {
        loaders: [{
            test: /.html$/,
            loader: 'file?name=templates/[name]-[hash:6].html'
        }, {
            test: /.css$/,
            loader: "style!css"
        }, {
            test: /.js$/,
            exclude: /(node_modules)/,
            loader: "ng-annotate?add=true!babel"
        }, {
            test: [/fontawesome-webfont.svg/, /fontawesome-webfont.eot/],
            loader: 'file?name=fonts/[name].[ext]'
        }]
    },
    plugins: [
        new HtmlWebpackPlugin({
            filename: 'index.html',
            template: './lib/index.html'
        })
    ]
};

Entry point (lib/index.js)

The following entry point gathers all our application basic needs: Angular, Material Design, the router and the icons. Here we use import which is the ECMAScript 6 way to require CommonJS modules, inject angularMaterial and angularUIRouter as our module dependencies and to finish we export our module as default (You can export several modules within a single file, default is the export you will get if you do not specify a specific import).

// Import angular
import 'angular/angular.js';
// Material design css
import 'angular-material/angular-material.css';
// Icons
import 'font-awesome/css/font-awesome.css';
// Materail Design lib
import angularMaterial from 'angular-material';
// Router
import angularUIRouter from 'angular-ui-router';

// Create our demo module
let demoModule = angular.module('demo', [
    angularMaterial,
    angularUIRouter
])

export default demoModule;

Index.html

The index.html needs two things. A way to bootstrap the application (here ng-app="demo") and a way to include the JavaScript file generated by Webpack (here src="{%=o.htmlWebpackPlugin.assets[chunk]%}").

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
    </head>
    <body ng-strict-di ng-app="demo">
        {% for (var chunk in o.htmlWebpackPlugin.assets) { %}
        <script src="{%=o.htmlWebpackPlugin.assets[chunk]%}"></script>
        {% } %}
    </body>
</html>

Now you should have your demo module running. To make sure it works add the following lines to your entry point:

demoModule.run(($log) => {
    $log.info('demo running');
})

and check the console!


Going further

Create your own module

Now that our application is running let’s create a home module with ES6!

// Create a new module
let homeModule = angular.module('demo.home', []);
// Named export is needed to inject modules directly as Angular dependencies
export default homeModule = homeModule.name

Then we can import it the same way as other modules:

import home from './home/home.module.js';

// Create our demo module
let demoModule = angular.module('demo', [
    angularMaterial,
    angularUIRouter,
    home
])

Now let’s create a controller function './home.controller' that will be imported by our new module:

export default function($scope) {
    'ngInject';
}

'ngInject'; is an annotation of ng-annotate that allow us to use AngularJS in strict mode. If you want to know more about Ng-annotate here is an explanation: http://julienrenaux.fr/2015/01/18/angularjs-1-x-open-source-projects-to-follow-in-2015/#Ng-Annotate

We can then import the function that way:

let homeModule = angular.module('demo.home', []);

import HomeController from './home.controller';

homeModule.controller('HomeController', HomeController);

export default homeModule = homeModule.name

Full demo

A working example is available on Github, feel free to fork: https://github.com/shprink/angular1.4-ES6-material-webpack-boilerplate

Install

git clone git@github.com:shprink/angular1.4-ES6-material-webpack-boilerplate.git
cd angular1.4-ES6-material-webpack-boilerplate.git
npm install

Dev (liverelaod server)

npm run-script devserver

Build

npm run-script build

Codility efficient algorithm solutions in JavaScript

This post aim is to provide Codility algorithm solutions in JavaScript as there are so many of then available out there. I am not pretending to have the best algorithm possible but at least the following answers scored 100% on Codility test result.

After reading the task description a wise thing to do is to check the expected worst case time complexity. It gives you a hint on how to apprehend the solution. For instance if the worst case time complexity is O(N), you would probably need to use a for loop, if it is O(N*M) a nested for loop might be necessary etc.

big_o

This post in on going, I am adding new solutions often.

Lesson 1: Time Complexity

FrogJmp

Difficulty: PAINLESS

Count minimal number of jumps from position X to Y.

https://codility.com/demo/take-sample-test/frog_jmp

Expected time complexity: worst-case is O(1)

function solution(X, Y, D) {
    return Math.ceil((Y - X)/ D);
}

PermMissingElem

Difficulty: PAINLESS

Find the missing element in a given permutation.

https://codility.com/demo/take-sample-test/perm_missing_elem

Expected time complexity: worst-case is O(N)

function solution(A) {
    var length = A.length;
    var sum = ((length + 1) /2) * (length + 2);
    var sumMinusMissing = 0;
    for (i = 0; i < length; i++) { 
        sumMinusMissing += A[i];
    }
    return sum - sumMinusMissing;
}

TapeEquilibrium

Difficulty: PAINLESSS

Minimize the value |(A[0] + … + A[P-1]) – (A[P] + … + A[N-1])|

https://codility.com/demo/take-sample-test/tape_equilibrium

Expected time complexity: worst-case is O(N)

function solution(A) {
    var sumAfter = sumBefore = 0;
    var minDiff = Number.POSITIVE_INFINITY;
    
    A.forEach(function(value){
        sumAfter += value;
    });
    
    for (var i = 1; i < A.length; i++){
        sumBefore += A[i -1];
        sumAfter = sumAfter - A[i -1];
        minDiffTemp = Math.abs(sumBefore - sumAfter);
        if (minDiffTemp < minDiff){
            minDiff = minDiffTemp;
        }
    }
    return minDiff;
}

Lesson 2: Counting Elements

MaxCounters

Difficulty: RESPECTETABLE

Calculate the values of counters after applying all alternating operations: increase counter by 1; set value of all counters to current maximum.

https://codility.com/demo/take-sample-test/max_counters

Expected time complexity: worst-case is O(N+M)

function solution(N, A) {
    var counters = [], 
    size = N, 
    max = 0,
    forValue = 0,
    counter = 0,
    lastUpdate = 0;
    // init zeros
    for (var i = 0; i < N; i++){
        counters[i] = 0;
    }
    
    for (var i = 0; i < A.length; i++){
        if (A[i] <= N){
            position = A[i] -1;
            if (counters[position] < lastUpdate){
                counters[position] = lastUpdate + 1;
            } else {
                counters[position] = counters[position]+1;
            }
            if (counters[position] > max) {
                max = counters[position];
            }
        } else {
            lastUpdate = max;
        }
    }
    
    for (var i = 0; i < N; i++){
        if (counters[i] < lastUpdate)
            counters[i] = lastUpdate;
    }
    
    return counters;
}

MissingInteger

Difficulty: RESPECTETABLE

Find the minimal positive integer not occurring in a given sequence.

https://codility.com/demo/take-sample-test/missing_integer

Expected time complexity: worst-case is O(N)

function solution(A) {
    var onlyPositiveInt = [];
    for (var i =0; i < A.length; i++){
        if (A[i] > 0 ){
            onlyPositiveInt[A[i]] = true;
        }
    }
    for (i = 1; i <= onlyPositiveInt.length; i++){
        if (!onlyPositiveInt[i]){
            return i;
        }
    }
    return 1;
}

Lesson 3: Prefix Sums

In computer science, the prefix sum, scan, or cumulative sum of a sequence of numbers x0, x1, x2, … is a second sequence of numbers y0, y1, y2, …, the sums of prefixes (running totals) of the input sequence

http://en.wikipedia.org/wiki/Prefix_sum

Material https://codility.com/media/train/3-PrefixSums.pdf

PassingCars

Difficulty: PAINLESS

Count the number of passing cars on the road.

https://codility.com/demo/take-sample-test/passing_cars

Expected time complexity: worst-case is O(N)

function solution(A) {
    var ones = 0, passing = 0;
    for(var i=A.length-1; i>=0; i--) {
	    if (A[i] === 0){
	        passing += ones;
	        if (passing > 1000000000){
	            return -1;
	        }
	    } else {
	       ones ++;
	    }
    }
    return passing;
}

CountDiv

Difficulty: RESPECTETABLE

Compute number of integers divisible by k in range [a..b].

https://codility.com/demo/take-sample-test/count_div

For this one your coding skills won’t help. It is a pure math problem.

Expected time complexity: worst-case is O(1)

function solution(A, B, K) {
    if (A % K === 0)
        return Math.floor((B - A) / K + 1);
    return Math.floor((B - (A - (A % K) )) / K)
}

MinAvgTwoSlice

Difficulty: RESPECTETABLE

Find the minimal average of any slice containing at least two elements.

https://codility.com/demo/take-sample-test/min_avg_two_slice

Expected time complexity: worst-case is O(N)

Still searching for this one. If you have a 100% solution please share 🙂

GenomicRangeQuery

Difficulty: RESPECTETABLE

Find the minimal nucleotide from a range of sequence DNA.

https://codility.com/demo/take-sample-test/genomic_range_query

Expected time complexity: worst-case is O(N+M)

function solution(S, P, Q) {
    var positionOne,
    positionTwo,
    factorPerType = {
        "A":1,
        "C":2,
        "G":3,
        "T":4
    },
    prefix = [[0,0,0,0]],
    Plen = P.length,
    Slen = S.length,
    result =[],
    counterType = [0,0,0,0];

    for(var i = 0; i<Slen; i++) {
        counterType = counterType.concat(); // local copy
        counterType[factorPerType[S[i]] -1]++;
        prefix.push(counterType);
    }
    
    for(i=0; i<Plen; i++) {
	    positionOne = P[i] + 1;
	    positionTwo = Q[i]+ 1;

	    var finalCount =0;
	    for (j = 0; j < 4; j++){
	        finalCount = prefix[positionTwo][j] - prefix[positionOne -1][j];
	        if (finalCount > 0){
	            result.push(j + 1);
	            break;
	        }
	    }
    }
 
    return result;
}

Lesson 4: Sorting

MaxProductOfThree

Difficulty: PAINLESS

Maximize A[P] * A[Q] * A[R] for any triplet (P, Q, R).

https://codility.com/demo/take-sample-test/max_product_of_three

Expected time complexity: worst-case is O(N*log(N))

function solution(A) {
    var N = A.length;

    // Sort ascending
    A.sort(function(a, b){
        return a - b;
    });
    // the max product of three elements is the product of the last three
    // elements in the sorted array or the product of the first two elements
    // and the last element if the first two elements are negatives.    
    return Math.max(A[0] * A[1] * A[N-1], A[N-3] * A[N-2] * A[N-1]);
}

Distinct

Difficulty: PAINLESS

Compute number of distinct values in an array.

https://codility.com/demo/take-sample-test/distinct

Expected time complexity: worst-case is O(N*log(N))

function solution(A) {
    var leng = A.length, counter = 0;

    // Sort ascending
    A.sort(function(a, b){
        return a - b;    
    });
    
    for (var i=1; i <= leng; i++){
        if (A[i] != A[i - 1]){
            counter++;   
        }
    }
    
    return counter;
}

Triangle

Difficulty: PAINLESS

Determine whether a triangle can be built from a given set of edges.

https://codility.com/demo/take-sample-test/triangle

Expected time complexity: worst-case is O(N*log(N))

function solution(A) {
    var len = A.length;
    
    // Sort descending
    A.sort(function(a, b){
        return b - a; 
    });
    
    for(var i=0; i<len - 2; i++) {
        var P = i, Q= i+1, R= i+2;
        var condition1 = A[P] + A[Q] > A[R];
        var condition2 = A[Q] + A[R] > A[P];
        var condition3 = A[R] + A[P] > A[Q];
        if (condition1 && condition2 && condition3){
            return 1;
        }
    }
    return 0;
}

NumberOfDiscIntersections

Difficulty: RESPECTETABLE

Compute intersections between sequence of discs.

https://codility.com/demo/take-sample-test/number_of_disc_intersections/

Expected worst-case time complexity is O(N*log(N));

function solution(A) {
    var len =  A.length,
    tupples = [],
    count =0;
    
    for (var i=0; i < len; i++){
        tupples.push([i - A[i], i + A[i]]);  
    }
    
    // [[5,5], [0,4], [-4, 6]] => [[-4, 6], [0,4], [5,5]]
    tupples.sort(function(a,b){
        return a[0] - b[0];
    });

    for (var j=0; j < len; j++){
        var tupple = tupples[j];
        for (var k=j+1; k < len; k++){
            var comparisonTupple = tupples[k];
            if (comparisonTupple[0] <= tupple[1]){
                count++;
                if (count >10000000){
                    return -1;    
                }
            } else {
                break;    
            }
        } 
    }
    return count;
}

Lesson 5: Stacks and Queues

Brackets

Difficulty: PAINLESS

Determine whether given string of parentheses is properly nested.

https://codility.com/demo/take-sample-test/brackets/

Expected worst-case time complexity is O(N)

function solution(S) {
    var len = S.length;
    
    if (!len){
        return 1;
    }
    
    var stack = [],
    matches = {
        "{" : "}",  
        "(" : ")", 
        "[" : "]"   
    };
    
    for (i=0; i < len; i++){
        var currentCharacter = S[i];
        if (matches[currentCharacter]){
            stack.push(currentCharacter);
        } else {
            if (!stack.length){
                return 0;
            }   
            var previousCharacter = stack.pop();
            if (matches[previousCharacter] !== currentCharacter){
                return 0;
            }   
        }   
    }        
    
    return (stack.length)? 0 : 1;
}

Nesting

Difficulty: PAINLESS

Determine whether given string of parentheses is properly nested.

https://codility.com/demo/take-sample-test/nesting/

Expected worst-case time complexity is O(N)

function solution(S) {
    var len = S.length;
    
    if (!len){
        return 1;
    }
    
    var stack = [],
    matches = {
        "(" : ")" 
    };
    
    for (i=0; i < len; i++){
        var currentCharacter = S[i];
        if (matches[currentCharacter]){
            stack.push(currentCharacter);
        } else {
            if (!stack.length){
                return 0;
            }   
            var previousCharacter = stack.pop();
            if (matches[previousCharacter] !== currentCharacter){
                return 0;
            }   
        }   
    }        
    
    return (stack.length)? 0 : 1;
}

Fish

Difficulty: PAINLESS

N voracious fish are moving along a river. Calculate how many fish are alive.

https://codility.com/demo/take-sample-test/fish/

Expected worst-case time complexity is O(N)

function solution(A, B) {
    var len = A.length,
    count = parseInt(len),
    stackDownstreamFishes = [];
    
    for (var i = 0; i < len; i++){
        var direction = B[i] ? 'downstream' : 'upstream';
        if (direction === 'downstream'){
            stackDownstreamFishes.push(A[i]);    
        } else {            
            // Going backward through all downstream fishes
            for(var j= stackDownstreamFishes.length-1; j>=0; j--) {
                var lastDownstreamFishSize = stackDownstreamFishes[j];
                if (lastDownstreamFishSize > A[i]){
                    count--;
                    break;
                } else if (lastDownstreamFishSize < A[i]){
                    count--;
                    stackDownstreamFishes.pop();
                }
            }
        }
    }
    return count;
}

StoneWall

Difficulty: PAINLESS

Cover “Manhattan skyline” using the minimum number of rectangles.

https://codility.com/demo/take-sample-test/stone_wall/

Expected worst-case time complexity is O(N)

function solution(H) {
    var len = H.length,
        stack = [H[0]],
        result = 1;
    if (!len) {
        return 0;
    }
    for (var i = 1; i < len; i++) {
        var currentHeight = H[i];
        while (stack.length && stack[stack.length - 1] >= currentHeight) {
            if (currentHeight == stack[stack.length - 1]) {
                result--;
            }
            stack.pop();
        }
        stack.push(currentHeight);
        result++;
    }
    return result;
}

I started with a backward for loop:

for (var j = stack.length - 1; j >= 0; j--) {
    if (stack[j] < currentHeight) {
        break;
    }
    if (stack[j] == currentHeight) {
        result--;
    }
    stack.pop();
}

But a while loop is faster: https://jsperf.com/compare-while-loop-vs-for-loop/4


Lesson 6: Leader

Material https://codility.com/media/train/6-Leader.pdf

EquiLeader

Difficulty: PAINLESS

Find the index S such that the leaders of the sequences A[0], A[1], …, A[S] and A[S + 1], A[S + 2], …, A[N – 1] are the same.

https://codility.com/demo/take-sample-test/equi_leader/

Expected worst-case time complexity is O(N)

function solution(A) {
    var len = A.length,
        i = 0,
        j = 0,
        k = 0,
        size = 0,
        indexCount = 0,
        candidateCount = 0,
        leader,
        leaderCount = 0,
        candidate = null;

    // First find the leader within A
    for (; i < len; i++) {
        if (size === 0) {
            size++;
            candidate = A[i];
        } else {
            (candidate === A[i]) ? size++ : size--;
        }
    }

    for (; j < len; j++) {
        if (A[j] === candidate) {
            candidateCount++;
        }
    }

    if (candidateCount <= len / 2) { // Our candidate failed 🙁
        return 0;
    } else { // we have a winner!
        leader = candidate;
        leaderCount = candidateCount;
    }

    var leaderLeftCount = 0;
    for (; k < len - 1; k++) {
        var lenLeft = (k + 1);
        var lenRight = len - lenLeft;
        if (A[k] === leader) {
            leaderCount--;
            leaderLeftCount++;
        }
        if (leaderLeftCount > (lenLeft / 2) && leaderCount > (lenRight / 2)) {
            indexCount++;
        }
    }
    return indexCount;
}

Dominator

Difficulty: PAINLESS

Find an index of an array such that its value occurs at more than half of indices in the array.

https://codility.com/demo/take-sample-test/dominator/

Expected worst-case time complexity is O(N)

function solution(A) {
    var len = A.length,
    i = 0,
    j = 0,
    leaderCount = 0,
    latestIndex = -1,
    size = 0,
    candidate = null,
    value = null;
    
    for (; i < len; i++){
        if (size === 0){
            size++;
            value = A[i];
        } else {
            value !== A[i] ?  size-- : size++;
        }
    }
    
    candidate = value;
    for (; j < len; j++){
        if (candidate === A[j]){
            leaderCount++;
        }
        if (leaderCount > len / 2){
            latestIndex = j;
            break;
        }
    }
    return latestIndex;
}

## Lesson 7: Maximum slice problem

Material

### MaxProfit

Difficulty: PAINLESS

Given a log of stock prices compute the maximum possible earning.

Expected worst-case time complexity is O(N)

At first I could not find a better solution the following:

function solution(A) {
    var len = A.length,
    i= len-1,
    max = 0;
    
    for(; i>=0; i--) {
    	var stockShare = A[i];
    	for(j = i-1; j>=0; j--) {
    	   var diff = stockShare - A[j];
    	   if (diff > max){
    	       max = diff;
    	   }
    	}
    }
    return max;
}

The time complexity is quadratic O(N^2) which is terrible.

Then I spent a little more time thinking about it and I ended up writing the following which has the correct time complexity: O(N).


Introduction to Webpack with practical examples

Webpack is taking the task automation market by a storm. I have been using it for months now and for most of my needs Webpack took over Grunt and Gulp.

Webpack is a module bundler, it takes modules with dependencies and generates static assets representing those modules.

This post will only focus about Webpack “loaders” and “post loaders”.

Webpack Loaders

Loaders are pieces of code that can be injected in the middle of the compilation stream. Post loaders are called at the end of the stream.

webpack can only process JavaScript natively, but loaders are used to transform other resources into JavaScript. By doing so, every resource forms a module.

Source available on Github

Prerequisite

You will need to have Node and Npm installed on your machine to go through the following examples.

Install

npm install webpack --save-dev

Now create a webpack.config.js file and dump this basic scaffolding in it:

var webpack = require('webpack'),
    path = require('path');

module.exports = {
    debug: true,
    entry: {
        main: './index.js'
    },
    output: {
        path: path.join(__dirname, 'dist'),
        filename: '[name].js'
    },
    module: {
        loaders: []
    }
};

You main entry point is now index.js at the root of your folder. The compiled file will be dumped in the dist folder when compiling.

Compile

When your entry point is defined you can start the compilation using the CLI:

# Debug mode
webpack

# Production mode (minified version)
webpack -p

ECMAScript 6 compilation

ECMAScript 6 introduce tones of new features (Arrows, Classes, Generators, Modules etc.) that can be used right now! To do so I recommend using Babeljs.

Installation:

npm install babel-loader --save-dev

Add the loader to the Webpack configuration:

loaders: [{
  test: /.es6.js$/,
  loader: "babel-loader"
}]

You now can require any ES6 modules using require('./src/index.es6.js');

Result

Before

// Generators
var fibonacci = {
    [Symbol.iterator]: function*() {
        var pre = 0,
            cur = 1;
        for (;;) {
            var temp = pre;
            pre = cur;
            cur += temp;
            yield cur;
        }
    }
}

module.exports = fibonacci;

After

"use strict";

var fibonacci = function() {
    var a = {};
    a[Symbol.iterator] = regeneratorRuntime.mark(function b() {
        var a, c, d;
        return regeneratorRuntime.wrap(function e(b) {
            while (1) switch (b.prev = b.next) {
              case 0:
                a = 0, c = 1;

              case 1:
                d = a;
                a = c;
                c += d;
                b.next = 6;
                return c;

              case 6:
                b.next = 1;
                break;

              case 8:
              case "end":
                return b.stop();
            }
        }, b, this);
    });
    return a;
}();

module.exports = fibonacci;

CoffeeScript compilation

Coffeescript needs no introduction, it has been popular for a long time now.

Installation:

npm install coffee-loader --save-dev

Add the loader to the Webpack configuration:

loaders: [{
  test: /.coffee$/,
  loader: "coffee-loader"
}]

You now can require any CoffeeScript modules using require('./src/index.coffee');

Result

Before

module.exports = ->
    square = (x) -> x * x
    math =
      root: Math.sqrt
      square: square
      cube: (x) -> x * square x

After

module.exports = function() {
  var math, square;
  square = function(x) {
    return x * x;
  };
  return math = {
    root: Math.sqrt,
    square: square,
    cube: function(x) {
      return x * square(x);
    }
  };
};

Require CSS files

Installation:

npm install css-loader --save-dev

Add the loader to the Webpack configuration:

The css-loader will create a style tag that will be injected into your page on run time. The css-loader also takes care of minification when called in the production mode (-p) e.g webpack -p

loaders: [{
  test: /.css$/,
  loader: "css-loader"
}]

You now can require any CSS file using require('./src/index.css');


Autoprefix CSS files

Installation:

npm install autoprefixer-loader --save-dev

Add the loader to the Webpack configuration:

What’s really annoying with CSS is that some properties are not implemented the same way by browsers. That’s the reason behind prefixes -ms- for IE, -moz- for Firefox and -webkit- for Chrome, Opera and Safari. The autoprefixer loader allow you to use the standards CSS properties without having to care for browser compatibility.

loaders: [{
  test: /.css$/,
  loader: "css-loader!autoprefixer-loader"
}]

You now can require any CSS file using require('./src/index.css');

Result

Before

body {
    display: flex; 
}

After

body {
    display: -webkit-box;      /* OLD - iOS 6-, Safari 3.1-6 */
    display: -ms-flexbox;      /* TWEENER - IE 10 */
    display: -webkit-flex;     /* NEW - Chrome */
    display: flex;             /* NEW, Spec - Opera 12.1, Firefox 20+ */
}

Sass compilation

Sass lets you use features that don’t exist in CSS yet like variables, nesting, mixins, inheritance etc. the code created using sass is less complex and therefore easier for developers to maintain than standard CSS.

Installation:

npm install css-loader sass-loader --save-dev

Add the loader to the Webpack configuration:

Here we use two loaders at the same time. The first one the sass-loader (read from right to left) will compile Sass into CSS then the css-loader will create a style tag that will be injected into your page on run time.

loaders: [{
  test: /.scss$/,
  loader: "css-loader!sass-loader"
}]

You now can require any Sass file using require('./src/index.scss');

Result

Before

$font-stack:    Helvetica, sans-serif;
$primary-color: #333;

body {
  font: 100% $font-stack;
  color: $primary-color;
}

After

body {
  font: 100% Helvetica, sans-serif;
  color: #333;
}

Less compilation

Less is a CSS pre-processor similar to Sass.

Installation:

npm install css-loader less-loader --save-dev

Add the loader to the Webpack configuration:

Here we use two loaders at the same time. The first one the less-loader (read from right to left) will compile Less into CSS then the css-loader will create a style tag that will be injected into your page on run time.

loaders: [{
  test: /.less$/,
  loader: "css-loader!less-loader"
}]

You now can require any Sass file using require('./src/index.less');

Result

Before

@font-stack: Helvetica, sans-serif;
@primary-color: #333;
body {
    font: 100% @font-stack;
    color: @primary-color;
}

After

body {
  font: 100% Helvetica, sans-serif;
  color: #333;
}

Move files

You can move any type of file around by using the file-loader.

Installation:

npm install file-loader --save-dev

Add the loader to the Webpack configuration:

For the example let’s try to move images from their directory to a brand new image folder with a naming convention of img-[hash].[ext].

loaders: [{
  test: /.(png|jpg|gif)$/,
  loader: "file-loader?name=img/img-[hash:6].[ext]"
}]

You now can require any image file using require('./src/image_big.jpg');

Result

the image ./src/img.jpg will be copy and renamed as such: dist/img/img-a4bd04.jpg


Encode files

Sometimes you do not want to make HTTP requests to get assets. For example, what’s the point making HTTP requests to get tiny images when you can directly access them encoded (base64) ? The url-loader does just that. What you need to do is to determine the limit (in bytes) under which you want the encoded version of the file (if the file is bigger you will get the path to it).

Installation:

npm install url-loader --save-dev

Add the loader to the Webpack configuration:

When images are under 5kb we want to get a base64 of them and when they are greater than 5kb we want to get the path to them (exactly as with the file-loader).

loaders: [{
  test: /.(png|jpg|gif)$/,
  loader: "url-loader?limit=5000&name=img/img-[hash:6].[ext]"
}]

Result

Before

var imgBig = '<img src="' + require("./src/image_big.jpg") + '" />';
var imgSmall = '<img src="' + require("./src/image_small.png") + '" />';

After

var imgBig = '<img src="img/img-a4bd04.jpg" />';
var imgSmall = '<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA" />';

Require HTML files

The html-loader turn any html file into a module and require any image dependency along the way!

Installation:

npm install html-loader --save-dev

Add the loader to the Webpack configuration:

loaders: [{
  test: /.html$/,
  loader: "html-loader"
}]

You now can require any HTML files using require('./src/index.html');. All images will also be treated as dependencies and therefore go through their specific stream of events (see Encode files).

Result

Before

<html>
    <head>
        <title></title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width">
    </head>
    <body>
        <img src="./image_small.png">
    </body>
</html>

After

module.exports = '<html>n    
   <head>
      n        
      <title></title>
      n        
      <meta charset="UTF-8">
      n        
      <meta name="viewport" content="width=device-width">
      n    
   </head>
   n    
   <body><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA"></body>
   n
</html>';

Expose any module

The expose-loader loader allow you to bind any module to the global scope.

Installation:

npm install expose-loader --save-dev

Add the loader to the Webpack configuration:

In this example we want lodash (Underscore.js decorator) to be exposed in the global scope as _.

loaders: [{
  test: require.resolve("lodash"),
  loader: 'expose?_'
}]

Now when requiring lodash (require('lodash');) will also expose it globally. It is necessary for popular modules such as angularJs, jQuery, underscore, moment or hammerjs.

Creating an hybrid app in minutes with Ionic Framework

Creating hybrid apps with Ionic is really fast and powerful. I have gather a year of information to create an ultimate presentation of Ionic in a airpair blog post: A year using Ionic to build hybrid applications

If you only want a summary of what’s inside this post you can check out the below presentation. It contains all you need to know to create, build and package an hybrid app with Ionic!

[iframely]http://www.slideshare.net/julienrenaux/hybrid-apps-withionic[/iframely]

Some quick tips:

  • Develop in the browser with live reload: ionic serve
  • Add a platform (ios or Android): ionic platform add ios [android] Note: iOS development requires OS X currently
  • Build your app: ionic build
  • Simulate your app: ionic emulate
  • Run your app on a device: ionic run
  • Package an app using Ionic package service: ionic package

D3.js Responsive Word Cloud

There are few examples of word cloud using D3js, the best known is the one from Jason Davies but the code is difficult to understand as it is coupled with the cloud form (angle, number of words etc) and has many functions.

Based on Jason’s D3-cloud project, my aim was to simplify the code, making it responsive and more accessible to anyone. It only has two functions: Draw and Update


Re-size the browser to see the SVG re-rendered.

Source available on Github

Introduction to Gulp.js with practical examples

What is Gulp.js?

Gulp.js is what we call a JavaScript Task Runner, it is Open Source and available on GitHub. It helps you automate repetitive tasks such as minification, compilation, unit testing, linting, etc. Gulp.js does not revolutionize automation but simplifies it tremendously.

Today the Web automation ecosystem is dominated by Grunt.js (which is a great tool BTW) but lately Gulp.js is getting more trending and soon will be overtaking Grunt.js (according to the GitHub popularity, aka “stars”: 7900 for Grunt.js and 6250 for Gulp.js).

How is it better than Grunt or Cakefile?

I would say it is no better nor worse than Grunt or Cakefile, it is different. While Cakefile or Grunt use files to execute tasks, Gulp.js uses streams. It means that a typical Cakefile or Grunt workflow would be to execute a task that dumps a temporary file, than based on this file to execute another task that dumps another temporary file an so on…

With Gulp.js everything happens on the fly using Node’s stream, temporary files are not needed anymore which make it easy to learn, use and enjoy.

Installation

Use the -g options to install Gulp globally on your machine.

sudo npm install -g gulp

Practical examples

Now let’s use Gulp a little bit. Throughout those examples we will discover how to use plugins to create specific tasks such as minifying, concatenate or even linting your code.

Source available on Github

HTML Minification

Using gulp-minify-html

npm install --save-dev gulp-minify-html

gulpfile.js:

// including plugins
var gulp = require('gulp')
, minifyHtml = require("gulp-minify-html");

// task
gulp.task('minify-html', function () {
	gulp.src('./Html/*.html') // path to your files
	.pipe(minifyHtml())
	.pipe(gulp.dest('path/to/destination'));
});

Run:

gulp minify-html

CSS Minification

Using gulp-minify-css

npm install --save-dev gulp-minify-css

gulpfile.js:

// including plugins
var gulp = require('gulp')
, minifyCss = require("gulp-minify-css");

// task
gulp.task('minify-css', function () {
	gulp.src('./Css/one.css') // path to your file
	.pipe(minifyCss())
	.pipe(gulp.dest('path/to/destination'));
});

Run:

gulp minify-css

JS Minification

Using gulp-uglify

npm install --save-dev gulp-uglify

gulpfile.js:

// including plugins
var gulp = require('gulp')
, uglify = require("gulp-uglify");

// task
gulp.task('minify-js', function () {
	gulp.src('./JavaScript/*.js') // path to your files
	.pipe(uglify())
	.pipe(gulp.dest('path/to/destination'));
});

Run:

gulp minify-js

CoffeeScript Compilation

Using gulp-coffee

npm install --save-dev gulp-coffee

gulpfile.js:

// including plugins
var gulp = require('gulp')
, coffee = require("gulp-coffee");

// task
gulp.task('compile-coffee', function () {
	gulp.src('./CoffeeScript/one.coffee') // path to your file
	.pipe(coffee())
	.pipe(gulp.dest('path/to/destination'));
});

Run:

gulp compile-coffee

Less Compilation

Using gulp-less

npm install --save-dev gulp-less

gulpfile.js:

// including plugins
var gulp = require('gulp')
, less = require("gulp-less");

// task
gulp.task('compile-less', function () {
	gulp.src('./Less/one.less') // path to your file
	.pipe(less())
	.pipe(gulp.dest('path/to/destination'));
});

Run:

gulp compile-less

Sass Compilation

Using gulp-sass

npm install --save-dev gulp-sass

gulpfile.js:

// including plugins
var gulp = require('gulp')
, sass = require("gulp-sass");

// task
gulp.task('compile-sass', function () {
	gulp.src('./Sass/one.sass') // path to your file
	.pipe(sass())
	.pipe(gulp.dest('path/to/destination'));
});

Run:

gulp compile-sass

ECMAScript 6 Compilation

Using gulp-babel

npm install --save-dev gulp-babel

gulpfile.js:

// including plugins
var gulp = require('gulp')
, babel = require("gulp-babel");

// task
gulp.task('compile-es6', function () {
	gulp.src('./ES6/one.es6.js')
        .pipe(babel())
	.pipe(gulp.dest('path/to/destination'));
});

Run:

gulp compile-es6

JavaScript Linting

Using gulp-jshint

npm install --save-dev gulp-jshint

gulpfile.js:

// including plugins
var gulp = require('gulp')
, jshint = require("gulp-jshint");

// task
gulp.task('jsLint', function () {
	gulp.src('./JavaScript/*.js') // path to your files
	.pipe(jshint())
	.pipe(jshint.reporter()); // Dump results
});

In case of success:

[gulp] Starting 'jsLint'...
[gulp] Finished 'jsLint' after 6.47 ms

In case of failure:

[gulp] Starting 'jsLint'...
[gulp] Finished 'jsLint' after 5.86 ms
/var/www/gulp-examples/JavaScript/two.js: line 3, col 15, Expected '}' to match '{' from line 3 and instead saw '['.
/var/www/gulp-examples/JavaScript/two.js: line 3, col 16, Missing semicolon.
/var/www/gulp-examples/JavaScript/two.js: line 3, col 154, Expected an assignment or function call and instead saw an expression.

3 errors

Run:

gulp jsLint

CoffeeScript Linting

Using gulp-coffeelint

npm install --save-dev gulp-coffeelint

gulpfile.js:

// including plugins
var gulp = require('gulp')
, coffeelint = require("gulp-coffeelint");

// task
gulp.task('coffeeLint', function () {
	gulp.src('./CoffeeScript/*.coffee') // path to your files
	.pipe(coffeelint())
	.pipe(coffeelint.reporter());
});

In case of success:

[gulp] Starting 'coffeeLint'...
[gulp] Finished 'coffeeLint' after 7.37 ms

In case of failure:

[gulp] Starting 'coffeeLint'...
[gulp] Finished 'coffeeLint' after 6.25 ms

one.coffee
?  line 3  Line contains a trailing semicolon

? 1 error

Run:

gulp coffeeLint

Rename a file

Using gulp-rename

npm install --save-dev gulp-rename

gulpfile.js:

// including plugins
var gulp = require('gulp')
, rename = require('gulp-rename')
, coffee = require("gulp-coffee");

// task
gulp.task('rename', function () {
	gulp.src('./CoffeeScript/one.coffee') // path to your file
	.pipe(coffee())  // compile coffeeScript
	.pipe(rename('renamed.js')) // rename into "renamed.js" (original name "one.js")
	.pipe(gulp.dest('path/to/destination'));
});

Run:

gulp rename

Concatenate files

Using gulp-concat

npm install --save-dev gulp-concat

gulpfile.js:

// including plugins
var gulp = require('gulp')
, concat = require("gulp-concat");

// task
gulp.task('concat', function () {
	gulp.src('./JavaScript/*.js') // path to your files
	.pipe(concat('concat.js'))  // concat and name it "concat.js"
	.pipe(gulp.dest('path/to/destination'));
});

Run:

gulp concat

Add copyright

Using gulp-header

npm install --save-dev gulp-header

Copyright

/*
Gulp Examples by @julienrenaux:

* https://github.com/shprink
* https://twitter.com/julienrenaux
* https://www.facebook.com/julienrenauxblog

Full source at https://github.com/shprink/gulp-examples

MIT License, https://github.com/shprink/gulp-examples/blob/master/LICENSE
*/

gulpfile.js:

// including plugins
var gulp = require('gulp')
, fs = require('fs')
, concat = require("gulp-concat")
, header = require("gulp-header");

// functions

// Get copyright using NodeJs file system
var getCopyright = function () {
	return fs.readFileSync('Copyright');
};

// task
gulp.task('concat-copyright', function () {
	gulp.src('./JavaScript/*.js') // path to your files
	.pipe(concat('concat-copyright.js')) // concat and name it "concat-copyright.js"
	.pipe(header(getCopyright()))
	.pipe(gulp.dest('path/to/destination'));
});

Run:

gulp concat-copyright

Add copyright with version

Using gulp-header and Node’s file system

npm install --save-dev gulp-header

Copyright

/*
Gulp Examples by @julienrenaux:

* https://github.com/shprink
* https://twitter.com/julienrenaux
* https://www.facebook.com/julienrenauxblog

Version: <%= version %>
Full source at https://github.com/shprink/gulp-examples

MIT License, https://github.com/shprink/gulp-examples/blob/master/LICENSE
*/

Version

1.0.0

gulpfile.js:

// including plugins
var gulp = require('gulp')
, fs = require('fs')
, concat = require("gulp-concat")
, header = require("gulp-header");

// functions

// Get version using NodeJs file system
var getVersion = function () {
	return fs.readFileSync('Version');
};

// Get copyright using NodeJs file system
var getCopyright = function () {
	return fs.readFileSync('Copyright');
};

// task
gulp.task('concat-copyright-version', function () {
	gulp.src('./JavaScript/*.js')
	.pipe(concat('concat-copyright-version.js')) // concat and name it "concat-copyright-version.js"
	.pipe(header(getCopyrightVersion(), {version: getVersion()}))
	.pipe(gulp.dest('path/to/destination'));
});

Run:

gulp concat-copyright-version

Mix them up (Lint, Concat, Compile, Minify etc.)

The purpose of this task is to mix the previous tasks into just one.

Copyright

/*
Gulp Examples by @julienrenaux:

* https://github.com/shprink
* https://twitter.com/julienrenaux
* https://www.facebook.com/julienrenauxblog

Version: <%= version %>
Full source at https://github.com/shprink/gulp-examples

MIT License, https://github.com/shprink/gulp-examples/blob/master/LICENSE
*/

Version

1.0.0

gulpfile.js:

// including plugins
var gulp = require('gulp')
, fs = require('fs')
, coffeelint = require("gulp-coffeelint")
, coffee = require("gulp-coffee")
, uglify = require("gulp-uglify")
, concat = require("gulp-concat")
, header = require("gulp-header");

// functions

// Get version using NodeJs file system
var getVersion = function () {
	return fs.readFileSync('Version');
};

// Get copyright using NodeJs file system
var getCopyright = function () {
	return fs.readFileSync('Copyright');
};

// task
gulp.task('bundle-one', function () {
	gulp.src('./CoffeeScript/*.coffee') // path to your files
	.pipe(coffeelint()) // lint files
	.pipe(coffeelint.reporter('fail')) // make sure the task fails if not compliant
	.pipe(concat('bundleOne.js')) // concat files
	.pipe(coffee()) // compile coffee
	.pipe(uglify()) // minify files
	.pipe(header(getCopyrightVersion(), {version: getVersion()})) // Add the copyright
	.pipe(gulp.dest('path/to/destination'));
});

Run:

gulp bundle-one

Tasks automation

Using gulp.watch you can easily automate any tasks when files are modified. It is really convenient because you do not have to run single tasks by hand every time a file is modified, and therefore your code is always up to date.

// including plugins
var gulp = require('gulp');

// task
gulp.task('watch-coffeescript', function () {
    gulp.watch(['./CoffeeScript/*.coffee'], ['compile-coffee']);
});

Run:

Now run the task:

gulp watch-coffeescript

and see what happens when you modify one of the source file.

Ionic Framework features you may have missed

Ionic Framework is one of the best framework for developing hybrid mobile apps with HTML5. Based on AngularJS the set of available features is tremendous. This post presents, with examples, some of the best hidden features provided.

Scroll

Scroll documentation

Infinite Scroll

The ionInfiniteScroll directive allows you to call a function whenever the user gets to the bottom of the page or near the bottom of the page.

[codepen_embed height=”268″ theme_id=”5820″ slug_hash=”jukJh” default_tab=”result” user=”shprink”]See the Pen Infinite Scroll: 1.0.0-beta.14 by Julien Renaux (@shprink) on CodePen.[/codepen_embed]

List

List documentation

Collection repeat

The collection-repeat directive is a directive that allows you to render lists with thousands of items in them, and experience little to no performance penalty.

[codepen_embed height=”268″ theme_id=”5820″ slug_hash=”HoIDJ” default_tab=”result” user=”shprink”]See the Pen collection-repeat: 1.0.0-beta.14 by Julien Renaux (@shprink) on CodePen.[/codepen_embed]

Gesture

$ionicGesture documentation

Events

The gesture service has only two methods, on adds an event listener for an DOM element and off removes it. While AngularJS ngTouch provides only three touch events (ngClick, ngSwipeLeft and ngSwipeRight) $ionicGesture provides dozens (hold, tap, doubletap, drag, dragstart etc.).

[codepen_embed height=”268″ theme_id=”5820″ slug_hash=”txliu” default_tab=”result” user=”shprink”]See the Pen Ionic $ionicGesture example: 1.0.0-beta.14 by Julien Renaux (@shprink) on CodePen.[/codepen_embed]

Dom manipulation

DomUtil documentation

If you are accustomed to AngularJS I am sure that you experienced some difficulties when manipulating the DOM. JQlite helps but is itself very limited. Ionic provides some methods to help you deal with it.

ionic.DomUtil.ready

Call a function when the DOM is ready, or if it is already ready call the function immediately.

[codepen_embed height=”268″ theme_id=”5820″ slug_hash=”BxufK” default_tab=”result” user=”shprink”]See the Pen ionic.DomUtil.ready Example by Julien Renaux (@shprink) on CodePen.[/codepen_embed]

ionic.DomUtil.getParentWithClass

Returns the closest parent of element matching the className, or null.

[codepen_embed height=”268″ theme_id=”5820″ slug_hash=”lDrpb” default_tab=”result” user=”shprink”]See the Pen ionic.DomUtil.getParentWithClass Example: 1.0.0-beta.14 by Julien Renaux (@shprink) on CodePen.[/codepen_embed]

Utilities

ionic.throttle

Only call a function once in the given interval. In this example the function should be called half as many as we tried.

[codepen_embed height=”268″ theme_id=”5820″ slug_hash=”iefAE” default_tab=”result” user=”shprink”]See the Pen Ionic Throttle example: 1.0.0-beta.14 by Julien Renaux (@shprink) on CodePen.[/codepen_embed]

ionic.debounce

Only call a function once in the given interval, the timer is reset on every call. In this example the function should never be called.

[codepen_embed height=”268″ theme_id=”5820″ slug_hash=”yzrsD” default_tab=”result” user=”shprink”]See the Pen Ionic Debounce example: 1.0.0-beta.14 by Julien Renaux (@shprink) on CodePen.[/codepen_embed]

ionic.Utils.arrayMove

Really useful function that manipulates array items position.

[codepen_embed height=”268″ theme_id=”5820″ slug_hash=”HghBw” default_tab=”result” user=”shprink”]See the Pen Ionic arrayMove example: 1.0.0-beta.14 by Julien Renaux (@shprink) on CodePen.[/codepen_embed]

Tabs

Starting from ionic beta.14 we can select the position of the tabs through configuration.

Tabs top

.config(function($ionicConfigProvider){
    $ionicConfigProvider.tabs.position('top');
})

[codepen_embed height=”268″ theme_id=”5820″ slug_hash=”qlECF” default_tab=”result” user=”shprink”]See the Pen Tabs Top: 1.0.0-beta.14 by Julien Renaux (@shprink) on CodePen.[/codepen_embed]

Tabs bottom

.config(function($ionicConfigProvider){
    $ionicConfigProvider.tabs.position('bottom');
})

[codepen_embed height=”268″ theme_id=”5820″ slug_hash=”emXyjV” default_tab=”result” user=”shprink”]See the Pen Tabs bottom: 1.0.0-beta.14 by Julien Renaux (@shprink) on CodePen.[/codepen_embed]

Delegation

Delegation allow you to have several instances of the same component within the same view. You have this capability on ion-side-menus, ion-tabs,ion-scroll ion-content, ion-list and ion-slide-box using the delegate-handle directive attribute.

[codepen_embed height=”268″ theme_id=”5820″ slug_hash=”CsBhf” default_tab=”result” user=”shprink”]See the Pen Ionic Side Menu delegation: 1.0.0-beta.14 by Julien Renaux (@shprink) on CodePen.[/codepen_embed]