Protractor: The Secret Service


This post is not about how to install and use Protractor. I believe setting up Protractor is a lot easy, so heading over to the documentation is an ideal choice to make. For those who have not heard of Protractor yet, it is nothing but an end-to-end test framework for AngularJS applications. However, it works seamlessly for non-angular applications as well, obviously, with a small tweak which is what this post is all about.

In a nutshell, Protractor runs tests against your application running in a real browser, interacting with it as a user would. That means you have to give a set of instructions for each test you write. But before that, let us create a small demo in jQuery (no AngularJS). Below demo is fairly simple but useful to put my point across about robustness of writing tests in Protractor. In this demo, we are having a dummy Google Sign In button loaded via a fake REST call to Google Developers APIs.

<!DOCTYPE html>
<html>
<head>
	<title>Protractor: The Secret Service</title>
	<script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
	<script>
	$(window).load(function() {
		// Simulating a REST call with Google APIs
		window.setTimeout(function() {
			$('#signin-placeholder').replaceWith(
				'<button id="signin">Google Sign In</button>'
			);

			$('#signin').click(function() {
				$(this).text('Sign Out');
			});
		}, 2000);
	});
	</script>
</head>
<body>
	<div id="signin-placeholder"></div>
</body>
</html>

Sleep

Now that we understood how our application works, it’s time to write E2E tests for it. Following test block might look sound and easy to grasp to you, but there are couple of hidden tricks have been used in order to pass it.

describe('Non EC Tests', function() {
	beforeEach(function() {
		browser.ignoreSynchronization = true;
		browser.get('demo.html');
	});

	it('Should', function() {
		browser.sleep(2 * 1000);
		element(by.id('signin')).click();
		expect(element(by.id('signin')).getText()).toBe('Sign Out');
	});
});

First line in the beforeEach block i.e. browser.ignoreSynchronization is to tell Protractor that, Hey, this is not an Angular application, so do not wait for Angular to load. Start running tests as soon as the page loads in a browser. This is the one and only trick to consider while using Protractor for non-angular applications which means if in case a webdriver control flow hangs while running tests, that’s the thing to look for in the Spec. Moving on to the it block which is our actual test. In the beginning, we make sure to wait for 2 seconds as per our business logic before we click the login button. Later we confirm the button text is changed to Sign Out.

The important thing to note here is that the browser.sleep method is a last resort most people use to make tests pass to prevent random failures, however, in our case, it is tightly coupled with the business logic. If we increase/decrease the timeout in the fake REST call, we’ll have to adjust the same to fix the broken test. In addition to it, the real REST call may or may not complete within the expected timeout making your test unstable. Let’s fix that…

Wait

Selenium webdriver exports a method called browser.driver.wait that schedules a command to wait for a condition to hold true. This means wait will repeatedly evaluate the condition until it returns a truthy value. You can pass a condition or a custom function that returns a promise to it. So we will simply replace the browser.sleep statement with,

browser.wait(element(by.id('signin')).isDisplayed, 2 * 1000);

In here browser will wait until isDisplayed method returns a truthy value. If it did not, it will time out after 2 seconds. Note in protractor version 2.0.0, due to changes in WebDriverJS, wait without a timeout will now default to waiting for 0 ms – which off-course forbids our business logic. So we chose to provide ideal explicit timeout. To your surprise the above statement will throw, Failed: No element found using locator: By.id("signin") error because it’s not available in the DOM yet. We could have used browser.waitForAngular method for Angular to render the button if we were using it in the demo. Protractor deals with such scenarios nicely, especially in Angular applications wherein it forces the webdriver to wait until Angular has finished rendering and has no outstanding $http or $timeout calls before continuing.

ExpectedConditions

No worries..! Selenium offers a different mechanism to handle the same for Protractor called as ExpectedConditions a.k.a. EC. It’s similar to protractor isDisplayed API that we saw earlier but especially for non-angular applications. Again the webdriver waits until the expected condition returns a truthy value. Moreover, you can mix it with multiple and, or, and not operators. So to fix the error, we’ll use,

