Building a Captcha using HTML5 Canvas

CAPTCHA (/kæp.ə/, an acronym for “Completely Automated Public Turing test to tell Computers and Humans Apart”) is a type of challenge–response test used in computing to determine whether or not the user is human.[1]
The term was coined in 2003 by Luis von AhnManuel Blum, Nicholas J. Hopper, and John Langford.[2] The most common type of CAPTCHA was first invented in 1997 by two groups working in parallel: (1) Mark D. Lillibridge, Martin AbadiKrishna Bharat, and Andrei Z. Broder; and (2) Eran Reshef, Gili Raanan and Eilon Solan.[3] This form of CAPTCHA requires that the user type the letters of a distorted image, sometimes with the addition of an obscured sequence of letters or digits that appears on the screen. Because the test is administered by a computer, in contrast to the standard Turing test that is administered by a human, a CAPTCHA is sometimes described as a reverse Turing test.

This user identification procedure has received many criticisms, especially from disabled people, but also from other people who feel that their everyday work is slowed down by distorted words that are difficult to read. It takes the average person approximately 10 seconds to solve a typical CAPTCHA.[4]

Demo

On the similar lines, we are going to build a simple Captcha, which is going to validate a form before submitting it. Here is how it is going to look like

Live demo of the same can be found here: arvindr21.github.io/captcha

So, let’s get started.

Design

The Captcha module that we are going to create in this post can be tightly coupled with an existing form or can be used in a generic way.

We are going to have a container that the app owner is going to provide. The captcha and the input field are going to be created inside this container.

To generate the passcode, we are going to use  Math.random() in combination with a computed scenario of uppercase or lowercase letters.

The input field will be publishing two events on keyup.  captcha.success when the validation of text box value matches the generated passcode &  captcha.failed when the values do not match. The “form owner” is going to listen to these events and work with it to get to know if the captcha is valid or invalid.

In the sample form we are building, we are going to enable or disable the submit button based on the above events.

And we are going to style the text in canvas as well to add some randomness.

So, let’s get started.

Setup Simple Login Form

We are first going to setup a simple login form using Twitter Bootstrap 4. We are going to use Signin Template for Bootstrap for the same.

Anywhere on your machine, create a folder named  login-form-with-captcha and inside that create a new file named  index.html.

Update  index.html  as shown below

I have borrowed the structure and styles from Signin Template for Bootstrap and built the above page.

As you can see, the Sign in button is disabled on load. We will enable the button once the Captcha is valid. We will do this in the later sections.

If you open the page in the browser, it should look something like


A simple form for a simple job!

Setup Captcha

Now, we are going to setup the container where the Captcha is going to appear. Just above the button tag,  we will add the Captcha container

Next, we are going to create a file named  captcha.js in the  login-form-with-captcha folder and then we will link the same to  index.html  just after the form tag as shown below

The basic  captcha.js would be structured this way

The above code is an IIFE with a Module pattern.

If we save the above file and refresh the browser, we should see the following in the console

Now, we will flesh out the remaining code.

Develop Captcha module

Now that we have a basic structure, we will continue building the plugin. First we are going to setup the  init()

Init()

In  init(), we are going to do the following

  1. Get the captcha container
  2. If container does not exists, exit the initialisation
  3. Create a canvas element & an input text element
  4. Setup Canvas
  5. Setup Textbox
  6. Bind events on Textbox
  7. Generate Passcode
  8. Set Passcode
  9. Render component on page

The Updated  init() would look like

setupCanvas()

We are going to setup a canvas element as shown below

We are setting up a canvas with the width of the parent container and height of 75px.

setupTB()

The text box will be setup as shown below

We have updated the type of input field and added a className and a placeholder. Next, we are going to bind events to the input field. The .are the events that the parent application consuming this captcha would be listening to.

bindTBEvents()

On keyup, we are going to validate the passcode against the input field

We have created 2 events

  1. When the validation is successful
  2. When the validation failed

Pretty straight forward.

generatePasscode()

Below is the logic to generate a random passcode.

Scripting to the rescue!

setPasscode()

To  setPasscode() , we are going to add two more helper functions that create a random font color for a character.

And then finally

render()

Now that we have all the pieces ready, we will render the canvas and text box on the page

This concludes our Captcha module.

The final  catpcha.js would be as follows

Setup Validation

Now, we are going to setup the validation on the form. After including  catpcha.js in the  index.html

The complete  index.html would be as follows

Save all the files and when we refresh the page in the browser, we should see

You can find the above code here: arvindr21/captcha.


