Angular.JS: Acing Security with $sce

Hi, reader! Hope you’re having a great week so far! On our last blog post, we saw Backbone.JS, a JavaScript framework, which provides structure to our client side code. Seeing Backbone was very refreshing especially after coming from the Underscore blogpost which focused more on utility functions and dealt less with structure.

Now for this blog post, we’ll be leaning on to AngularJS, it’s $sce service in particular. Often in coding projects, we get to encounter strings which contain HTML elements that should be rendered as html elements themselves. For example: markdowns, user generated html strings, etc.

And often, the frameworks we use don’t dispaly them as it should be (for security), rather, as simple strings. That is why we can use their sanitizing methods (such as html_safe for Ruby on Rails) by which we declare that we trust the string and we want it displayed as HTML (whatever the contents are).

Here’s a Rails example:

We have two strings with two versions each, one that is raw and another one that is declared safe with html_safe.

Screen Shot 2016-01-21 at 11.31.49 PM.png

When we load the page containing these:

We see that our JS script was ran once (alert flashed),

Screen Shot 2016-01-21 at 11.32.02 PM.png

And also a string containing our string was printed. Similar to the strong tag, in the html_safe version, <strong> was evaluated and led to bold letters.

Screen Shot 2016-01-21 at 11.31.41 PM.png

Now, that we have already got the hang of it, let’s now focus on Angular JS and its $sce service.

ng-bind-html

Similar to Rails’ html_safe that we saw a while ago, AngularJS has a similar version, the ng-bind-html directive. And let’s see an example.

Here we have a simple AngularJS application with a textarea with myHtml assigned as the ng-model. And then two divs attached to the myHtml ng-model as well. These divs are listening to any value changes with the model and reflects them accordingly.

What sets these two divs apart is that one is bounded via the simple ng-bind while the other one is bound by ng-bind-html.

Screen Shot 2016-01-22 at 12.05.00 AM.png

Let us see the difference:

Screen Shot 2016-01-22 at 12.04.52 AM.png

For the div that binded to myHtml using  the simple ng-bind, the value was just printed as a string while for the second div which was bound using ng-bind-html, the html was evaluated and the string in bold letters was shown.

Buuuut, why won’t we want something like this all the time? It is because we can’t always trust user input or interpolated for that matter. What if some bad guy injects malicious snippets of code into a seemingly clean html text like the following:

Screen Shot 2016-01-22 at 12.35.02 AM.png

As we see above, the line seems clean and safe – just a string with a series of characters and one (cute) emoticon. But then when we (accidentally or intentionally) hover on it, KABOOM:

Screen Shot 2016-01-22 at 12.34.03 AM.png

JK. It’s not really just a string, it actually has a onmouseover event attached to it. Our actual string was:

Screen Shot 2016-01-22 at 12.33.56 AM.png

Lucky for us that the hidden JavaScript is just an alert message but what if it was something more serious (i.e. XSS).

This has indeed some security concerns! So to solve, angular actually has the $sce service, short for Strict Contextual Escaping, which ensures and

requires that bindings in certain contexts to result in a value that is marked as safe to use for that context

If you’re using Angular version 1.2 or higher and you tried copying the above snippets of code, you may notice that it results to an error:

Screen Shot 2016-01-22 at 12.55.59 AM.png

And this is because the $sce is already loaded and enabled by default in AngularJS versions 1.2 and higher. And as we mentioned earlier, $sce ensures and requires that binding result to a value that is marked as safe. (And we haven’t explicitly marked our input to be safe or trusted).

To demo the above data bindings without explicitly marking our html values as safe, I just disabled the $sce in my AngularJS version 1.4.1 to demonstrate how the ng-bind-html have behaved before $sce was loaded by default.

Note: Disabling the $sce module is highly discouraged as disabling it is like stripping away one security layer from your app.

Btw, if you’re curious and want to know how to disable $sce, you just need to set the enabled attribute of the $sceProvider to false in the config section of your module:

Screen Shot 2016-01-22 at 1.17.09 AM.png

$sce, $sceProvider, $trustAs*

So now, let’s work on the default behaviour of AngularJS (1.2 onwards) – with $sce enabled. So either we just set enabled to true or just erase the config part completely as it defaults to true.

So now going back to the error above, let’s try to fix it. With $sce enabled we are saying that the value should be sanitized and marked as safe first. So what we can do is use Angular’s trustAs* methods.

Here we are saying that we explicitly trust the contents and it is safe to display it as it is with whatever the original value is.