browser.wait(protractor.ExpectedConditions.visibilityOf(
  element(by.id('signin'))
));

This will schedule a command for the webdriver to wait and repeatedly evaluate the condition to check if the element is available/visible in the DOM. There are various functions EC supports that you should take a look at http://www.protractortest.org/#/api?view=ExpectedConditions.

Wrap up

So that’s it. In a real-world project, I happened to encountered similar issues on staging environment where pages load slighly slow than local webserver and some of my tests started failing randomly because browser.sleep hack for HTTP or AJAX calls did not pan out :-). EC statements have helped me a lot while writing robust Protractor tests for non-angular apps and made tests more stable too, mostly, on Firefox and Safari.

Thanks for reading and keep Rocking \m/.

Advertisements

Migration guide for jQuery Developers


There are couple of links explaining AngularJS to jQuery developers and my effort also goes to do the same. This post is dedicated to all the jQuery developers who wish to know AngularJS before they dive in. I myself worked on jQuery since a very long time and literally its hard to switch to something which is radically different and way cooler than jQuery (sorry, darling!).

Document is Ready?

We all know about $(document).ready() or $(window).load() methods to setup a safe wrapper around the code to make sure that everything runs after the DOM is loaded.
Also, you might have used literal styled javascript with jQuery:

var App = {
  run: function() {
    var bootstrapper = 'You have successfully bootstrapped jQuery';
    $('div.alert').html(bootstrapper);
  }
};

// Finally I'll call the main method
$(document).ready(function() {
  App.run();
});

Do not panick! Angular itself provides the manual bootstrapping the same way. Angular advocates modularity so that every piece of an application should have its own module and there is a main module that holds rest of the modules together. The subsequent code defines the main module (similar to jQuery example above) and run() block is the built-in (sort of) main method in Angular which runs once the application is bootstrapped.

  // Define a module, App
  var App = angular.module('App', []);

  // Built-in run method
  App.run(function($rootScope) {
    $rootScope.bootstrapper = 'You have successfully bootstrapped AngularJS';        
  });

  // Finally bootstrap angular manually
  angular.element(document).ready(function() {
    angular.bootstrap(document, ['App']);

    // Target an element instead
    // angular.bootstrap(jQuery('body'), ['App']);
  });

The one thing to notice here is $rootScope – which is a global variable you can bind properties to that can be injected in other modules for further use.

Finally we’ll use angular’s templating syntax {{ }} to declaratively place data into the markup instead of grabbing the element explicitly like jQuery. Can you see?

<div class="alert alert-success">{{bootstrapper}}</div>

In case you are not a fan (like me) of manual bootstrapping, you can make it automatic as well by setting ng-app directive on any element such as html, body etc. Angular looks for an element having ng-app on it and uses it as a target during bootstrapping. Now you do not need angular.element(document).ready() block as defined above.

<html ng-app="App">

XHR

AJAX is the second most important thing people use jQuery for. jQuery provides different methods to fire up an XHR call.

In angular, there is $http service which is a wrapper around the browser’s XMLHttpRequest object that returns promises .then(), .success(), and .error() based on the request was successful or failed.

The only difference is that you have to manually inject it into the module definition. Suppose I want it inside the run() block we’d seen before:

  App.run(function($rootScope, $http) {
    $http.get('foobar.php').success(function(data, status) {
      // I succedded
    }).error(function(data, status) {
      // I failed
    });
  });

Do not touch the DOM

jQuery was made to do so, Angular is not!

In AngularJS, try to avoid touching DOM implicitly as much as possible so that you can fully leverage the 2-way data binding between your data and the DOM. We are going on journey to build a process order page using following directives.

ng-model

In jQuery, .val() is a setter/getter method to interact with form controls which was quite amazing but it gets worst when you want to show the value elsewhere instantly, means we had to bind keypress events on the input control that will update the DOM as expected. But its too much effort as well as code for such a small task.

Angular provides a neat directive to rule them all. Always use ng-model in order to read values out of form controls. You do not have to manually select an element to set/get its value – Just play with plain old javascript object/array.