Thanks for reading! Do comment.
@arvindr21

Deploying a Node.js Docker container to Heroku

In the last post titled Developing Node.js applications in Docker, we have seen how we can work with Docker as our development environment.

In this post, we are going to take the app that we have built named docker-node-app and deploy it to Heroku as a Docker container.

The sample code used in this post can be found here: docker-node-app.

So, let’s get started.

Setup Heroku

The first thing we need to do is download and install Heroku tool belt on our local machine.

Download Toolbelt

You can follow the instructions given here: Install Heroku Toolbelt to install Heroku tool belt for your Operating System.

Setup Account

If you do not have a Heroku account, you can signup here.

Login

Now that we have Heroku installed, we will login. Open a new command prompt/terminal and run

Next, we need to login to the container registry. Run

Once we have successfully logged in to Heroku & Heroku container registry, let’s work with Docker.

Setup Docker

The first thing we are going to do is download Docker for our Operating System.

Download

To Install Docker on our machine, navigate to here & download the software for your OS.

Test Download

Once Installed, you can open up a command prompt/terminal and run  docker ps and you should see something like

At this point, we have both Docker as well as Heroku installed on our machine.

Next, we are going to containerize our app and deploy it to Heroku.

Setup docker-node-app

If you have not already done, please go through Developing Node.js applications in Docker, where we see how to develop Node.js applications using Docker. We are going to begin at the ending of that post.

Clone docker-node-app

Now, we are going to clone docker-node-app from https://github.com/arvindr21/docker-node-app. From anywhere on your machine, run

And then  cd docker-node-app .

Fix Port

We need to make a change to the Dockerfile  to fix the port. While deploying to Heroku, port would be assigned by Heroku.

Open Dockerfile  and update it as shown below

That is it, we are all set to deploy our awesome container app to Heroku.

Deploy to Heroku

Now, we are going to deploy to Heroku. We are going to follow the below steps

  1. Heroku create new app (one time)
  2. Heroku container push – Create and push the container to Heroku Container Registry
  3. Heroku container release – Release/run the container app
  4. Heroku open – Launch the app

From inside  docker-node-app run

This will create a new Heroku app.

Next, we will push the container

Now, we will run the container

And finally open the deployed app run

And we should see

Voila! Our Node.js that we have containerized while development is now deployed to Heroku with ease.

Development & Deployment simplified!

PS: I am shutting down the above Heroku app, as it does not have any thing specific to showcase.

Hope you got an idea as to how we can deploy Node.js containerized application to Heroku.


Thanks for reading! Do comment.
@arvindr21

Developing a MEAN app with Angular 2.0

I know, I know it is too early to be building end to end apps with Angular 2.0, but I got so excited after looking at ng2-express-starter by my dear friend Antonio Fernandes. I was like, If we can integrate an Angular 2.0 app with an Express app, we can definitely add the MongoDB layer to make it a M.E.A.N. app. So, in this post, we will be developing a MEAN Todo App (Grrr..). This post is heavily inspired by Antonio’s Angular 2.0 Express starter app.

The final app would look like

Screen Shot 2015-04-29 at 1.48.10 pm Screen Shot 2015-04-29 at 1.49.06 pm Screen Shot 2015-04-29 at 1.50.02 pm

You can play with a live instance of the above app here. (It might take upto a minute to load the page, please be patient or open the dev tools – network tab to check progress).

You can find the completed code here.

Couple of things before we proceed

  1. Thumbs up to Tim Jacobi for creating angular2-education repo, which consists of lot of useful links to learn Angular 2.0
  2. Angular 2.0 is still in development. The todo app we are going to build is developed using Angular 2.0 2.0.0-alpha. There is a very good chance that most or all of this code can be of no help when Angular 2.0 becomes stable.

Prerequisites

If you are new to Angular 2.0 check out

  1. Getting Started with Angular 2.0
  2. Tim Jacobi’s angular2-education repo

If you are new to MEAN Stack development check out

  1. MEAN Stack – A Hands on Tutorial (with Angular 1.x)
  2. MEAN Stack Workshop

Architecture

A MEAN stack app would typically consist of a server layer built with Nodejs & Express – Express being the web framework. MongoDB for data persistence & Angular as the client side MVW framework.

ng2As you can see from the above diagram, Express exposes REST End points that would be consumed by the Angular 2.0 app. And when any request is made to the REST end point, Express contacts MongoDB and manages the data.

This is pretty much our architecture.

Note : If you are looking for creating a secure REST API with Nodejs checkout : Architecting a Secure RESTful Node.js App.