Screen Shot 2016-01-22 at 2.01.51 AM.png

Screen Shot 2016-01-22 at 2.02.46 AM.png

The behaviour is similar to how our app a while ago behaved when $sce is disabled. For this one, our explicit consent was asked for first before the HTML was rendered.

So since we declared that we trust the HTML to be safe, it is rendered as it is with the JavaScript script intact and enabled. So upon hovering, we got the message:

Screen Shot 2016-01-22 at 8.50.39 PM.png

What we can take from here is that explicitly trusted html/strings/values already bypasses any checks (but note that the CORS rules from your browser still apply and might impose stricter rules).

There are still many variations to the trustAs* method. There is trustAsJs, trustAsCss among others but they are used more or less the same way and what just differs is the type of value that they wrap.

ngSanitize

In case you were wondering how to clean and sanitize data, AngularJS provides the ngSanitize module which, when loaded, automatically cleans / sanitizes your HTML string, already getting rid of hiding JS scripts, etc.

To use ngSanitize:

  1. Include angular-sanitize.js to your page, you may get it via CDN or save it locally. You may see the instructions here.
  2. Load ngSanitize into your Angular app:
    Screen Shot 2016-01-22 at 1.13.04 AM.png
  3. And that’s it! ngSanitize is now loaded and ready to clean your bound values.

Say we have the following:

Screen Shot 2016-01-22 at 1.08.44 AM.png

Screen Shot 2016-01-22 at 9.13.28 PM.png

Hovering on “Anybody here?” doesn’t yield any alerts. Due to ngSanitize’s automatic cleaning, even if we didn’t explicitly parse clean our string, the sneaky script was automatically weeded out. We also did not need to use trustAsHtml on our controllers as once our string have passed ngSanitize’s secure parsing methods, our string is already marked as trusted and safe for display.

So there, we saw a few security features that AngularJS provides! Hope you’ll find them useful anywhere you see fit to further improve your app’s security. 🙂

Thank you so much for reading!

Wishing you a great and lovely weekend ahead,
Adelen

References:

Advertisements

Structuring Up Code with Backbone.JS

Hello reader! Hope you’re having a great first month of the year so far!

Things have become pretty  busy lately huhu (but no worries, as there are milestones that hopefully they’ll lead to) that is why this blog post came in 2 days late. Anyhoo, for this blog post, we’ll be looking into Backbone.JS, a JavaScript framework that could give structure to your client side code through the MV* Framework. Backbone.JS relies heavily on the utility functions provided by Underscore.JS (which we saw on our last blog post)  so make sure to have Underscore too when loading Backbone.

Screen Shot 2016-01-15 at 7.48.57 PM.png

MVC and MV* Frameworks

Before we start tinkering with Backbone.JS, let us first talk about MVC frameworks.

Even for at least once, you may have already heard of MVC frameworks, let it be on the client side or the server side. MVC stands for Model, View, and Controller.

Models are like data types that you can mold to represent your entity – maybe a user, a product, a student, etc, that are connected to your data store. Views, on the other hand, define the interface your users would be interacting with. And lastly, controllers, are the middlemen between your model and views – they are the ones responsible for fetching data for display as well as handling user input or actions passed by the views.

Backbone almost follows the same pattern, providing Models and Views, but it does not have a controller. Many consider the view as the controller as well since most of the logic of behaviour lies in it. Some of the entities in Backbone that we will encounter the most include Models, Views, Collections and Routers. Many say that Backbone could still be considered an MVC Framework, but C would stand for Collection which is also heavily used in any Backbone collection. And we’ll see them in a bit.

Prerequisites

Before we look into the components of a Backbone.JS application, let us first identify the things we need to have on hand to create a backbone application.

As mentioned above, we need to have Underscore.JS loaded in our page, so let’s first go and include it.


&lt;script src="underscore.min.js"&gt;&lt;/script&gt;

There are many ways to load it in your page and and you may refer to this post for ways how. Here I downloaded the Underscore JavaScript to be able to refer to it locally.

Next after we have included underscore, let us now include Backbone itself.

 

&lt;script src="backbone.min.js"&gt;&lt;/script&gt;

For this, I also downloaded Backbone.JS and included it in my page.

Underscore.JS is a prerequisite of Backbone.JS so the above order matters when loading them.

Backbone Models

So for our first bite of Backbone, let’s look at models.