<input type="text" ng-model="name">
App.run(function($rootScope) {
  // setting the default value for the input
  $rootScope.name = 'AngularJS';

  // this will return the existing value of the input
  // console.log($rootScope.name);
});

ng-options

Use to lay out options based on model for select element. Know more about it.

App.run(function($rootScope) {
  $rootScope.cities = [
    {id: 'NM', name: 'Navi Mumbai'},
    {id: 'PN', name: 'Pune'}
  ];
});
<select ng-model="city" ng-options="c.name for c in cities"></select>

ng-class

Toggle CSS classes based on expression. This is a very common thing in jQuery:

if (same) {
  $('small').removeClass('strike');  
} else {
  $('small').addClass('strike');
}

In angular, you can use ng-class directive to apply CSS classes conditionally. If same is boolean true then apply strike class. Otherwise remove it.

<small ng-class="{'strike': !same}">same as billing</small>

ng-disabled

Similar to ng-class, you can disable/enable form controls using ng-disabled directive.
In jQuery,

$('[ng-model="shipping_name"]').prop('disabled', same);

In angular,

<input ng-disabled="same" 
       type="text" 
       ng-model="shipping_name" 
       placeholder="Full Name">

ng-change

You may want to reflect your billing address as shipping address instantly.
In jQuery,

<input onkeypress="$('[ng-model="shipping_name"]').val($('[ng-model="billing_name"]').val());" 
       type="text" 
       ng-model="billing_name"> 

In Angular,

<input ng-change="reflect()" type="text" ng-model="billing_name">
$rootScope.reflect = function() {
  $rootScope.shipping_name = $rootScope.billing_name;
  $rootScope.shipping_address = $rootScope.billing_address;
  $rootScope.shipping_city = $rootScope.billing_city;
};

ng-click

In jQuery,

$('div.btn-primary').click(function() {
  processed = true;
});

In Angular,

<button class='btn btn-primary' ng-click="processed = true">Process Order</button>

ng-show/ng-hide

This is again very common thing in jQuery to show/hide elements based on conditions.
In jQuery,

if (processed) {
  $('div.alert').show();
} else {
  $('div.alert').hide();
}

In Angular,

<div class="alert alert-success" ng-hide='!processed'>
  <b>Well done!</b> We've successfully processed the order.
</div>

Here is the Final Demo of our Process Order form using all above directives.

Loading partials

Many of us often create a separate header and footer partials to be injected into many pages instead of repeating all over again.
In jQuery,

<body>
    <div id='header'></div>
    <script type="text/javascript">
      $('#header').load('header.html');
    </script>

    <!-- Body -->

    <div id='footer'></div>
    <script type="text/javascript">
      $('#footer').load('footer.html');
    </script>    
</body>

In Angular, ng-include works similar to jquery.load but also allows to compile and include an external HTML fragment. Do not forget to wrap your html fragment in single quotes as I’ve already wasted an hour to figure that out ūüė¶

<body>
    <div ng-include="'header.html'"></div>

    <!-- Body -->

    <div ng-include="'footer.html'"></div>
</body>

History – page navigation

Take an example of a simple addressbook application that contains 3 links shown below and div.abPanel is the place where you would wish to load the appropriate template.

<div class='cell abLinks'>
    <a href='javascript:void(0);' id='addNewContact'>Add New Contact</a><br />
    <a href='javascript:void(0);' id='listContacts'>List all Contact</a><br />
    <a href='javascript:void(0);' id='searchContacts'>Search any Contact</a><br />
</div>
<div class='cell abPanel'>Loading... Please Wait.</div>

In jQuery, you would probably do this.

$('#addNewContact').click(function () {
  $('div.abPanel').load('add_new_contact.html', function () {
    // do all DOM manipulations or event bindings here
  });
});

In Angular, we’ll use awesome $routeProvider service without writing much boilerplate code. This simply loads a template based on hash.

App.config(function ($routeProvider) {
  $routeProvider
    .when('/add', { templateUrl: 'partials/add.html' })
    .when('/list', { templateUrl: 'partials/list.html' })
    .when('/search', { templateUrl: 'partials/search.html' })
    .otherwise({
      redirectTo: '/add'
    });
});