Setting up the Server

First, we are going to setup an express app, build the REST API to Create, Read, Update & Delete todos and then integrate it with the Angular app.

Create a folder named ng2do-mean-app. Open a terminal/prompt here and run

npm init

Fill up the details as applicable.

Next, we will add express dependencies to our project. Run

npm install --save body-parser cookie-parser ejs express mongojs morgan path

This will download the required dependencies to run the express app. Once the above installation is done, your package.json should look like

At the root of the ng2do-mean-app create a file named server.js. Update it as below

This is a typical express server. Couple of things, on line 7, 8 we are including two sets of routes and on line 24, 25 we are mapping the routes to end points.

Next, we are going to create the routes folder and the two route files we declared above.

Create a new folder named routes at the root of ng2do-mean-app folder. Create a file named index.js inside the routes folder. And update index.js as below

We define a route to handle the http://localhost:3000/  and dispatch the index.html file.

Next, at the same level as index.js, create another file named todos.js. Update todos.js as below

Things to notice

Line 4 : I have created a new MongoDB instance for this example from MongoLab and configured it with Mongojs.

Line 7 : Endpoint to get all todos

Line 18 : Endpoint to get one todo based on the id provided

Line 31 : Endpoint to save a todo

Line 50 : Endpoint to update a todo

Line 79 : Endpoint to delete a todo

Test REST API

If you save all the file and run

node server.js

the express server would start on port 3000. If you navigate to  http://localhost:3000/api/v1/todos, you should be able to see all the todos (if any & if you have setup everything correctly). You can use Postman or any REST Client to test the remaining methods as well.

Pretty sweet right! Our REST API is completed. Now from our Angular 2.0 app, we are going to connect to the above REST API and manage our UI.

Setup the Client

The first thing we would be doing as part of the client side development is to download the Angular 2.0 starter app. This starter app consists of all the Angular 2.0 code and its dependencies.

From the root of ng2do-mean-app folder, run

git clone https://github.com/angular/quickstart.git public/vendor

As of today, the quickstart project does not ship with Angular 2.0 2.0.0-alpha source, which is needed for our project. To update the same, we will run the following commands from inside the public/vendor folder

npm install

gulp

npm install rx --save

The above steps are NEEDED till the quickstart project ships with Angular 2.0 2.0.0-alpha release.

Next, to manage client side dependencies, we are going to use bower. We will create a new bower.json file. From the project root, run

bower init

This will create a new bower.json file and it should look something like

Next, create a file at the same level as bower.json named .bowerrc. This file will consists of bower config. Update .bowerrc as below

Now, we will add Twitter Bootstrap to our app. Run

bower install bootstrap --save

This should download the Bootstrap source and place it inside the public/vendor/bower_components folder.

If you do remember, in routes/index.js we have a route that dispatches the index.html file. We will create that index.html file now.

Create a new folder named views at the root of our project & inside views create a new file named index.html. Update index.html as below.

Things to notice

Line 5 : We have included bootstrap css that we have downloaded using bower

Line 7 : The es6 shim file

Line 12 : Init our base component – todo-app

Line 18 : Paths where our assets are located

Line 28 : Kick off the app

In the next steps, we are going to create all the referenced files.

Client Side code structure

As of today, Angular 2.0 support only HTTP GET request using the XHR module. So, I have borrowed Antonio’s approach for making a HTTP GET, POST, PUT, DELETE calls.

So this is how we are going to structure the app

ng2-client

We will have a Todo App component, that will interact with the Todo Factory, which in turn uses the XHR factory to work with the REST API.

Developing the App

The first thing we are going to do is develop the todo-app component. Create a new folder named components inside the public folder. And create a new folder named todo-app inside the components folder.

Inside todo-app create a new file named todo-app.es6. Update todo-app.es6 as below

Things to notice

Line 1 : We import Component, View, bootstrap, For from Angular 2 source

Line 2 : We import TodoFactory, which we will be creating a bit later

Line 5 : We create a new component identified by the selector todo-app

Line 9 : We are going to load the template for this view from an external file and also specify what directives would be using, so that Angular can inject them.

Line 15 : We create a TodoAppComponent that consists of the component definition.

Line 17 : We create a new variable named todos  of type Array.

Line 19 : Inside the constructor method, we are going to fetch the list of todos using  TodoFactory.getAll() and assign the same to todos. This will take care of loading any existing todos on page load.

Line 27 : This method is used to add a new todo to our DB. When the user enters a Todo and hits the return key, we fetch the text, create a todo object and call the  TodoFactory.save() passing in the todo to be saved. Once we get a response, we update the local  todos with the response from the server, to keep things in sync.