As mentioned above, models are like data types that you can model to represent entities of your application, like a user, a photo, a product, etc. Creating a model is easy, you just have to extend the Backbone.Model.

myModel = Backbone.Model.extend();
instanceOfMyModel = new myModel();

And then we can try in the console, creating an instance of our model:

Screen Shot 2016-01-16 at 9.21.58 PM.png

From instances of models, we can get attributes through the .get() function. Now, when we tried getting the name attribute of instanceOfMyModel, we got undefined (oops it’s because we haven’t specified it). Let’s try specifying a name attribute upon instantiation:

Screen Shot 2016-01-16 at 9.25.13 PM.png

And tadaaa, we got ‘Victoria’! 🙂

Along with our model’s definition code (where we extended Backbone model), we could also add parameters to further customize our models behaviour. Here are some of the parameters that Backbone allows us to add:

defaults

Class = Backbone.Model.extend({
     defaults: {
           enlisted: false,
     }
});

Math17 = new Class({name: 'Math 17'});
Eng1 = new Class({name: 'Eng 1', enlisted: true})

Screen Shot 2016-01-16 at 9.36.37 PM.png

We see that when we instantiated Math 17 without specifying the enlisted attribute, it was set by default to false. On the other hand, instantiating Eng 1 with a true value for the enlisted attribute, overrode the default value of false.

initialize

The function that you’ll provide to the initialize parameter is ensured to be called everytime an instance of this model is initiated.

Class = Backbone.Model.extend({
     defaults: {
           enlisted: false,
     },
     initialize: function() {
           console.log('Created class: ' + this.get('name'));
     }
});

Math17 = new Class({name: 'Math 17'});

Screen Shot 2016-01-16 at 9.41.50 PM.png

Here, we instructed that for every instantiation, we output some text and it indeed was when we created Math 17.

There are still a whole lot more additional parameters that you can specify and in addition to these, you can also empower your model to have other customized functions:

Class = Backbone.Model.extend({
     defaults: {
           enlisted: false,
     },
     initialize: function() {
           console.log('Created class: ' + this.get('name'));
     },
     drop: function() {
            console.log('Oops, you need to consult your adviser first');
     }
});

Math17 = new Class({name: 'Math 17'});

Screen Shot 2016-01-16 at 9.45.42 PM.png

Collection

The C on MVC won’t be dubbed as Collections for Backbone for no reason. We saw earlier that models are like the blueprint of our data structure. On the other hand, Backbone provides collections to represent groups of our model. For example, a user could belong to an organization, a list item could belong to a todo list, and a class could belong to a curriculum.

Similar to creating a model, collections can also be created by just extending Backbone.Collection:

Curriculum = Backbone.Collection.extend();
CompSciCurri = new Curriculum();
CompSciCurri.length

Screen Shot 2016-01-16 at 9.56.18 PM.png

We can see that the length of our CompSciCurri is still zero as we haven’t created any elements of it yet. Before we add elements, let us first see what other parameters we can provide when extending Backbone.Collection:

model

With model, we can specify the model of our data elements.

Curriculum = Backbone.Collection.extend({model: Class});
CompSciCurri = new Curriculum();

Screen Shot 2016-01-16 at 10.03.39 PM.png

We specified our Curriculum model to be housed by objects with objects with the Class model. We also instantiate a curriculum model and added our first element, Math 17.

create

So far, what we have is all ephemeral data – data is lost upon refresh. Backbone provides capability to save persistent data. We just need to specify where we want data to be stored.

Calling create on a collection instance creates another element of the collection based on the specified model. Trying it out on our current example:

Screen Shot 2016-01-16 at 10.08.51 PM.png

We get an error. Why is this so? Create tries to already store the data we are trying to create but we haven’t specified where yet.

For purposes of demo, we will be storing our data in our browser’s local storage, so be sure to also load the localStorage library in your page for these examples to work. Should you wish to use an API, you can also just provide the url parameter to the definition of your collection.

 

&lt;script src="backbone.min.js"&gt;&lt;/script&gt;

Now, we adjust our Collection definition to include the use of localStorage.

Curriculum = Backbone.Collection.extend({
     model: Class,
     localStorage: new Backbone.LocalStorage('curri-class')
});

CompSciCurri = new Curriculum();
CompSciCurri.create({name: 'Comm 3', enlisted: true});

Further inspecting what our CompSciCurri looks so far:

Screen Shot 2016-01-16 at 10.22.02 PM.png

Same with models, you may also add additional functions to your collections.

Backbone Views

