iOS / Android push notifications 100% free and self hosted for WordPress using Cordova and Ionic

Push notification is always a pain when it comes to find the perfect free service, there are several possibilities like pushwoosh, pushapps, pushover etc.

If you are hosting your WordPress website there is no need to subscribe any of those services. With your server you have already what it takes to send push notifications to your subscriber.

No third party service involved, just your WordPress server and your application.

It all start with installing Push Notifications for WordPress (Lite) plugin to your WordPress.

Send push notifications to iOS, Android, and Fire OS devices when you publish a new post. Straight from your WordPress site, in real-time.

Installation

  1. Search and install “Push Notifications for WordPress (Lite)” from the Plugins WordPress page
  2. Activate “Push Notifications for WordPress (Lite)” through the ‘Plugins’ menu in WordPress
  3. Configure the plugin by going to the Push Notifications menu that appears in your admin menu

Android

If you have not already done so, you’ll need to set up a Google API project, to generate your senderID. Follow these steps to do so.

Get the SenderID

Signing into https://developers.google.com/mobile/add and follow the steps to get Cloud messaging senderID and apiKey.

Tip: The senderID is a 12 digit number

Configure the WordPress plugin

Go to Push Notifications > Settings and check the following checkboxes:

  • Basic Options > Send push notifications when a new post is published
  • Basic Options > Android devices
  • Send Push Notifications for > Posts
  • Misc > In the Android notification payload add the message field

Then go to “Android Push Notifications (via GMC)” section and enter you Google Api key.

Do not forget to save.


iOS

Configure the WordPress plugin

Go to Push Notifications > Settings and check the following checkboxes:

  • Basic Options > Send push notifications when a new post is published
  • Basic Options > iOS devices
  • Send Push Notifications for > Posts

Do not forget to save.

Certificates and Provisioning profiles

This part is really painful (Generally when you have to use Apple’s service it is…). It is all well explained there: http://strangemilk.com/ionic-push-notifications-with-ios/

Create .pem

Get .perm files

Once you have got your .pem files upload them in the iOS Push Notifications section

Setup Ionic / Cordova

I recommend using NgCordova and the NgCordova pushNotifications plugin

Installation

cordova plugin add https://github.com/phonegap-build/PushPlugin.git

# Or if you are using Ionic CLI
ionic plugin add https://github.com/phonegap-build/PushPlugin.git

Register to “Push Notifications for WordPress (Lite)”

“Push Notifications for WordPress (Lite)” exposes a Web service API that you can access over HTTP.

It only takes the OS (iOS | Android) and the device token.

function register(os, token) {
        var baseUrl;
        baseUrl = 'http://yourDomainName.com/pnfw';
        if (!baseUrl) {
            return $q.reject();
        }
        return $http({
            method: 'POST',
            url: baseUrl + '/register',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded'
            },
            transformRequest: function(obj) {
                var p, str;
                str = [];
                for (p in obj) {
                    str.push(encodeURIComponent(p) + '=' + encodeURIComponent(obj[p]));
                }
                return str.join('&');
            },
            data: {
                os: os,
                token: token
            }
        });
    };

iOS

$cordovaPush.register(iosConfig).then(function(deviceToken) {
    register('iOS', deviceToken).success(function() {
        return $log.info('Push notif Token stored');
    });
    $log.debug('iOS push notification registration success', deviceToken);
}, function(err) {
    $log.error('iOS push notification registration error', err);
});

$rootScope.$on('$cordovaPush:notificationReceived', function(event, notification) {
    $log.debug('Push notif message', notification);
    if (notification.alert) {
        if (notification.foreground) { // If your user is using the app
            // Do something like opening the Post within the app
            // You have access to
            // notification.id which is the new Post ID
            // notification.alert which is the new Post Title
        } else { // If your user has clicked on the notification
            // Do something like opening the Post within the app
            // You have access to
            // notification.id which is the new Post ID
            // notification.alert which is the new Post Title
        }
    }
    if (notification.badge) {
        return $cordovaPush.setBadgeNumber(notification.badge).then(function(result) {
            $log.debug('Push notif badge ok', result);
        }, function(err) {
            $log.debug('Push notif badge error', err);
        });
    }
});

Android