Line 42 : This method is used to update the todo text in the DB. It is pretty much same as the addTodo() except, this time we have a _id  associate with the todo and we use TodoFactory.update() to update the data against the given todo.

Line 59 : This method is used to update the todo status, i.e. the todo completion. Here we pick the todo’s isCompleted property and build a todo object. We then call the same  TodoFactory.update() to update the data.

Line 74 : This method is used to delete a Todo. We pass the Id of the todo to be deleted to TodoFactory.delete() and the todo gets deleted from the DB. Once the server responds with a success, we clear the same from the local todos  array to save a DB call.

Line 91 : This is a utility method, that helps us manage the state of the todo. When clicked on the Edit button, next to the todo, we set isEditMode  to true and when we are done editing, we set isEditMode  to false.

Finally on line 101, we bootstrap the TodoAppComponent.

Next, we are going to create the template. Inside the todo-app folder, create another file named todo-app.html. Update todo-app.html as below

Before digging into the file, we will look at three changes to Angular 2.0 templating syntax.

  • Variable are declared using a hash before them – #name
  • Event Handlers are declared using a parenthesis around them – (click)
  • Property binding are done using square braces – [class]

Keeping the above in mind, we will go through the above template

Line 6 : We create a input element, which is bound to a local variable named todotext which is represented by  #todotext on the tag. We have bound a  (keyup) event that calls  addTodo() in our component definition.

Line 11 : If there are no todos, we show a message – No Todos yet!. This is achieved using  [hidden] property binding

Line 14 : We use the  *for syntax (analogous to ng-repeat) to iterate over all the todos in our collection and display them. Also do notice  [class.strike], (analogous to ng-class) if the current todo is in a completed state, we want to add a class named strike.

Line 16 : We provide a check box for the user to check or uncheck the todo. The state of the checkbox is maintained by  [checked]="todo.isCompleted". And when a user clicks on the checkbox, we set the value of isCompleted for that todo from updateStatus().

Line 19 : We display the todo text if it is not in edit mode

Line 20, 21 : we show the editable text box and a cancel button when the todo is in edit mode.

Line 24 : Button to toggle edit mode

Line 25 : Button to delete a todo

Now you can figure out what is happening on a tag based on the 3 new changes we saw earlier. Also, the classes which you see here are specific to Twitter Bootstrap.

That is it, our todo-app component is ready.

Now, we need to develop the two services. Create a new folder inside the public folder named services. Create a new file inside it named todos-factory.es6 and update it as below

Quite self explanatory.

Important : Angular 2.0 DOES NOT have a $http service. I have created one using the xhr-factory and named it to $http for familiarity sakes.

Next, create a new file named xhr-factory.es6 inside the public/services folder and update it as below

All we are doing is making a HTTP Request using the XMLHttpRequest() and returning a promise.

Pretty simple right! With this we are done with app logic. For some styling, we will create a new folder inside the public folder named css. Inside the css folder, create a new file named app.css and update it as below.

Test the App

That is it! Save all your files and run

node server.js

Next, navigate to  http://localhost:3000 and you should see

Screen Shot 2015-04-29 at 1.48.10 pm

Add a few todos and you can click on edit

Screen Shot 2015-04-29 at 1.49.06 pm

You can mark todos as completed or delete them

Screen Shot 2015-04-29 at 1.50.02 pm

Simple and sweet MEAN App with Angular 2.0


Thanks for reading! Do comment.
@arvindr21

 

Pushbots and Cordova – Easy Push Notifications for your app

A few days ago Francisco Merino requested a post for implementing push notifications for a Phonegap/Cordova app. He was looking for a simple solution to start off. So, here is the post.

In this post, we will be sending push notifications to a device using the Pushbots dashboard as well from its Nodejs API.

Pushbots’s notification service is pretty simple to use and is one of the best solution if you are planning to send notification to all the devices at once. You can read more about pushbots here.

A quick demo of the app we are building

You can find the completed code here.

So, let us get started.

What is a Push Notification?

If you are new to push notifications, take a look at this

Setup Pushbots

Navigate to the Pushbots Signup page and create an account. You will be sent an activation mail and once you activate your account, you can login. You will be taken to your dashboard, and it should look something like

Screen Shot 2015-04-20 at 9.42.10 am

From the bottom of this page, create a new app. Let is calls it testPushApp and hit the return key. This will create a new project.

Next, we need to obtain the Apple Push Certificate and Android’s GCM API Key. You can follow the step by step guide below

After you have obtained the GMC API key and the Apple’s Push certificate, you need to head back to your app on Pushbots, Click on settings and update the same inside the Platforms’s Tab

Screen Shot 2015-04-27 at 10.36.30 am

Develop the App

Once you have the GCM sender ID and API Key or Apple’s Push Certificate, we will scaffold a new Cordova app. For this post, I will be using only Android’s GCM values.

Create a new folder named testPushApp. Now, scaffold a new Cordova project. Open a new terminal/prompt inside the testPushApp folder and run

cordova create myApp com.push.notif.app testPushApp

Note : Make sure you have Nodejs installed and then Cordova installed globally before executing the above statement. If you run into any issues refer PhoneGap 3 CLI Setup on Mac & Windows.

The above command will create a new Cordova project. To test the scaffolded app, CD into myApp folder and run

cordova platform add browser

Next, we will run the app.

cordova run

and you should the app launch in you browser and it should look like

Screen Shot 2015-04-20 at 10.37.01 am

Next, we will add Android and iOS platforms.

cordova platform add android

and

cordova platform add ios

After that we will add the pushbots Cordova plugin.

cordova plugin add com.pushbots.push

Once the plugin is installed, open www/js/index.js and update the  onDeviceReady() as shown below

Things to notice

55347ccb17795958748b457c – is the application id from your Pushbots dashboard

Screen Shot 2015-04-27 at 10.40.46 am

145091056519 – is the GCM project Number from your Google developer console

Screen Shot 2015-04-27 at 10.42.33 amThis all the setup you would need to integrate Pushbots with your Cordova App for iOS. For Android there is one more step.

After you have added Android platform to the current project and installed the pushbots plugin, a new file named pushbots.xml will be created at /platforms/android/res/values/pushbots.xml. Open that file and update it as below

You can get the values from the previous step.

That is it!!! Now, we can test the app.

Test the App

I am going to deploy this app on to my Android phone by running

cordova prepare

cordova run android

This will install the app on my device. Now if I head back to the Pushbots dashboard, and select the testPushApp you should see the number of devices updated

Screen Shot 2015-04-27 at 10.51.57 am

Now, click on Send a push link and you can enter a text and send it to all devices or only to devices you wish to target (using the segmentation button below the message box).

When the notification is sent, you can checkout the same on your device

Screenshot_2015-04-27-10-53-18

Simple and sweet!

And if you want to launch a webpage when the user clicks on the notification, it is as simple as adding a custom field named openURL and the value is the link.

Screen Shot 2015-04-27 at 11.04.34 am

And when you send this notification,

Screenshot_2015-04-27-11-04-58When the user clicks on the notification, a web page with that link would be opened.

Implementing Notifications from a Nodejs App

So far, we have used the Pushbots dashboard to send the notification. Now, we are going to send push notification programatically, thanks to the NPM module named pushbots.

Inside the testPushApp folder, create another folder named myNodeApp, which is at the same level as myApp (Cordova app). Open a terminal/prompt here and run

npm init

This will create a package.json file and should look something like

Next, we will add pushbots module to our project and save it in package.json. Run

npm install pushbots --save

Create a new file named index.js at the root of the myNodeApp folder. And add the below code.

Things to notice

Line 4, 5 : You can get the ID and secret from the Pushbots dashboard, key’s tab

Screen Shot 2015-04-27 at 11.19.55 amLine 7 : The message you would like to send. 1 as the last argument indicates an Android device and 0 an iOS device. You read more about the API API V1.

Line 8 : The custom field property, to open a URL

Line 11 : Send the push notification.

If you save the file and run

node index.js

You should see

Screen Shot 2015-04-27 at 11.17.55 am

And on your device

Screenshot_2015-04-27-11-15-37

Hope this post gave you an idea on how to implement Push Notifications. Do remember, this same logic can be ported to any Cordova app, be it Ionic or Framework7.

Another widely used push notification service is PushPlugin from the Phongap team. You can check out that too.

PS : The API keys’s and ID’s shown in the video or the code would not work for you, as I have already deleted those projects.


Thanks for reading! Do comment.
@arvindr21

Getting Started with Client Side Storage

In this post, we will take a look at various client side storage solutions and how to work with them.

We are going to cover the following

  • Cookies
  • Web Storage API
    • Session Storage
    • Local Storage
    • String Compression
  • IndexedDB
  • Next Steps

You can find the completed code in the below examples here.

Cookies

There was a time when client side storage was all about saving data in cookies. Cookies were designed initially not to save data offline but rather save the established session details and send it with every request to the server.

 … a way to create a stateful session with Hypertext Transfer Protocol (HTTP) requests and responses.  It describes three new headers, Cookie, Cookie2, and Set-Cookie2, which carry state information between participating origin servers and user agents.  The method described here differs from Netscape’s Cookie proposal [Netscape], but it can interoperate with HTTP/1.0 user agents that use Netscape’s method.

You can read more : rfc2965

Back to storage with Cookies. For instance, you have a very long form to be filled in by the user. If the user refreshes the page accidentally while filling the form, you want to save the data and populate it back. And at the same time, you do not want to send this partial data to the server. This should be saved on the client side. And this is how we would implement this using cookies.

You would have a long form like

I have used only 2 form fields for simplicity. Also, I have used Twitter Bootstrap for styling. This form can be how ever long you want and how many ever form elements you want (select, radio, textarea, etc..).

And the JS code to control this would be

Things to notice

Line 5 :  A wrapper API to work with cookies. Create, Read, Delete

Line 38 : When the document is ready, we register for blur events on the form elements. And when the call back is triggered, we create a new cookie passing the cookieName, the entire form data and days to expire to  createCookie().

Line 50 : On page load, we check if there is any pre-saved data available. If yes, we read the same and populate it

Line 66 : And the form is submitted successfully, we delete the saved cookie.

And when you fill the form and “accidentally” refresh, you should the see the saved data populate. And when you inspect the saved cookies and you should see

Screen Shot 2015-04-19 at 8.41.32 am

And when submit, you should see the cookie removed.

Size Limitations :

If you want to support most browsers, then don’t exceed 50 cookies per domain, and don’t exceed 4093** bytes per domain (i.e. total size of all cookies <= 4093 bytes).

You can read more : Browser Cookie Limits.

For me the biggest problem with cookies is that, the browser sends all the cookies related to that domain with every HTTP request. Which does not sound very “Client Side Storage” for me.

Then came along HTML5 with it’s arsenal of storage solutions.

Web Storage API

The Web Storage API provides mechanisms by which browsers can securely store key/value pairs, in a much more intuitive fashion than using cookies.

The two mechanisms within Web Storage are as follows:

  • sessionStorage maintains a separate storage area for each given origin that’s available for the duration of the page session (as long as the browser is open, including page reloads and restores)
  • localStorage does the same thing, but persists even when the browser is closed and reopened.

You can read more about the Web Storage API from MDN here.

As you see from below http://caniuse.com/#feat=namevalue-storage support

Screen Shot 2015-04-19 at 9.18.22 am

there is about 94% support for Web Storage API across all browsers. Which is good as we can consider this to be a reliable solution in almost all cases.

Session Storage

Taking the above example, of saving a long form, we will implement the same using session storage API. The HTML for the page would remain the same. The JS code would look like

Things to notice

Line 1 : A wrapper around sessionStorage API.

Line 8 : We create a method to check sessionStorage support.

Line 12, 16 : Save and retrieve string based data. The Storage API saves all the values in the form of string. So any value as in a string, number, boolean can be saved and retrieved using these methods.

Line 26, 30 : These methods are used to save and retrieve Objects and Arrays. You can read more about this here : Storing Objects in HTML5 Local Storage.

Line 34 : A method to remove an item from the sessionStorage

Line 38 : A  method to clear all items from the sessionStorage

Line 47 : We check if sessionStorage is supported, else we throw an alert

Line 51 : We register a blur event on the form elements. And when the listener fires, we get the form data, convert it to an object and save it

Line 68 : We check if anything is already stored in the sessionStorage. If yes, we populate the form.

Line 76 : When the form saves the data successfully, we clear the sessionStorage.

You can inspect the Session Storage saved data and you should see.

Screen Shot 2015-04-19 at 10.01.37 amIn the above case, if the form fields are dependent on a session then the session storage is perfect. Because if the form changes for the same user for a different session, the old data will not clash with the new data.

Local Storage

What if you are looking for a way to persist the data even after the user’s session expires. The answer is simple, Local Storage API.

The transformation from Session Storage to Local Storage is as simple as replacing the word Session with Local. The updated JS file would look like

Things to notice

Line 1 : A wrapper around localStorage API.

Line 8 : We create a method to check localStorage support.

Line 12, 14 : Save and retrieve string based data. The Storage API saves all the values in the form of string. So any value as in a string, number, boolean can be saved and retrieved using these methods.

Line 26, 30 : These methods are used to save and retrieve Objects and Arrays. You can read more about this Storing Objects in HTML5 Local Storage.

Line 34 : A method to remove an item from the localStorage

Line 38 : A  method to clear all items from the localStorage

Line 47 : We check if localStorage is supported, else we throw an alert

Line 51 : We register a blur event on the form elements. And when the listener fires, we get the form data, convert it to an object and save it

Line 68 : We check if anything is already stored in the localStorage. If yes, we populate the form.

Line 76 : When the form saves the data successfully, we clear the localStorage.

You can inspect the Local Storage saved data and you should see

Screen Shot 2015-04-19 at 10.15.53 amNow, even after rebooting the machine, this data will be persisted.

Size Limitations :

The size limitations for a given domain for the Storage API is dependent on the browser and the OS. If you check out Web Storage Support Test,

Screen Shot 2015-04-19 at 10.34.15 am

The above values are for Chrome 42 64bit. Also based on a lot of solutions on the internet, the storage seems to be around 5 MB.

You can read more : Is 5MB the de facto limit for W3C Web Storage?

String Compression

If you see that your storage needs seem to exceed the 5 MB quota, you can implement lz-string compression. You can checkout the demo page and see the compression factor

Screen Shot 2015-04-19 at 10.44.28 am

The implementation is pretty simple. First we include lz-string.min.js in our page. Then we will update the storage API to compress and decompress the string. The updated Local Storage API would be

On line 13 and line 31, we compress the string before we save it. And on line 19 and line 37, we decompress the string.

Note : On Firefox and IE, localStorage cannot contain invalid UTF16 characters. You need to use  LZString.compressToUTF16() and  LZString.decompressFromUTF16() if you are targeting IE and FF as part of your app. Else you can use  LZString.compress() &  LZString.decompress()

If you observed the save data, you should see the compressed string

Screen Shot 2015-04-19 at 10.51.25 am

You can implement the same API for Session Storage as we did above for Local Storage. Do notice that compressing adds an overhead to the get and set process. So use this only if needed.

IndexedDB

IndexedDB is a way for you to persistently store data inside a user’s browser. Because it lets you create web applications with rich query abilities regardless of network availability, these applications can work both online and offline.

IndexedDB is an alternative to WebSQL Database, which the W3C deprecated on November 18, 2010. While both IndexedDB and WebSQL are solutions for storage, they do not offer the same functionalities. WebSQL Database is a relational database access system, whereas IndexedDB is an indexed table system.

Concepts of IndexedDB

  • IndexedDB databases store key-value pairs.
  • IndexedDB is built on a transactional database model.
  • The IndexedDB API is mostly asynchronous.
  • IndexedDB uses requests all over the place.
  • IndexedDB uses DOM events to notify you when results are available.
  • IndexedDB is object-oriented.
  • IndexedDB does not use Structured Query Language (SQL).
  • IndexedDB adheres to a same-origin policy.

You can read more about the above concepts here.

Before we start implementing IndexedDB, we need to go through its terminology.

  • database : A repository of information, typically comprising one or more object stores.
  • object store : The mechanism by which data is stored in the database.
  • version : When a database is first created, its version is the integer 1.
  • database connection : An operation created by opening a database.
  • transaction : An atomic and durable set of data-access and data-modification operations on a particular database.
  • request : The operation by which reading and writing on a database is done.
  • index : An index is a specialized object store for looking up records in another object store, called the referenced object store.

You can read more here.

Now that we have a basic understanding of what IndexedDB is all about, we will make use of it save our form offline. Yes, this use case is not an ideal example for IndexedDB. It can do a lot more.

If you are planning to use the IndexedDB API as is, you can do so by following this tutorial : Using IndexedDB. To keep things simple and interesting, I am going to use an awesome IndexDB wrapper named Dexie.js.

Dexie has a huge API that helps a lot while interacting with IndexedDB. You can read more about Dexie from its very well documented wiki.

Back to our example. We will be implementing offline storage of our form using IndexedDB via Dexie. The HTML for the form will remain the same. After you include dexie.js in your page, you can write your logic as follows

Things to notice

Line 3 : We create a new database named longForm

Line 5 :  We create a new auto incrementing index. You can read more about Schema definition syntax here.

Line 8 : We connect to the DB. On successful connection, we query the DB for any pre-saved data.

Line 10 : Once we get any pre-saved data, we populate our form on line 13.

Line 20 : On blur of any form fields, we collect the latest form data

Line 32 : We delete any existing data before we save a fresh copy.

Line 39 : When the form is successfully submitted, we will delete the DB.

When you inspect the data, it should look like

Screen Shot 2015-04-19 at 2.15.30 pm

Next Steps

With this, we have completed the most prominent offline storage solution available today. I recommend taking a look at the following as next steps

I will keep adding more resources as I get.


Thanks for reading! Do comment.
@arvindr21

Ionic Framework, Cordova and File API – A Media Player App

Yves Bamani requested a post to build a media player app using Ionic Framework and Cordova. The mediaPlayer app will show a player interface and a couple of buttons. The user can browse through the filesystem and pick a file to play. The initial request was to play both Audio and Video files inline. But I was only able to get the Audio files to play inline where as the Video will be launched in the device default video player.

Here is a quick demo of the app

Screenshot_2015-03-30-10-53-15 Screenshot_2015-03-30-10-53-24 Screenshot_2015-03-30-10-53-54

Yves also requested for the app to be built using ngCordova. But there are a couple of features in $cordovaMedia like getDuration(media)  and  getCurrentPosition(), which are not working yet. And the $cordovaFile does not have a method to recursively get all the folders in a directory, so I am going to use Cordova API as is and build this app.

You can find the completed here.

So, let us get started.

Prerequisites

You need to have the knowledge of the following to get a better understanding of the code below.

Application Design

The application is pretty simple. When the user launches the app, we show a file browser, where the user can browse through his/her device. Then they can select an audio or video file to play.

We will be using a side menu template, where the player is a instance of  $ionicModal. This modal lives in the background. As mentioned earlier, we will be using the Media API from cordova to manage the audio files and a Video player Cordova plugin by Dawson Loudon named VideoPlayer inspired by Simon MacDonald’s VideoPlayer. All this plugin does is create a new Video Intent and launch it.

I am still looking for a consistent solution on how to implement inline videos. If you do know one, please drop a comment.

I have tested this app on an Android and not on iOS.

Develop the App

Create a new folder named mediaPlayerApp. Open a new terminal/prompt here. We will scaffold the side menu template and then clean it up as per our needs. Run,

ionic start mediaPlayerApp sidemenu

Once the scaffolding is completed, you can CD into the mediaPlayerApp folder and run

ionic serve

and you should see the side menu app in your browser.

The first thing we are going to do is update index.html. Open www/index.html in your favorite editor and update it as below

We have referred the audio service JS code that consist of the logic to deal with the Media API and the controllers file which consist of the controller logic.

Next, open www/templates/menu.html. We will update this file with fewer menu items

We have removed all the old menu items and added 2 new. One to show the player, and one to browse the device.

Now, we will clean up and rename the required files inside www/templates folder

  • Rename login.html to player.html
  • Delete playlist.html
  • Delete playlists.html
  • Delete search.html

Open www/templates/player.html and update it as below

This template will be shown when we init the Ionic Modal. This Modal will always be in the background while the app is running.

This template is the base for showing the audio player. Line 18 consists of the logic to show the seek bar. Line 22 shows the play button, when we have paused the video using the button on line 25. We can also stop the media play back completely using the Stop button.

As you can see from the directives on these buttons, they are subjected to visibility based on the state of the audio file.

Next, open www/templates/browse.html and update it as below

This is a very simple template drive by the files[]  from scope. When the user launches the browse page, we will query the file system and show the root files. Once the user clicks on a particular folder, we query the file system API passing in the current folder as the root and fetch its children.

And when a user selects a file, we check if it is of the type audio or video and then play it. Else we will show a message that we cannot play the selected file.

This completes all our templates. We will now work with the Audio Service. Open www/js folder and create a new file named audio.service.js and update it as below.

Things to notice

Line 1 : We have created a new module named starter.services and added the  AudioSvc to that.

Line 8 : Defines the play audio method, which plays the given src using the Cordova’s Media API.

Line 18 : We create a setInterval for every seconds to execute  getCurrentPosition() and trigger the callback. This way we update the seek bar with the total time and time left.

Line 46 : The logic for resume audio

Line 52 : The logic for pause audio

Line 58 : The logic for stop audio

We will be injecting this service as a dependency in our controller, where we will manage the above API based on the user interactions.

Next, we will update www/js/app.js as below

Things to notice

Line 1 : We create a module named starter and inject ionicstarter.controllers and starter.services as dependencies.

Line 4 : Inside the  $ionicPlatform.ready() we config the keyboard and status bar.

Line 12, 20, 26 : We are building an API to work with the  $ionicLoading  API.

Line 32 : We config the router

Finally, the controllers. Open www/js/controller/js and update it as below