Now that we already had a glimpse of Models and Collections, let’s now look into Views, where majority of behaviour and interaction logic lies.

Views define what users get to interact with. In Backbone Views, we get to define templates from which our views will be modeled after, define the behaviour when elements receive certain user actions like clicks or key presses, and also even listen to changes and other actions triggered on our models and collections.

For templates, Backbone uses Underscore.JS templating functions which you are more or less already familiar now from our last Underscore blog post. 🙂

Just with models and collections, to create the view we just need to extend the Backbone.View class.

Schedule = Backbone.View.extend();
mySchedule = new Schedule();
mySchedule.tagName
mySchedule.className
mySchedule.el
mySchedule.$el

Screen Shot 2016-01-16 at 11.15.09 PM.png

Wew, it seems that there’s much going on here. But don’t fret, let’s take them one by one. First, we defined Schedule to be a Backbone View.

Schedule = Backbone.View.extend();

And then we created an instance of this Schedule object:

mySchedule = new Schedule();

Now, we have mySchedule. We then checked its innate properties which included tagName, className, el, and $el. Let’s take them one by one:

tagname

Tagname is the container for the element that we are building inside the view. This is required but could be unspecified. If unspecified, it defaults to <div>. That is why from in the preceding screenshot, we got “div”.

Let’s try specifying a tagName:

Schedule = Backbone.View.extend({tagName: 'li'});
mySchedule = new Schedule();
mySchedule.tagName

Screen Shot 2016-01-16 at 11.32.34 PM.png

className

As with tagName, we can also specify any class (and ID), we want our element to have.

Schedule = Backbone.View.extend({tagName: 'li', className: 'highlight'});
mySchedule = new Schedule();
mySchedule.el

Screen Shot 2016-01-16 at 11.38.44 PM.png

There, our produced element is a <li> element with the class highlight. Multiple class names could also be specified by separating them with spaces.

Screen Shot 2016-01-16 at 11.41.05 PM.png

Now, before we proceed on looking at other attributes we can pass along in the View definition. Let’s first talk about $el. $el references the contents of our view. It is the whole element defined by the tagname with the compiled contents inside. In the preceding screenshot, when we got the el attribute from mySchedule, we got the li element that was constructed and getting $el attribute, on the other hand, gives us a jQuery-like array where we can further execute jQuery functions.

Knowing that el is also an attribute, let us try specifying it.

Say we have an existing element in our html page,


&lt;table id='sched-tbl'&gt;

&lt;/table&gt;

We can create a view having our $(‘#sched-tbl’) as its el.

Schedule = Backbone.View.extend({el: $("#sched-tbl"));

Screen Shot 2016-01-17 at 12.10.36 AM.png

And then from there, we can continue to manipulate our el:

Screen Shot 2016-01-17 at 12.10.57 AM.png

Output:Screen Shot 2016-01-17 at 12.11.04 AM.png

Note that what we are using above is the $el attribute of our Schedule object because using el only would just give us the element itself (on which we can’t apply jQuery functions):

Screen Shot 2016-01-17 at 12.22.13 AM.png

Now, let’s get to the additional values that we can define once we instantiate views.

template

With the template parameter, we can specify a specific template we want our view modelled from. It can contain dynamic variables, as well, enclosed in ERB style of evaluation (<%= %>, but could be further customized as we saw with Underscore).

We can specify a simple string

template1 = "I love Math!";
template2 = "I love <%= name %>"

Or get the contents of a text/template we have declared:

template3 = $('#main-div').html()

And then compile it with Underscore’s template,

compiledTemplate1 = _.template(template1)
compiledTemplate2 = _.template(template2)

And then pass our dynamic values:

compiledTemplate(Math17.toJSON())

Screen Shot 2016-01-18 at 1.04.11 AM.png

Screen Shot 2016-01-18 at 1.05.12 AM.png

render

On the other hand, render is the one responsible for rendering and updating the content of our views. Usually this is bind to “on change” events of the model or collection it is responsible for so that the displayed information gets updated.

Schedule = Backbone.View.extend({
   el: $("#sched-tbl"),
   template: _.template('TEMPLATE FOR CONTENTS'),
   render: function() {
       console.log('I am rendering!');
       this.$el.html(this.template());
       return this;
   }
});

mySched = new Schedule();
mySched.render().$el

Screen Shot 2016-01-18 at 1.15.59 AM.png

events

We have mentioned before that views could listen to events made on it. Say it has a Add Button that when clicked, should call a function, or it has an input that when entered, saves the object to the database. And we could do this through the events parameter.

Events accepts a hash with the target events as keys and the functions to be called as values.


events: {

   'click':'alertName',

   'click #add-btn' : 'createProduct',

   'dblClick .label' : 'showInput'

}

In our example above, we declared three events that our view is looking out for.

  • For the first one, we are just declaring that when the whole view is clicked, alertName will be called.
  • The second one specifies that when the #add-btn is clicked, createProduct will be called
  • And the last one just states that when an element with class label is double clicked, showInput is called.

listenTo

In addition to listening to events on elements. Views could also listen to events on our models and collections and by good practice, this is done by using listenTo.


this.listenTo(this.model, 'change', this.render)

Backbone Routers

With the above mentioned features, we can already do a single page application. No need for site refreshes, data is fetched and updated already, realtime. With this, since everything happens in the page,  we may have the same URL all throughout, whatever the state of our page is. Having a constant url though won’t let people bookmark or jump to certain states immediately.

And that’s where backbone routers jump in. Backbone routers provide a way for our url to change and do specific changes when they do.

Here is a sample Backbone Router:

myRouter = Backbone.Router.extend({
    routes: {
       "*param": "doSomething"
    },
doSomething: function(param){
    alert('CALLED'); 
});
 
router1 = new myRouter();
Backbone.history.start();

Here we used a basic *splat, where in *param acts as a sponge to whatever you append to the main url. This parameter could then be passed to doSomething, the method that we specified to be called upon reaching a /#<anything here> URL.

Backbone.history.start() is necessary to let backbone listen to routes and manage URL history.

Now that we have seen the basics, let’s try integrating all of these parts into a sample application.

Sample App:

So now we are going to apply what we have learned so far in a sample application. Say that we have this application that tracks our Travel Plans (cheers to our inner wanderlust! <3)! We can add new places and cross-out already visited ones! We can also filter domestic and international travels as well (sooo, get your passports ready!).

We have the model Trip to represent each of our travel plans and the TripList collection to represent all our Trips. We then create two Views, a TripListView and a TripView, which are collective and individual views for our Trips.

And then finally, we declare a router that would make our “pages” bookmark-able. We’ll be using this for our filters for domestic and international travel as well.

You may also see the full source page in this public gist.

I. Including the required JS files

In the head of our html page, I added jQuery, Underscore, Backbone, and LocalStorage. Take note of the order as one is a prerequisite of the next ones. I also added basic styles to make our page a little bit presentable.

Screen Shot 2016-01-16 at 9.01.25 PM.png

II. Organize Backbone Components

In the spirit of organizing the components of our Backbone application, let us “namespace” them.

Screen Shot 2016-01-16 at 9.03.46 PM.png

III. Individual Trip Model

We first have our Trip model. We utilized Backbone defaults and added a function toggleState that basically just toggles the “completed” attribute of our Trip.

Screen Shot 2016-01-16 at 9.04.03 PM.png

IV. Trips Collection

Next would be our TripList collection which is the group of our Trip models.

Screen Shot 2016-01-16 at 9.04.12 PM.png

V. Defining the template to our individual trips

We first define a template for an individual trip. So basically our trip will be shown in table cells. … and you guessed it right, our tagName for the view that will be utilizing this template is a <tr>.

Screen Shot 2016-01-16 at 9.02.26 PM.png

Once we have defined our template, we then compile it using Underscore’s _.template function and assign it to our Travel.Templates.TripTemplate variable.

Screen Shot 2016-01-16 at 9.04.26 PM.png

Our namespacing has been quite useful so far. One look at a variable, we already know if it’s a model, a collection, a template, and so on.

VI. Individual Trip View

We can notice the _.bindAll(this, ‘render’, ‘toggleCheckbox’, ‘determineClass’) line in the next snippet of code. What we are doing here is ensuring that the correct reference to “this” is used in this methods. We are binding this specific view to this for these methods.

For example, look at the render() function, we can use this.$el. Without binding “this” on the initialize function, we may not be able to do it since this may be bound to something else – a button, the window, or anything that triggered it.

Screen Shot 2016-01-17 at 1.03.43 AM.png

Screen Shot 2016-01-17 at 1.03.58 AM.png

You may also see that in our isHIdden function, we made use of a app.TravelFilter variable which is initialized in our Backbone router (which we will see later).

VII. Trip List View

Next is our trip list view which house all our trips. We can see that it “listens” to the add and filter events on our collection (TripList) and does certain fucntions accordingly (update UI, etc).

Screen Shot 2016-01-17 at 1.04.43 AM.png

Screen Shot 2016-01-17 at 1.04.51 AM.png

And here’s how our $(‘#body’) looks like. It also houses the $(‘#loc-filter’) that when clicked triggers the createTrip function as we indicated through the events hash of our view.

Screen Shot 2016-01-17 at 1.05.28 AM.png

From our $(‘#body’), we can also see $(‘#main-table’) to whom we append the table rows created from our TripListView render function.

$(‘#add-btn’) is present as well and to whom we are on the lookout for the click action as we also specified on the events hash.

VIII. Backbone Router

Screen Shot 2016-01-17 at 1.06.29 AM.png

As we mentioned earlier, it is in the Backbone Router where we set app.TravelFilter in our view’s isHidden function.

This router now allows our URL to change depending on the applied filter:

Screen Shot 2016-01-17 at 1.18.09 AM.png

This way, we can now use the browser’s back button as well as the bookmark button to keep our filters.

Screen Shot 2016-01-17 at 1.15.18 AM.png

IX. Running our App

Screen Shot 2016-01-17 at 1.07.08 AM.png

Demo:

output_X7HVSa.gif

Woo! So much wanderlust feels right now (but that’s alright!). So there, we saw Backbone.JS, its many components, and one of its usage in an application.

Thanks for reading!

References:

P.S. There are still a lot of awesome books and references on Backbone.JS that I haven’t read yet but plan to do soon. For the mean time, on your free time, you may take a look on them as well:

Happy reading!

Underscore.JS: Your Helpful Library

Hey reader! First of all a happy happy new year! 🎉 Wishing you happiness, prosperity, good health, and success in the year ahead! \:D/

For this blog post,  we’ll be looking into Underscore.JS. As described in the Underscore.JS page,  Underscore is

“a JavaScript library that provides a whole mess of useful functional programming helpers without extending any built-in objects.”.

In a bird’s eye view, functional programming is the use of functions to transform values to other structures or into units of abstraction (and indeed Underscore provides a battalion of functions that you can use as is or use inside other functions).

Most blog posts say that if you miss the usual functional methods (available in most functional programming languages like Ruby) in your Javascript code then, Underscore is for you!

Screen Shot 2016-01-07 at 5.06.40 PM.png

Underscore.JS Website

Looking through the available functions and sample code, indeed, it’s true! Underscore provides a wide array of functions including pluck, map, and reduce which we see (and use) most of the time with our server code and other functional programming languages. With these, it is much easier to manipulate and transform data even on the client side.

To see a quick sample:

Let’s say we have this array:

var ratings = [80, 90, 99, 98, 100, 60, 50, 70];

And we want to add 5 to each of the array elements. With pure JavaScript, we do this:

for(i = 0; i < ratings.length; i++) {
   ratings[i] = ratings[i] + 5;
}

But with Underscore on, we can do a simple one-liner:

ratings = _.map(ratings, function(rating) { return rating + 5;});

Tadaaaa! Sweet and simple isn’t it? So now let’s get it going with Underscore.js.

Including Underscore.JS in our File

To utilize Underscore, we need to first load it in our page. There are many methods to achieve this depending on your need, you can have bower, npm (Node Package Manager), Require.JS, among others. For this blog post, I downloaded underscore.js and included it in our page.

http://underscore.min.js

We can check that is indeed loaded, by typing “_” in our console:

Screen Shot 2016-01-07 at 7.05.29 PM.pngNow that we have Underscore is loaded, we can start coding either by typing in the browser console or adding JavaScript code to in our html file.

 

Getting Started with Array, Collections, and Objects

As you may have observed, all of Underscore’s functions can be invoked on “_” (but we could also change this as we’ll see later on :D)

On the left side of Underscore’s page, you can see the multitude of functions available in the different categories of Collections, Array, Functions, Objects, Utility, and Chaining.

In this blog post, we’ll see a few examples from those categories and we’ll see how we can combine them to form more complex queries.

For the examples below, this is the dataset that we will be working on:
Screen Shot 2016-01-07 at 7.22.37 PM.png

_.each

We can use _.each to iterate over an objects (that can be enumerated)

For example we want print the items and the category where they belong:

_.each(grocery, function(item) {
 console.log(item.name + " belongs to " + item.category)
 });

Screen Shot 2016-01-07 at 7.30.02 PM.png

_.pluck

Similar to Ruby’s pluck, we can use pluck when we want to extract a list of values for the given key (think of it like a shortcut to map when just getting the values).

For example, if we want to get all the names of the items in our grocery list, we could do:

_.pluck(grocery, 'name')

Screen Shot 2016-01-07 at 7.30.40 PM.png_.filter

Returns the elements in the list that returns true for the given condition.

Say we want to get all grocery items with price less than 50, we can have:

_.filter(grocery, function(item) { return item.price < 50; })

* _.filter is now the preferred name for _.select as mentioned in the official documentation but using _.select still works so far (you might see this often in other Underscore.JS blogs and tutorial). 🙂

Screen Shot 2016-01-07 at 7.33.50 PM.png

_.defaults

In case there are some undefined properties, _.defaults fills them up for you depending on the default values that you provide.

grocery = _.map(grocery, function(item) {
 return _.defaults(item, {name: 'Unnamed', category: 'Uncategorized', subcategory: 'Unsubcategorized'});
 });

Screen Shot 2016-01-07 at 7.39.30 PM.png

On our remote controlled car object (last item in the list), we can see that after we ran _.defaults, category and subcategory were filled in and were set to Uncategorized and Unsubcategorized repectively.

 

_.pick

In an object’s sea of attributes, when you only want certain attributes, you can use _.pick.

Let’s say we want our array grocery to have objects that only include name and category, we can do:

console.log(_.map(grocery, function(item) {
 return _.pick(item, 'name', 'category');
 }));

Screen Shot 2016-01-07 at 7.46.32 PM.png

_.reduce

The reduce function allow us to compress a list to a single value.

For example, we want to add all the prices of our items. In our callback, we first pass acc, our accumulator and item, the variable upon which the elements of the list will be assigned to in the loop.

_.reduce(grocery, function(acc, item) {
 return acc + item.price
 }, 0);

Screen Shot 2016-01-07 at 7.47.22 PM.png

_.groupBy

_.groupBy groups the list of a list into categories and returns an object with the categories as keys and with arrays containing the items that fit into that certain category.

_.groupBy(grocery, function(item) { return item.category })

Screen Shot 2016-01-07 at 7.50.24 PM.png

_.countBy

_.countBy on the other hand, groups a list in categories that you can specify and returns how many belonged to the specific category.

Here, we counted how many belonged to the different price ranges, 1-30, 31-60, 60-100, and 100 and above.

_.countBy(grocery, function(item) {
   if (item.price < 30) return '1 - 30';
   if (item.price < 60) return '31-60';
   if (item.price < 100) return '60-100';
   return '> 100';
 });

Screen Shot 2016-01-07 at 7.48.00 PM.png

_.range

_.range, on the other hand, is a handy function that gives the values within the given range (start inclusive, end exclusive) by increments of the given third parameter.

_.map(_.range(1, 12, 1), function(day) { return 'Day ' + day + ' of Christmas!'});

Screen Shot 2016-01-07 at 7.48.51 PM.png

Doing _.range(0, 10, 2), on the other hand, gives 0, 2, 4, 6, 8. And having a negative incrementor like _.range(99, 0, -1) gives the numbers from 99 to 1 in descending order.

 

Continuing with Function and other Utility Functions

_.once

Another handy function from Underscore is _.once, it allows the wrapped function to be ran only once. Succeeding calls to the wrapped function just returns the given previous value.

generateRaffleCoupon = function() {
 // Assigns only one unique raffle number per user. 
 var points = _.random(10);
 return points
}
a = _.once(generateUniqueId)

Screen Shot 2016-01-07 at 11.31.09 PM.png

 

In the above example, only one raffle number can be assigned to a user and succeeding calls to our simple raffle number generator just gives the already assigned number.

The original unwrapped function, generateUniqueId(), on the other hand, just behaves normally and can gives different values for different calls as we can see in the last two calls.

_.times

_.times invokes the given function for the given number of times.

_.times(5, function(i) { console.log('hi ' + i)});

Screen Shot 2016-01-07 at 7.52.04 PM.png

 

Method Chaining

Above, we saw a lot of handy functions that you should let you go up and running (but of course there are still so much more that you should also check out the official documentation :D)

As we mentioned above, functional programming involves the use of functions to accomplish a certain task, either to transform objects or to simplify and reduce an object or list to a single value. And in accomplishing a task, we may use not only one, but a series of functions to get our desired result. For this purpose, we can do method chaining.

Calling _.chain returns wrapped objects so we can only get the value until we call  .value() on our chain.

console.log(_.chain(grocery).map(function(item) {
 return item.category + ' Product';
 }).uniq().value());

Screen Shot 2016-01-07 at 7.51.01 PM.png

Underscore.JS as a Templating Engine

Say we have a dynamic page that should say “Hello <name of user here>“. We need to have our html code evaluate a dynamic value that will be passed to it. For this purpose, underscore’s _.template comes handy.

So how do we do it?

First, let us declare our template and enclose the dynamic values with the default interpolation delimiter of Underscore <%= %>.

var template = 'Hello <%= name %>! Welcome to this site!';

And then let’s compile it with _.template,

var finalTemplate = _.template(template);

which returns as with a function that we can call.

console.log(finalTemplate({name: 'John Doe'}));

Screen Shot 2016-01-08 at 10.05.41 AM.png

 

We now have our html code with the name variable replaced by the given parameter. To use this, what we can do is just assigned result ot html (for ease of use, I also used jQuery for DOM manipulation):

result = finalTemplate({name: 'John Doe'});
$('#header-txt').html(result);

 

Other Configurations

As mentioned above, there are several customizations that you can do with Underscore and here are some of them:

I. Changing _

We can change _ to other characters or set of characters that you like (maybe you want to do this if you have other use for the underscore character like storage for the last value), you can do the following:

var uscore = _.noConflict();

So now, we can use uscore instead of _

events = ['New Year', 'Graduation', 'Birthday', 'Anniversary'];
console.log(uscore.each(events, function(event) { console.log('Happy ' + event  + '!!!')}));

Screen Shot 2016-01-07 at 5.01.03 PM.png

But bear in mind that when you do this, _ no longer is usable, unless you re-assign. 

Screen Shot 2016-01-07 at 5.01.49 PM.png

II. Object Orientedness

scores = {'Bob': 1, 'Alice': 4, 'Mallory': 3};
(scores).keys();
(scores).invert();
(scores).keys().map(function(p) { return "Hi " + p + "!"; })

When doing this object oriented style, of using Underscore.JS, you can immediately chain functions without using _.chain.

Screen Shot 2016-01-07 at 4.58.21 PM.png

III. Customized Template Delimiters

In case we want to change the delimeters from being <% %> to something else of our liking, we can do so by proving custom interpolation and evaluation regular expressions parameters to _.templateSettings.

In this example, we changed <%= %> to {{ }}

_.templateSettings = {
 interpolate: /\{\{(.+?)\}\}/g,
 evaluate: /\<\%(.+?)\%\>/g
 };

Screen Shot 2016-01-07 at 8.15.59 PM.png

Sample application

So now, we try to build a sample application that uses Underscore.JS for data processing as well as a templating engine.

Say we have a product inventory, where our list of grocery items is displayed plus the user can also add more items.

Screen Shot 2016-01-07 at 5.48.35 PM.png

The full source code can be found in this gist.

In implementing this, we used the following:

 

  1. Use of Defaults

    We allow empty categories and subcategories in our form so we need to fill them up with defagrocery = _.map(grocery,

    function(item) {
       return _.defaults(item, {name: 'Unnamed', category: 'Uncategorized', subcategory: 'Unsubcategorized'});
    });

    Screen Shot 2016-01-07 at 5.50.14 PM.png

  2. Use of Templates

    We also used templates to display dynamically our table. We call the updateView() function when the page loads and every time an item is added to our grocery list. Screen Shot 2016-01-07 at 5.50.37 PM.pngScreen Shot 2016-01-07 at 5.50.29 PM.png

  3. Customized Template Delimiters

    We changed the interpolation delimiters from <%= %> to {{ }} and retained the evaluation delimiters as <% %>.

    Screen Shot 2016-01-08 at 10.14.55 AM.png

  4. Some Functional Programming

    We standardized our error and warning messages by creating the fail and warn methods which we can call anywhere accordingly.

    Screen Shot 2016-01-07 at 5.57.20 PM.png

    We also created a parser for our input which is called before we push our the new item to our grocery list. This parser calls our fail and warn functions.

    Screen Shot 2016-01-07 at 5.50.56 PM.png

Demo:

output_ujipux.gif

There, as we saw, Underscore.JS is very helful and provides tons of functions that we can use to manipulate our data on the client side. With a mere 4 KB file size, it can already do wonders! Try it now! 🙂

References: