Preventing JavaScript memory leaks with Dojo disconnect

One of the things with using event listeners in JavaScript is that it causes memory leaks. This causes the website performance to slow down after a while. A pretty good description of how and why these memory leaks happen is explained here.

In Dojo, attaching events to an element are done as below:

dojo.connect(dojo.byId('elementId'), 'onclick'/*or other events*/, scope/*context*/, function(event) {
   //do something when the event happens.
});

Eugene Lazutkin’s solution here on StackOverflow is perfect in my opinion. I’ve started using it in all the Dijit widgets I’ve been writing. I put this in the destroy() method of the widget.

dojo.forEach(handles, dojo.disconnect);

Understanding CSS box model properly

I’ve noticed a lot of developers are unsure of how the box model concept works with respect to how rectangles are created for elements laid out on the DOM tree. Although this document explains it pretty well, I built a small example which I feel also demonstrates the core concept reasonably well.

http://jsfiddle.net/thxzc/1/

4 main concepts to properly understand the box model:

  1. Content: The actual content area with a width and height specified to it.
  2. Padding: Clears space inside the rectangle created for the content rectangle above. This padding also assumes he background color of the content area.
  3. Margin: Clears space OUTSIDE the rectangle created for the content rectangle above.
  4. Border: The border wraps around the content area/rectangle + the padding. It may or may not have its own color.

The actual size of the node includes the padding and the border. So if the width of a node is 200px, and it has a 10px padding and 1px border around it. Its real width is 222px(width + paddingLeft + paddingRight + borderLeft + borderRight).

Execute the example again and you will see how the height and width of the content area are computed: http://jsfiddle.net/thxzc/1/

Removing duplicates from a JavaScript object array

Removing duplicates from a JavaScript array is an often encountered problem but after searching around, I have found very few good solutions to this. I wrote a small program but I realized that my solution had a O(n2) complexity. So I asked on twitter if someone knew of a better solution:

http://twitter.com/#!/vikasrao/status/77134502132064256

My friend pointed out that I can use a map. Since a JavaScript object is essentially a map. I came up with:

var arr = [
    { name: "a", age: 24},
    { name: "b", age: 25},
    { name: "a", age: 24},
    { name: "b", age: 25}
];

var newarr = [];
var unique = {};

dojo.forEach(arr, function(item) {
    if (!unique[item.age]) {
        newarr.push(item);
        unique[item.age] = item;
    }
});

console.log(dojo.toJson(newarr)); //prints [{"name":"a","age":24},{"name":"b","age":25}]

Here’s a JsFiddle link for the above code: http://jsfiddle.net/k6v3R/1/

I’m sure there are better solutions out there, but the complexity for the above code is O(n) although I’m thinking I don’t need to use both an object and an array to filter unique items.

JavaScript’s call and apply methods

A lot of people starting out with JavaScript are unsure of how JavaScript’s call() and apply() methods work. Some have a theoretical understanding of it but are not sure where they would use these powerful methods. I’m taking a stab below at explaining them:

Call and Apply are JavaScript methods used to pass the required object scope for a function to execute as expected.

The syntax for the JavaScript call method:

fun.call(object, arg1, arg2, ...)

The syntax for the JavaScript apply method:

fun.apply(object, [argsArray])

The main difference is that call() accepts an argument list, while apply() accepts a single array of arguments.

So if you want to call a function which prints something and pass an object scope for it to execute in, you can do:

function printSomething() {
    console.log(this);
}
printSomething.apply(new SomeObject(),[]); // empty arguments array
// OR
printSomething.call(new SomeObject()); // no arguments

Here’s a JsFiddle example below which explains how scope can be passed as required: http://jsfiddle.net/8uRXe/8/

The first alert window uses the scope of the dojo widget, while the second call without any scope passed to it uses the default window scope for the “this” object printed from the printSomething() method.

Dojo provides a hitch method which allows the programmer to pass around scope. This hitch method along with dojo.connect is probably what I love most about Dojo.

  var myObj = {
        foo: "bar"
    };
    var func = dojo.hitch(myObj, function() {
        console.log(this.foo);
    });
    func();

Here’s a small example continuing the earlier examples: http://jsfiddle.net/8uRXe/9/

Hopefully this sheds some light on these 2 powerful JavaScript methods.

Validate email address using JavaScript

In order to validate email address using JavaScript, use this simple check:

//where emailString is the string under consideration
if(/^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{3}$/.test(emailString)) {
 console.log("valid email address");
}

Breakdown of : /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{3}$

  • First part checks for alpha numberic characters, period, underscore and – are allowed.
  • Needs to have an @ sign
  • Last part can only contain 3 characters (a-z or A-Z) alphabets only, if you want anywhere between 2-4 characters, you can use {2,4} instead of {3} like I have.

UPDATE:
This below should work just as well as the above regex. For more useful info, check this out.

(/^[/\w/._-]+@[/\w/.-]+\.[a-zA-Z]{3}$/.test("vikas123@gmail.com"))

The above code in action here

Sorting birthdays received from Facebook’s graph API

While working with Friend lists using Facebook’s graph API, you may want to retrieve your friends and do something based on their birthdays. Here’s some sample code to sort your friends based on upcoming birthdays.

FB.api("/me/friends?fields=id,name,birthday,picture, link", dojo.hitch(this, function(response) {
    var birthdays = response.data; //list of friend objects from facebook
    var currentMonth = new Date().getMonth() + 1;
    var upcoming = [];
    dojo.forEach(birthdays, function(item) {
        if (item.birthday) {
            var bday = item.birthday;
            //if the birthday is after today
            if (currentMonth <= bday.substr(0, 2) * 1 && new Date().getDate() <= new Date(bday).getDate()) {
                upcoming.push(item);
            }
        }
    });

    //set the year to current year because of birth years being different.
    var year = new Date().getFullYear();
    upcoming = upcoming.sort(function(a, b) {
        return new Date(a.birthday).setYear(year) - new Date(b.birthday).setYear(year);
    });

    console.log(upcoming);//console log here, but do whatever you want with the sorted friends
}));