And finally change above links a little bit to:

<div class='cell abLinks'>
    <a href='#/add'>Add New Contact</a><br />
    <a href='#/list'>List all Contact</a><br />
    <a href='#/search'>Search any Contact</a><br />
</div>
<div ng-view>Loading... Please Wait.</div>

The one thing to notice here is ng-view directive that lets your render the template of the current route automagically.

Animation

The .animate() method allows us to create animation effects in jQuery. In order to fade out the process order page while hiding, we can write something like this:

$('div.row').animate({opacity: 0}, 1000);

In angular(version 1.1.4+), ng-animate allows us to control the animation either using CSS or JS. This directive can gel up with other directives like ng-show/ng-hide, ng-view, ng-include, ng-switch, etc.
We’ll simply add it to our div.alert which takes processed CSS class as an option.

<div class="alert alert-success" ng-show='processed' ng-animate="'processed'">
  <b>Well done!</b> We've successfully processed the order.
</div>

Then we’ll define necessary CSS classes. What happens here is when div.alert is about to be shown (means processed becomes boolean true), both processed-show and processed-show-active classes will be applied which will help fade in the element for 0.5 seconds and later be removed. And display property sets to block.

.processed-show {
  -webkit-transition:all linear 0.5s;
  -moz-transition:all linear 0.5s;
  -ms-transition:all linear 0.5s;
  -o-transition:all linear 0.5s;
  transition:all linear 0.5s;
  opacity:0;
}
.processed-show-active {
  opacity:1;
}

We can use similar css while hiding the element but opacity will change from 100% to 0%.

.processed-hide {
  -webkit-transition:all linear 0.5s;
  -moz-transition:all linear 0.5s;
  -ms-transition:all linear 0.5s;
  -o-transition:all linear 0.5s;
  transition:all linear 0.5s;
  opacity:1;
}
.processed-hide-active {
  opacity:0;
}

Check out the demo. There are more in-depth articles on yearofmoo.com and nganimate.org.

jQuery plugins

We can not live without it. A few weeks ago, I’d written an article on how to use jQuery plugin the angular way.

Custom Directives

AngularJS really shines where it lets you write custom directives also. There are hell lot of articles to get you started.

Wrap ups

I’d seen many of my colleagues struggled to get going with AngularJS and hence I’d decided to write this post. Time has come to expand the horizon. All the best.

55th Neat thing built with AngularJS


I’m extremely glad to announce today that an application I’d built over months in AngularJS has now been listed on builtwith.angularjs.org

What’s in a name?

y’know like all the funky names, I named it eShell. Oh, wait, its not another terminal emulator. Rather, its an eLearning player – a building block for eLearning courses to be run on created with authoring tools. FYI, An eLearning player is a building block for more conventional eLearning courses. Its pretty basic though I’d a different vision when I decided to write it. You can learn more about it here and here.

I’ve covered:

  • jQueryUi Drag & Drop
  • Form Validation in AngularJS
  • Ordering/Sorting images
  • jPlayer integration to play audios

Working Demo

Update:

I’d decided to rewrite the application from the scratch and also written the steps how I did it.

Writing your first application using Backbone.js


Getting Started

As we know, writing a Single Page application using just jQuery is not quite a good idea especially when our application grows bigger and we need to modularize our codebase. To resolve this problem, there are many MV* frameworks available for us.

What is Backbone.js

Backbone.js is one of the many Javascript frameworks for creating MVC-like web applications which comes with a default template engine Underscore.js. Backbone.js lets us split our code into Model, Collection and View. The general idea is to organize an interface into logical views, backed by models, each of which can be updated independently when the model changes, without having to redraw the page.

On the front-end, it’s my architectural framework of choice as it’s both mature, relatively lightweight and can be easily tested using third-party toolkits such as Jasmine or QUnit.
– Developing Backbone.js Applications by Addy Osmani.

What is MVC

In this case, each contact is our Model, all the contacts group together by Collection and View renders the contacts details. We are going to use contacts mysql table for this application so contacts table is our Collection and each row exists in the table is our Model.

Let us begin

Let’s start by writing our first Backbone.js app – Addressbook in Backbone.js. Here is our 2-column layout, one for side links on the left and another to load forms/grid.

addressbookMVC/index.html – Main Layout

<div class='table abWrapper'>
  <div class='row'>
    <div class='cell abLinks'>
      <a href='#add_new_contact'>Add New Contact</a><br />
      <a href='#list_contacts'>List all Contacts</a><br />
      <a href='#search_contacts'>Search any Contact</a><br />
    </div>
    <div class='cell abPanel'>Loading... Please Wait.</div>
  </div>
</div>

Add New Contact – Backbone.View and Backbone.Model

We’ll write our first view addView¬†and load it inside div.abPanel. We can write our custom view by extending¬†Backbone.View.extend()¬†method and¬†can keep our templates either into a same page or can¬†load it from a separate html file. In this case, we’ll simply wrap our template in <script>¬†tag by giving it a special type and an id:

addressbookMVC/index.html – addNewContact Template

<script type='text/template' id='addContactTemplate'>
  <h2> Add New Contact</h2>
  <form id='frmAddContact'>
    <div>Full Name:</div> <input type='text' id='full_name' class='input' /> <span class='false full_name_error'></span><br />
    <div>Email Id:</div> <input type='text' id='email' class='input' /> <span class='false email_error'></span><br />
    <div>Phone:</div> <input type='text' id='phone' class='input' /> <span class='false phone_error'></span><br />
    <div>Address:</div> <textarea id='address' class='textarea'>
    <input type='submit' value='Save Contact Details' class='button' />
    <span class='success'></span>
    <input type='hidden' id='id' class='input' />
  </form>
</script>

Backbone View allows us to specify custom methods and properties but there are some predefined attributes you should use to simplify the flow and maintain the unity between all backbone apps.
el – specify the DOM element selector where you want to load your template within a page. In our case its div.abPanel.
template РThe _.template method in Underscore compiles JavaScript template into function which can be evaluated for rendering.
initialize – The constructor to keep a piece of code to be executed while creating an instance of a view.

Below is our AB.addView backbone view which compiles the template mentioned above  and load it into el. 

addressbookMVC/js/script.js – addNewContact View

AB.addView = Backbone.View.extend({
  el: 'div.abPanel',
  template: _.template($('#addContactTemplate').html()),
  initialize: function () {
    _.bindAll(this, 'addContactPage');
  },
  addContactPage: function () {
    this.$el.html(this.template());
  }
});

In above code, we have used the _.bindAll method in Underscore which fixes the loss of context for this within methods. So we have to specify all those method names wherein we’ll use this.any_method or this.any_property i.e. this.$el, this.template etc.

In backbone.js, there is no need to grab elements the jquery way and attach some events to them. There is a special attribute events¬†which allows us to attach event listeners to either custom selectors or directly to el¬†if no selector is provided. It takes the form¬†{‘eventName selector’ : ‘callbackMethod’},¬†So¬†we can attach the submit event to our <form> in order to prevent the default form submission and fetch the form data. And once we get the data, we can simply call model.save() method to save the record into the DB which invokes Backbone.sync function every time we attempt to read or save a model to the server by making a RESTful JSON request.

Lets write our contactModel first. Notice that if a passed JSON data to model.save() contains an id key then a method name will be update in model.sync() else it will be create.

addressbookMVC/js/script.js – Contact Model

AB.contactModel = Backbone.Model.extend({
  sync: function (method, model, options) {
    if (method === 'create' || method === 'update') {
      return $.ajax({
        dataType: 'json',
        url: '../php/addNewContact.php',
        data: {
          id: (this.get('id') || ''),
          full_name: (this.get('full_name') || ''),
          email: (this.get('email') || ''),
          phone: (this.get('phone') || ''),
          address: (this.get('address') || '')
        },
        success: function (data) {
          // put your code after the contact is saved/updated.
        }
      });
    }
  }
});

Now we’ll create an instance of above model in our view and call the save() method.

addressbookMVC/js/script.js – addNewContact View

AB.addView = Backbone.View.extend({
  events: {
    'submit form#frmAddContact': 'addContact'
  },
  addContact: function (event) {
    var full_name = $('#full_name').val(),
        email = $('#email').val(),
        phone = $('#phone').val(),
        address = $('#address').val(),
        id = $('#id').val();
        
    if (id === '') {
      var contactmodel = new AB.contactModel({
        full_name: full_name,
        email: email,
        phone: phone,
        address: address
      });
    } else {
      var contactmodel = new AB.contactModel({
        id: id,
        full_name: full_name,
        email: email,
        phone: phone,
        address: address
      });
    }
    contactmodel.save();
    return false;
  }
});

List contacts – Backbone.View & Backbone.Collection

Usually we make an AJAX request to fetch all the data in JSON format but there is a special method collection.fetch() available to fetch the default set of models for the collection from the server based on the url¬†defined in the collection. We’ll write our collection by specifying the model and the url:

# addressbookMVC/js/script.js – Contacts Collection

AB.contactsCollection = Backbone.Collection.extend({
  model: AB.contactModel,
  url: '../php/listContacts.php'
});

And we’ll put the templates in index.html:

addressbookMVC/index.html – listContacts Template

<script type='text/template' id='listContactsTemplate'>
  <h2>List Contacts</h2>
  <table id='contactsGrid' width='100%' border='1' cellspacing='1' cellpadding='5'>
    <tr>
      <td width='25%'><b>Full Name</b></td>
      <td width='25%'><b>Email ID</b></td>
      <td width='15%'><b>Phone</b></td>
      <td width='25%'><b>Address</b></td>
      <td width='10%' align='center'><b>Action</b></td>
    </tr>
    <% if ($.isEmptyObject(contacts)) { %>
      <tr><td colspan='5'>No Record Found</td></tr>
    <% } else {
        $.each(contacts, function () { %>
          <tr data-id=<%= this.id%>>
            <td><%= this.full_name%></td>
            <td><%= this.email %></td>
            <td><%= this.phone %></td>
            <td><%= this.address %></td>
            <td align='center'><a>Edit</a> | <a>Delete</a></td>
          </tr>
    <%  });
       }
    %>
  </table>
</script>

And then call the fetch() within its View:

addressbookMVC/js/script.js – listAllContacts View

AB.listView = Backbone.View.extend({
  el: 'div.abPanel',

  template: _.template($('#listContactsTemplate').html()),

  initialize: function () {
    _.bindAll(this, 'listContactsPage', 'render');
  },

  render: function (response) {
    var self = this;

    this.$el.html(this.template({contacts: response}));
  },

  listContactsPage: function (querystring) {
    var self = this;

    AB.contactscollection.fetch({
      data: querystring,
      success: function (collection, response) {
        self.render(response);
      }
    });
  }
});

Search contacts – Backbone.View and Backbone.Collection

I will not explain this section in detail because it is pretty much similar when it comes to load a searchContacts template into a page and to show all the contacts based on the search criteria, we can reuse the same method listContactsPage({full_name: ‘alice’}) from AB.listView class. We’ll get it once we go through the codebase. Lets move on to Backbone.Router.

Backbone.Router

In Backbone, routers are used to help manage application state and for connecting URLs to application events. This is achieved using hash-tags with URL fragments, or using the browser’s pushState and History API. Some examples of routes may be seen below:
http://addressbook.com/#addNewContact
http://addressbook.com/#editContact/6
When all of our routers have been created, and all of the routes are set up properly, call Backbone.history.start() to begin monitoring hashchange events, and dispatching routes. Inside run method, we are updating the hash to #add_new_contact and triggering it immediately so that renderAddNewContactPage will be called immediately once the page is loaded.

# addressbookMVC/js/script.js – Backbone.Router

var AB = {
  run: function () {
    this.addview = new this.addView();
    this.listview = new this.listView();
    this.searchview = new this.searchView();
    this.contactscollection = new AB.contactsCollection();
    this.router = new this.Router();
    Backbone.history.start();
    this.router.navigate('add_new_contact', {trigger: true});   
  }
};

AB.Router = Backbone.Router.extend({
  routes: {
    'list_contacts': 'renderListContactsPage',
    'add_new_contact': 'renderAddNewContactPage',
    'search_contacts': 'renderSearchContactsPage',
    'edit_contact/:id': 'renderEditContactPage'
  },

  renderAddNewContactPage: function () {
    AB.addview.addContactPage();
  },

  renderListContactsPage: function () {
    AB.listview.setElement('div.abPanel');
    AB.listview.listContactsPage();
  },

  renderSearchContactsPage: function () {
    AB.searchview.searchContactsPage();
  },  

  renderEditContactPage: function (id) {
    AB.addview.addContactPage(id);
  }
});

Summary

I simply love to use Backbone.js in my projects, its amazing.

Download the source code from github

And do share your thoughts in the comment section below.

Updates:

Since a very long time, I wanted to try out Require.js in my projects and what could be the best way than to rewrite the addressBook in backbone.js and require.js again.
So here it is: addressBook in Backbone.js and Require.js

Happy Hacking ūüôā

jQuery video series: The making of Address book


Hello friends,

I really enjoyed making these¬†screen-casts¬†for the first time and it was an awesome experience. I personally believed that to learn any new technology or library, one has to get acquainted with the basics and write a small generic application to get the hang of it. Below are the¬†things¬†that I’ve covered in this video series:

The Addressbook in jQuery
The Addressbook in jQuery
  • Basic Instinct¬†
    • Why to use jQuery and¬†Where to get it from?
    • $ and beyond (overriding $)
    • Difference between document.ready and window.load
    • Selectors, dom traversing and events
    • Ajax and writing custom jquery function
  • Welcome to the jungle of jQuery
    • Selectors to fetch the values of form elements
    • Ajax calls to save the data (using php and mysql)
  • A list apart
    • List all the contacts in a tabular format
    • Delete contact functionality
  • Searching through
    • Search contacts by name or email

You can download the code from github.com.

References: 

P.S. There are many ways to improve the code. You can add edit-contact functionality or you can avoid unnecessary ajax calls to load forms/grids by simply keeping them in index.html and show/hide on demand instead of calling `$.load()` every time. Plus, its not always a valid choice to use only jQuery to write a Single Page app as there are lots of good MVC or MVVM frameworks available that can save your substantial amount of time and effort.

socialFlair – Stackoverflow like User Flairs to showcase your Social Profiles


Hurrey,

I’ve released one more Opensource project, socialFlair¬†on github today. It is a simple jQuery plugin which lets you embed social flairs in your about-me page of ¬†your personal website or blog. Currently, it is available for Twitter, Github and Facebook. This is how it looks:

socialFlair
socialFlair

Update1: 

Live Demo: http://jsfiddle.net/codef0rmer/wzpNB/embedded/result/

Select grouped checkboxes in jQuery


Have you ever noticed in gmail where we  select/deselect all the visible mails with the help of a checkbox given on top? Now it is possible to do it in a single line of javascript. For that purpose, you need to use jQuery.

Suppose you have a bunch of checkboxes having same id as show below:

Parent Checkbox:

<input type="checkbox" id='parent_id' />

Grouped Checkboxes:

<input type="checkbox" id='result_data_id' name="result_data_1" value="1" />
<input type="checkbox" id='result_data_id' name="result_data_2" value="2" />
<input type="checkbox" id='result_data_id' name="result_data_3" value="3" />
<input type="checkbox" id='result_data_id' name="result_data_4" value="4" />
<input type="checkbox" id='result_data_id' name="result_data_5" value="5" />

Now we have to attach onchange event to our parent checkbox this way:

$('#parent_id').change(function () {
$('input[id=result_data_id]').attr('checked', this.checked);
});

That’s it. Isn’t that simple and fun? BTW, do not forget to drop a comment.