$cordovaPush.register(androidConfig).then(function(result) {
    $log.debug('android push notification registration success', result);
}, function(err) {
    $log.error('android push notification registration error', err);
});
return $rootScope.$on('$cordovaPush:notificationReceived', function(event, notification) {
    switch (notification.event) {
        case 'registered':
            if (!notification.regid.length) {
                return;
            }
            $log.debug('registration ID', notification.regid);
            register('Android', notification.regid).success(function() {
                return $log.info('Push notif Token stored');
            });
            break;
        case 'message':
            $log.debug('Push notif message', notification);
            if (notification.foreground) { // If your user is using the app
                // Do something like opening the Post within the app
                // You have access to
                // notification.payload.id which is the new Post ID
                // notification.payload.message which is the new Post Title
            } else { // If your user has clicked on the notification
                // Do something like opening the Post within the app
                // You have access to
                // notification.payload.id which is the new Post ID
                // notification.payload.message which is the new Post Title
            }
            break;
        case 'error':
            $log.debug('Push notif error', notification);
            break;
    }
});

All in one

angular.module('yourModuleName').run(function($log, $cordovaPush, $rootScope, $http, $ionicPlatform) {
    var androidConfig, iosConfig, register;

    androidConfig = {
        "senderID": ""
    };
    iosConfig = {
        "badge": true,
        "sound": true,
        "alert": true
    };

    register = function(os, token) {
        var baseUrl;
        baseUrl = 'http://yourDomainName.com/pnfw';
        if (!baseUrl) {
            return $q.reject();
        }
        return $http({
            method: 'POST',
            url: baseUrl + '/register',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded'
            },
            transformRequest: function(obj) {
                var p, str;
                str = [];
                for (p in obj) {
                    str.push(encodeURIComponent(p) + '=' + encodeURIComponent(obj[p]));
                }
                return str.join('&');
            },
            data: {
                os: os,
                token: token
            }
        });
    };
    return $ionicPlatform.ready(function() {
        if (ionic.Platform.isAndroid()) {
            $cordovaPush.register(androidConfig).then(function(result) {
                $log.debug('android push notification registration success', result);
            }, function(err) {
                $log.error('android push notification registration error', err);
            });
            return $rootScope.$on('$cordovaPush:notificationReceived', function(event, notification) {
                switch (notification.event) {
                    case 'registered':
                        if (!notification.regid.length) {
                            return;
                        }
                        $log.debug('registration ID', notification.regid);
                        register('Android', notification.regid).success(function() {
                            return $log.info('Push notif Token stored');
                        });
                        break;
                    case 'message':
                        $log.debug('Push notif message', notification);
                        if (notification.foreground) { // If your user is using the app
                            // Do something like opening the Post within the app
                            // You have access to
                            // notification.payload.id which is the new Post ID
                            // notification.payload.message which is the new Post Title
                        } else { // If your user has clicked on the notification
                            // Do something like opening the Post within the app
                            // You have access to
                            // notification.payload.id which is the new Post ID
                            // notification.payload.message which is the new Post Title
                        }
                        break;
                    case 'error':
                        $log.debug('Push notif error', notification);
                        break;
                }
            });
        } else if (ionic.Platform.isIOS()) {
            $cordovaPush.register(iosConfig).then(function(deviceToken) {
                register('iOS', deviceToken).success(function() {
                    return $log.info('Push notif Token stored');
                });
                $log.debug('iOS push notification registration success', deviceToken);
            }, function(err) {
                $log.error('iOS push notification registration error', err);
            });
            return $rootScope.$on('$cordovaPush:notificationReceived', function(event, notification) {
                $log.debug('Push notif message', notification);
                if (notification.alert) {
                    if (notification.foreground) { // If your user is using the app
                        // Do something like opening the Post within the app
                        // You have access to
                        // notification.id which is the new Post ID
                        // notification.alert which is the new Post Title
                    } else { // If your user has clicked on the notification
                        // Do something like opening the Post within the app
                        // You have access to
                        // notification.id which is the new Post ID
                        // notification.alert which is the new Post Title
                    }
                }
                if (notification.badge) {
                    return $cordovaPush.setBadgeNumber(notification.badge).then(function(result) {
                        $log.debug('Push notif badge ok', result);
                    }, function(err) {
                        $log.debug('Push notif badge error', err);
                    });
                }
            });
        }
    }, false);
});

WordPress Hybrid Client

If you want your WordPress website available on iOS and Android there is a simple free and Open Sourced solution: WordPress Hybrid Client

With WPHC (WordPress Hybrid Client), your WordPress website application (iOS and Android) is just a build away.

Here is the features already available and a lot more is coming:

  1. Push Notifications
  2. Social buttons
  3. About Page
  4. Params Page
  5. Language switch [French|English|Chinese]
  6. Accessibility (Post font size)
  7. App rate
  8. Docker support for easier installation
  9. Syntax highlighter for tech blogs

MISC: Test Push Notifications on Android

If you want to test that GMC is correctly setup and that your device receive notifications you can follow this tutorial: Sending push notifications to Android via Gulp

Sending push notifications to Android via Gulp

If you ever wondered how to test that your push notifications work on Android without setting up any server here is how to do.

Install

npm install gulp node-gcm

Get Api key, Sender ID and Device ID

In order to be able to send push notifications we need only need the Google Cloud Api key, and the device ID(s).

To get the Api key and the senderID you can register there: https://developers.google.com/mobile/add

As for the device ID it can be found once your device is registered.

If you are using this Cordova plugin https://github.com/phonegap-build/PushPlugin you can get it like this (note that the senderID is used here):

document.addEventListener("deviceready", function() {
    var pushNotification = window.plugins.pushNotification;
    pushNotification.register(
        successHandler,
        errorHandler, {
            "senderID": "replace_with_sender_id (12 digits number)",
            "ecb": "onNotification"
        });

    function onNotification(e) {
        switch (e.event) {
            case 'registered':
                if (e.regid.length > 0) {
                    // Your GCM push server needs to know the regID before it can push to this device
                    // here is where you might want to send it the regID for later use.
                    console.log('Device id', e.regid);
                }
                break;
        }
    }

    function successHandler() {}

    function errorHandler() {}
});

Script

Now that you have both Device ID and Api key let’s create a script that send push notifications.

gulp.task('push:android', function() {
    if (!gutil.env.apiKey || gutil.env.apiKey === true) {
        throw new Error('You must specify the android Api key, refer to the documentation');
    }
    if (!gutil.env.deviceId || gutil.env.deviceId === true) {
        throw new Error('You must specify the android ID, refer to the documentation');
    }

    console.log('apiKey', gutil.env.apiKey);
    console.log('deviceId', gutil.env.deviceId);

    var gcm = require('node-gcm')

    var message = new gcm.Message({
        collapseKey: 'demo',
        delayWhileIdle: true,
        timeToLive: 3,
        data: {
            key1: 'message1',
            key2: 'message2'
        }
    });

    var sender = new gcm.Sender(gutil.env.apiKey);

    sender.send(message, (gutil.env.deviceId instanceof Array) ? gutil.env.deviceId : [gutil.env.deviceId], 5, function(err, result) {
        if (err) {
            console.error('Failed, status code', err);
        } else {
            console.log('Success', result);
        }
    });
})

Run

You can run the script like like this on one or several devices:

# One device
gulp push:android --apiKey YOUR_API_KEY --deviceId YOUR_DEVICE_ID

# Two devices
gulp push:android --apiKey YOUR_API_KEY --deviceId YOUR_DEVICE_ID --deviceId YOUR_DEVICE_ID

If everything is fine you should have your push notifications working.

Commun error

If your api key and senderId are not ok you will get this error message:

Success { multicast_id: 7412383159195664000,
  success: 0,
  failure: 1,
  canonical_ids: 0,
  results: [ { error: 'MismatchSenderId' } ] }

If so regenerate a api key using this link https://github.com/phonegap-build/PushPlugin.

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

AngularJS memory stats

If you are familiar with AngularJS development, you know that memory consumption is one of the highest challenge you must face using it.

Introducing angular-memory-stats

angular-memory-stats

angular-memory-stats is a NPM package that allow you to follow the memory consumption of your AngularJS application.

Install via NPM

npm i angular-memory-stats --save

Include the AngularJS module to your application

angular.module('yourModule', [
    'angular-memory-stats'
])

Insert the directive in the dom

<angular-memory-stats></angular-memory-stats>

Enable/Disable angular-memory-stats

angular-memory-stats is enabled by default, if you wish to disable it use the angularMemoryStatsProvider Provider

angular.module('yourModule').config(function(angularMemoryStatsProvider){
    angularMemoryStatsProvider.enable(false)
});

Then all you need to do is to launch Chrome (only available on Chrome for now) with the --enable-precise-memory-info and --enable-memory-info flags

# Linux
google-chrome --enable-precise-memory-info --enable-memory-info

#MacOS
/Applications/Google Chrome.app/Contents/MacOS/Google Chrome --enable-precise-memory-info --enable-memory-info

Open your application and you will have the following indicator on the bottom right corner of your browser:

angular-memory-stats

Source available on Github

AngularJs 1.x Open Source projects to follow in 2015

Ionic Framework

ionic

Ionic needs no introduction, it is a HTML5 Mobile Framework for building, cross-platform hybrid native apps with HTML, JavaScript, and CSS.

In 2014 Ionic became one of the top 50 most popular open source projects in the world, with over 12,000 stars on GitHub and over 50,000 new apps were created using Ionic Framework.

2015 will be an important year for Ionic as they will slowly move from a simple HTML5 hybrid framework to a whole galaxy of tools to create hybrid apps. The npm ionic package is already available with features such as building cordova apps or creating splashscreens and icons for IOS and Android.

Developers to follow:


Angular Material Design

Material Design is a Google specification for a unified system of visual, motion, and interaction design that adapts across different devices.

angular/material is a lean, lightweight set of AngularJS-native UI elements that implement the material design specification for use in Angular single-page applications (SPAs). This is the official AngularJs Material Design library.

No doubt that 2015 will be the year of Material Design, it is already everywhere from Android to Polymer. I have a lot of expectations for this library that I already use in my current company. Unfortunately a lot of features are missing (menu, dropdown menu, select, multi-select etc.) and the development pace is not high enough to reach the planning explained at the end of this video:

Go Google go!

Developers to follow:


lumX Material Design

lumx

Material Design is a Google specification for a unified system of visual, motion, and interaction design that adapts across different devices.

LumX will help you to design beautiful applications, faster and easier, respecting Material Design specification in a pixel perfect way.

In a lot of aspects this set of directives is more advanced than the official Angular Material Design repository. I really hope this project will have the attention it deserves. A downside of it though is that it depends on jQuery..

Developers to follow:


Foundation for Apps

foundation_apps

Foundation for Apps is an Angular-powered framework for building powerful responsive web apps. With this project the Zurb foundation is clearly trying to compete with Ionic Framework. There is still a lot of work to do but it sounds really promissing!

Developers to follow:


Angular Hint – Runtime hinting for AngularJS

Whether you start a new project or want to have feedbacks on an existing Angular app, this project is for you. It basically tells you if you follow AngularJs’s standards or not.

If you do not want to add this project to your development dependencies you can use a Chrome plugin that includes it.

If you also wants to follow AngularJs’s best practice I suggest you to read John Papa’s angularjs-styleguide. There are a lot of great advices in there and I personally always go through it before starting a new project. Some are explained in this video:

Developers to follow:


Angular-google-maps

angular-google-map

Angular-google-maps is a set of directives for the Google Maps JavaScript API. It is part of the great Angular UI organization. This repository changed a lot in Q4 2014 and released 2.x versions that is really popular lately.

Developers to follow:


Ng-Annotate

If you are familiar with AngularJs and it’s concept of Dependency Injection (DI), you know that it can be really annoying to use when minifying your code:

Minification KO

angular.module('ngAppStrictDemo', [])
// BadController will fail to instantiate, due to relying on automatic function annotation,
// rather than an explicit annotation
.controller('BadController', function($scope) {
  $scope.a = 1;
  $scope.b = 2;
})

Minification OK

angular.module('ngAppStrictDemo', [])
// Unlike BadController, GoodController will not fail to be instantiated,
// due to using explicit annotations using the array style.
.controller('GoodController', ['$scope', function($scope) {
  $scope.a = 1;
  $scope.b = 2;
}])

angular.module('ngAppStrictDemo', [])
// Unlike BadController, GoodController2 will not fail to be instantiated,
// due to using the $inject property.
.controller('GoodController2', GoodController2);
function GoodController2($scope) {
  $scope.name = "World";
}
GoodController2.$inject = ['$scope'];

Before AngularJs 1.3 it was difficult to know if you code was production ready (minifiable) or not. To tackle this very problematic AngularJs 1.3 introduced the ngStrictDi directive which tells you if your code is production ready or not.

Ng-Annotate basically makes the “Minification KO” example a production ready code! You do not have to worry about the $inject property or the array style anymore. This project literally changed my life, with it I was able to remove all the duplicate service injection ['$scope', function($scope) and the $inject property GoodController2.$inject that I used before.

Developers to follow: