JavaScript Events: Part 1

January 2nd, 2012 Filed under: Tutorials by Andrew

With modern JavaScript libraries such as jQuery, many of the painful browser differences have been completely abstracted for us. This may not necessarily be a good thing. jQuery makes assigning event handlers so trivial, that most developers have no idea how the actual JavaScript event model works. As such, in the first part of this series I would like to take the opportunity to discuss how to work with the event model in raw form, and build our own cross browser event handling utility to gain a better understanding of how other libraries handle events under the hood. Along the way, we’ll also learn some other useful techniques that can be applied anywhere. By the time we are finished, we should have the following utility.

Before we begin coding, let’s go over some of the basics of working with events. Event assignment comes in two flavors, DOM Level 0, which is probably the most familiar, and DOM Level 3, which offers some additional features. DOM Level 0 basically consists of assigning an event handler as a property of the DOM element:

// DOM Level 0 event model
element.onclick = function(){
	// do something
};

With raw JS, this is probably the most widely used technique of event assignment. It’s straightforward and works across all browsers. Along the way, a much more robust technique was developed which offered new features such as event bubbling and capturing. With the DOM Level 3 event model, event handlers are assigned through the addEventListener method:

// DOM Level 3 event model
element.addEventListener(‘click’, function(e){ }, false);

This technique offers several huge advantage over the previous. First, we can assign multiple event handlers of the same event type, second, we have the ability to remove event handlers at will, and third, we can apply the use of event bubble and capture phases. The main drawback of this model is the fact that IE chose to implement it’s own proprietary way of assigning events, and the differences are quite drastic.

Internet Explorer’s non-compliance is probably why the DOM Level 0 event model is still widely favored. In IE, we are required to use the attachEvent method to assign events. The event name must always be prefixed with an “on” (onclick, onfocus, etc.), and the capture phase isn’t supported. The other major drawback is that the event object isn’t passed through the handler’s argument, instead, it is a property of the window object, having it’s own proprietary property and method interface.

// IE's event model
element.attachEvent(‘onclick’, function(){
    var event = window.event;
});

Now that we understand the basics, let’s start thinking about how to structure our code, and what specific interface we would like for our utility. For starters, we will need two methods, one to attach events, and the other to remove events. Also, we should use an object namespace to hold our methods to minimize global variables. If you do a quick search for a cross browser event script, you will most likely find something similar to this example:

// a simple event handling script
function addEvent(element, event, handler){
	// standard event model
	if(document.addEventListener){
		element.addEventListener(event, handler, false);

	// IE event model
	}else{
		element.attachEvent('on' + event, handler);
	}
}

function removeEvent(element, event, handler){
	// standard event model
	if(document.removeEventListener){
		element.removeEventListener(event, handler, false);

	// IE event model
	}else{
		element.detachEvent('on' + event, handler);
	}
}

This is a very basic implementation, and although it enables us to use the same interface across all browsers, we can do a much better job. For example, we should “fix” IE’s event model to match standard browsers by applying the following points:

  1. Normalizing the event object so that it is passed as an argument to the handler function instead of calling it from the window.
  2. Fix IE’s incorrect reference of the “this” keyword. In IE, it incorrectly refers to the window object, it should refer to the element the event is assigned to, as in other browsers.
  3. Normalize IE’s event properties so that they can be called in the same manner as other browsers. This includes stopPropagation(), preventDefault(), and the target property.

And while we’re fixing some of IE’s intricacies, we can apply some improvements to the existing event model. One such pitfall is the fact that handlers must be removed in the same exact way that they were assigned. For example, if we assigned an event to a “doSomething” handler as such:

element.addEventListener(‘click’, doSomething, false);

we must remove it in the same exact manner:

element.removeEventListener(‘click’, doSomething, false);

Not supplying the “doSomething” handler, or setting the capture phase to true will prevent the handler from being detached. Because of this pitfall, anonymous functions can not be removed, as they do not posses an identity. It would be a big plus if we can simply remove handlers as such:

element.removeEventListener(‘click’);

or

element.removeEventListener();

this would give us the ability to detach handlers that were supplied as anonymous functions.

Now that we’ve covered all our requirements, we can begin writing our code. I want to structure the utility by taking advantage of the module pattern. We will need to use some complex underlying logic, broken up across many functions that I want to be hidden away from the interface. With the module pattern, we can effectively create private and public methods. If you’re not familiar with the module pattern, below is an example of a basic object.

// module pattern
var module = (function(){
    // private members
    var privateMethod1 = function(){
		// do something
	};

	var privateMethod2 = function(){
		// do something
	};

    // public members
    return {
        method1: function(){ },
        method2: function(){ }
	};
})();

Basically, all the methods are wrapped within an immediately executing function. Any encapsulated methods are hidden away from access due to the function’s closure and are effectively made private, while we expose our public methods by returning them in an object literal. As such, I want two methods exposed in our interface, the add method, and the remove method, both of which can be accessed via the Event name space. When we’re finished, we will use our methods by calling Event.add() and Event.remove().

// basic app structure
var Event = (function(){
	return {
		add: function(element, event, handler){
			// standard compliant browsers
			if(typeof document.addEventListener === 'function'){
				element.addEventListener(event, handler, false);

			// IE
			}else{
				element.attachEvent('on' + event, handler);
			}
		},
		remove: function(element, event, handler){
			// standard compliant browsers
			if(typeof document.removeEventListener === 'function'){
				element.removeEventListener(event, handler, false);

			// IE
			}else{
				element.detachEvent('on' + event, handler);
			}
		}
	};
})();

That’s it for this week. In the next part of this series, we will look at how to improve our method and add some more advanced functionality.

Testing for NaN

December 30th, 2011 Filed under: Tips and Tricks by Andrew

Quick tip, Number() is a useful method for converting a numeric string value into an integer. If the passed value turns out to be non-numeric, Number will return NaN. Unfortunately, testing if the returned value is NaN is somewhat convoluted as NaN does not equal NaN. Confused? Ponder the following:

// returns NaN
console.log(Number(‘abc’));
// returns false, huh?
console.log(Number(‘abc’) == NaN);
// returns true, I’m confused
console.log(Number(‘abc’) != NaN);
// returns false, WTF?
console.log(NaN == NaN);

/* so how can I test for NaN? */
// returns false
console.log(Number(‘abc’) == false);
// also returns false, so no use
console.log(Number(‘abc’) == true);
// returns true, we’re getting somewhere
console.log(Number(‘5’) != false);
// returns false, oh well, this test is no use
console.log(Number(‘0’) != false);

/* ok, maybe we can test for typeof? */
// returns number as expected
console.log(typeof Number(‘5’));
// returns number, what the heck?
console.log(typeof Number(‘abc’));
// returns number? OMG! WTF?
console.log(typeof Number(NaN));

So, now that we’re thoroughly confused, we’ve discovered that NaN is a number, and NaN != NaN. So how the heck do we test for an invalid number? Luckily, we have the isNaN() method at our disposal, which outputs true if the passed string is NaN, and false if it is a number.

// true, yay!
console.log(isNaN(‘abc’));
// false, yay!
console.log(isNaN(‘123’));

CSS Modal Centering

December 26th, 2011 Filed under: Tips and Tricks, Tutorials by Andrew

Today I would like to give out a quick tip regarding modal dialogs. As we all know, one of the main characteristics of a modal is the fact that it is centered on screen. I’ve observed many different methods accomplishing this task, but none are as simple as the pure CSS method that I usually use. If you’re not familiar as to why exactly it’s difficult to center a modal, the reason being is that it is an absolutely positioned element. The usual trick of margin:0 auto; doesn’t work in this situation.

First, let’s review some of the usual techniques. The first, and most popular, is using JavaScript to calculate the width and height of the window, then assigning the appropriate top and left positions. The main disadvantage of this technique is that the top and left positions are based on the dimensions of the window when the modal is first rendered, if the window is re-sized, the values need to be recalculated. The second technique is CSS based and involves applying a left value of 50%. This will align the left edge of the modal with the exact center of the screen. To then center align the element, we apply a negative left margin that is half the pixel width of the modal. The main benefit of this method is that no scripting is involved. The major drawback is that this method doesn’t work with elements of unknown width. The width value needs to be explicitly set as the negative margin is based off of it.

My technique solves for the disadvantages of the previously mentioned methods. It works without scripting, it works when the window is re-sized, and it works with elements of unknown width. It is similar to the CSS method I’ve mentioned previously, but instead of applying a negative margin, we apply a right value of 50% to a relatively positioned child element. This means that we need to introduce a new element to wrap our modal, which is strictly used for positioning purposes:

<style>
.modal{position:fixed; z-index:9999; left:50%;}
</style>

<!-- this is used to position the modal -->
<div class="modal">
</div>

As you can see, this is exactly the same as the previously mentioned technique, but the difference comes in when we add the inner element that will actually apply the theme to the modal:

<style>
/* base */
.modal-position{position:relative; right:50%;}
/* theme */
.modal-position{padding:10px; background-color:#fff;
    border:5px solid #333; border-radius:5px;}
</style>

<div class="modal">
    <!-- this styles the modal content and nudges it to the center -->
    <div class="modal-position">
        <p>Lorem ipsum dolor ist amet.</p>
    </div>
</div>

You can take a look at a live example here.

The main advantage of this method is that it is a very modular approach and leads to easy re-usability since it works with unknown widths. If you’re looking for an approach to vertically center the modal, that’s a whole different story. There’s no easy way to accomplish this with only CSS. I’ve found it that 90% of the time we can get away with just setting the top value to about 150 or 200px, so that the modal is always above the fold. Visually it looks nice and most users don’t even notice the fact that the modal is not perfectly vertically aligned.

JavaScript Cookie Utility

December 23rd, 2011 Filed under: Tutorials by Andrew

Cookies are an important aspect of the dynamic web, unfortunately, manipulating cookies with JavaScript is about as much joy as getting your hand stuck in a car door. The problem comes from the strange interface used to write and retrieve cookies. Essentially, cookies are accessed through the document.cookie property, in which you either assign or retrieve a string value. For example to assign a cookie, we would write:

document.cookie =  ‘mycookie=test; '
    + 'expires=Sat, 24 Dec 2011 00:31:06 GMT; '
    + 'path=/; domain=andrewleeart.com'

To retrieve a cookie, we simply assign the document.cookie property to a variable, which returns a serialized string value. A problem arises in the fact that the string contains all the key value pairs under our domain. This means that we’re the ones tasked with parsing the string and finding our desired key, then retrieving it’s corresponding value. For example, below is what a typical cookie string looks like.

‘key1=value1; key2=value2; key3=value3; key4=value4’

Just from this short writeup you can observe a multitude of issues:

  1. The property syntax needed to create a cookie is difficult to remember, and any slight typo in this format will result in failure.
  2. A great deal of work is required to retrieve a cookie key value.
  3. I failed to mention how to actually delete a cookie, but it involves re-creating a cookie with an existing name and setting it’s expiration to a date to the past. This is more wonky behavior and presents code redundancy.

Hence the importance and need of having a cookie utility. As an exercise, I wrote my own cookie interface, which is pretty solid. I’ll briefly review some of it’s features and usage as I hope others find this script useful and helpful. You can download the script from my Github at http://github.com/drewlee/cookie_utility.

The cookie utility affords us a set of three methods under the “Cookie” namespace: set, get, and remove.

Creating a New Cookie
The simplest way is to create a cookie with only a key value pair.

Cookie.set(‘name’, ‘value’);

The problem here, is that the cookie will get trashed as soon as the user closes the browser, so you’ll probably want to issue a longer lifespan. As such, the method allows you to specify additional properties through an object literal:

Cookie.set('useremail', 'john@johnny.com', {
   expires: new Date(new Date().getTime() + (1000*60*60*24)),
   path: '/',
   domain: 'mail.mysite.com'
});

In the example above, the expiration date is set for 24 hours. Use a similar method to setting your dates. Here, I retrieve the current date and then add 24 hours to it. Remember that dates can be set through milliseconds, so here I multiply 1000 milliseconds by 60 seconds, by 60 minutes, by 24 hours, which results in the number of milliseconds in 24 hours. Behind the scenes, the date gets converted to a UTC string. Above, the path and domain settings are also specified. Note that the subdomain is set under “mail.mysite.com”, which means that this cookie can only be read from the “mail” subdomain. To give access to all subdomains, specify “mysite.com”. The default is always the subdomain under which the cookie was created. Additionally, you can specify the “secure” setting by giving it a boolean true value. The method returns a true if the cookie is successfully created, false if the operation fails.

Retrieving a Cookie Value
Retrieving a cookie is straight forward, simply run the Cookie.get() method, passing the cookie’s name as an argument. The function will return the value as a string, if the name cannot be found, the function will return a boolean false.

Cookie.get(‘name’);

Deleting a Cookie
To delete a cookie, simply call the Cookie.remove method and pass the cookie’s name as an argument. If the cookie is successfully removed, a boolean true is returned. If the operation fails, a boolean false is returned.

Cookie.remove(‘name’);

Optionally, you can specify the path and domain through an object literal. Reason being is that I’ve encountered situations where the path and domain need to be set to the same exact values as when the cookie was initially created, otherwise the delete operation fails.

Cookie.remove('useremail', {
   path: '/',
   domain: 'mail.mysite.com'
});

Behind the scenes, the date value gets set to 30 days in the past, which results in the browser trashing the cookie.

One brief point I would like to mention is the fact that many other cookie scripts use the split method to convert the key value pairs into an array off of the “; ” separator. The there are usually a set of for loops that further split the values on the “=”, and then use this array to retrieve the cookie’s value. Fortunately, I do not use any of this needless iteration and simply use a regular expression. Take a look at the script for the full details if you are curious.

As an excellent exercise, I recommend that everyone attempts to write their own cookie utility to gain a deeper understand how to work with JavaScript cookies. As always, feel free to contact me with any questions.

Tabulous jQuery Plugin

September 5th, 2011 Filed under: News by Andrew

I finally completed documentation for my jQuery tab plugin. More information and examples can be found at my github page. You can download the code from the main branch and also view the tabulous homepage here.

Sitepoint’s Test Your CSS Skills 39

August 30th, 2011 Filed under: Tips and Tricks by Andrew

I took a stab at an older CSS quiz from the Sitepoint forums. The challenge was to add arrow icons automatically to menus that contain flyouts. See the full details at the Sitepoint forum. See my solution here.

Structuring Pagination Dots

August 29th, 2011 Filed under: Tips and Tricks by Andrew

pagination dots

Pagination dots seem to have become all the rage. What started as a common interface element of mobile applications has worked it’s way into the web, especially often seen in mobile websites. This component seems fairly simple and straightforward to build, but features one deceptive problem. In this post I intend to explore the best approach in building this interface and provide a nice code base for easy reusability.

First let’s explore the markup we should use to construct the pagination dots. Since this is somewhat of a navigational element, the most obvious approach is to utilize an unordered list. Since this component may, or may not be interactive, the best option is to nest an anchor tag inside each list item for flexibility. Below is an outline of the overall HTML structure. I’ve also created a class name to denote the active dot and wrapped the unordered list with a div element that will render the bar housing the pagination component.

<div class="pg-dot-panel">
    <ul class="pg-dots-row">
        <li class="pg-dot">
            <a href="#"></a>
        </li>
        <li class="pg-dot">
            <a class="pg-active" href="#"></a>
        </li>
        <li class="pg-dot">
            <a href="#"></a>
        </li>
        <li class="pg-dot">
            <a href="#"></a>
        </li>
        <li class="pg-dot">
            <a href="#"></a>
        </li>
    </ul>
</div>

Now on to the CSS markup. First of all, our pagination dots need to be centered on the page. We typically center elements by defining an explicit width and assigning it left and right auto margins. But here’s the problem, our pages can contain any number of dots, the number which is not known. Sure, we can use JavaScript to calculate the number of list items and then assign a width based on that amount, but the best solution should not be dependent on scripting and should be elegant enough to accommodate any number of dots. Now I would suggest you try to think about the possible solution for this little problem. When you have and idea, or are completely stumped, read on to learn how it is possible to center an element without applying an explicit width.

What I discovered when trying to solve this problem is that there is one HTML element that does not require a width in order to be centered. Want to know which one? It’s our good old friend the TABLE. Now you’re probably thinking, “Are you suggesting we use a table? Tables are evil!” No, not directly. Through the magic of CSS, we can apply a display of table to any element so that it emulates the behavior of a table. From here, the rest is easy. We can now use the same idea to style the inner elements and apply displays of tables cells to the list items. No need to use floats!

.pg-dots-row {
    display:table;
    margin:0 auto;
}
.pg-dot{
    display:table-cell;
    padding:0 7px;
}
.pg-dot a{
    display:block;
    height:14px;
    width:14px;
    background-color:#aaa;
    -webkit-border-radius:7px;
    -moz-border-radius:7px;
    -o-border-radius:7px;
    border-radius:7px;
}

Also note that with the power of CSS3, we can create the dots without using any images. If you only need to support the latest versions of modern browsers that are HTML5 enabled, then you are done. But, if you need to support IE 6, IE 7, or IE 8, you have yourself a whole lot more work to do. In that case we need to take a different approach to building these elements because earlier versions of IE do not support display table or table-cell, and IE 8 does not support border radius properties. The next approach is a little bit dirtier and not as elegant, but gets the job done. In this case we utilize the display inline-block property. This is a weird hybrid display that takes on the properties of a block, but lies inline such as a span element. Remember, span elements can be centered within a block level element, and they do not break onto new lines. With that said, here is our new CSS.

.pg-dots-row{
    display:block;
    height:14px;
    margin:0;
    text-align:center;
}
.pg-dot{
    display:inline;
    padding:0 7px;
    vertical-align:top;
}
.pg-dot a{
    display:inline-block;
    height:14px;
    width:14px;
    background-color:#aaa;
    overflow:hidden;
    -webkit-border-radius:7px;
    -moz-border-radius:7px;
    -o-border-radius:7px;
    border-radius:7px;
}

The main difference here is that the UL element stretches the width of the page instead of shrink wrapping. Keep this in mind if you are doing any visual styling. Also since we’re applying inline displays, our list items may contain inconsistent space between each item due to white space and line heights, as well as inconsistent vertical alignment. Usually playing around with line heights and font sizes remedies this. This is why I’ve used the following markup to kill any white space between each list item.

<ul class="pg-dots-row">
    <li class="pg-dot"><a href="#">
        </a></li><li class="pg-dot"><a href="#" class="pg-active">
        </a></li><li class="pg-dot"><a href="#">
        </a></li><li class="pg-dot"><a href="#">
        </a></li><li class="pg-dot"><a href="#">
    </a></li>
</ul>

Also we need a fallback for browsers that do not support border radius.

/* IE 6, IE 7, and IE 8 */
.ltie9 .pg-dot a{background:url(pg_dots.gif) no-repeat 0 0;}
.ltie9 .pg-dot a:hover{background-position:-32px 0;}
.ltie9 a.pg-active,
.ltie9 a.pg-active:hover{background-position:-16px 0;}

As a side note, I’ve used a modified version of Paul Irish’s browser targeting technique to target all versions of IE prior to 9.

<!--[if lt IE 9]><body class="ltie9"><![endif]-->
<!--[if IE 9]><!--><body><!--<![endif]-->

This is a pretty neat method that does not rely on any JavaScript sniffing or CSS hacks. You can download all the HTML and CSS code for this tutorial from GitHub. You will find 3 HTML files, each suited to your specific needs. The file pgd_html5.html is for modern browsers only, which utilizes display table property. Use pgd_cross_browser.html if you need a cross browser solution. The file pgd_fallback.html is a hybrid that utilizes display table for modern browsers and display inline block for older browsers.

Sitepoint’s Test Your CSS Skills 40

August 27th, 2011 Filed under: Tips and Tricks by Andrew

I decided to take on one of the CSS challenges featured regularly on the Sitepoint forums. The challenge was to vertically and horizontally center align a random set of images of variable sizes within a 200px by 200px overflowed hidden container. See the details on the Sitepoint Forum, and my results page here.

Focusify jQuery Plugin

August 13th, 2011 Filed under: Tips and Tricks by Andrew

Recently I ran into an interesting problem while developing some forms for a project. The designer specked out the form’s behavior so that the label for each corresponding field changed color when the field was in focus.

focusify spec

I think this is a great visual cue to the user, and I didn’t think that it would present some problems while reviewing the comps a few weeks earlier. No problem I thought, I can easily do this with CSS. But once I began looking for a solution, I realized that this simple requirement would require a little bit of work. Obviously I didn’t want to resort to JavaScript for such a simple piece of interaction. I was hell bent on utilizing CSS, and came up with a few ideas. I knew that I would need to exploit the :focus pseudo-class. The problem with CSS is that it works from top down, parent to child hierarchy. You cannot style a parent element based on its child element’s state, nor can you do the same with a preceding element based on the following element’s state. So now I was trying many different combinations of coding the label and input relationship. The best possible solution I came up with was utilizing an adjacent sibling selector (element + element). But again, the problem with this selector is that the target is the element following a qualifier element, so the state of the qualifier determines the state of the target. In the usual form, the label comes before the field element which gains the focus, so the standard structure would not work here. I had to rearrange the code structure so that the label followed the input, this way the input’s state determines the label’s state (input:focus + label).

.fy-wrap .focus-hook:focus + label{background-color:#FFFCBD;}

<div class="fy-wrap">
    <input id="fy_txt_a_1" class="fy-txt focus-hook" type="text" />
    <label for="fy_txt_a_1">First Name:</label>
</div>

Visually, this worked like a charm, but the fact that now the HTML structure didn’t match the visual hierarchy bothered me quite a bit. In addition, there are several major cons to using this technique:

  1. Does not work in IE 6 and IE 7, very buggy in IE 8. The :focus pseudo selector isn’t supported in these browsers, neither is the adjacent sibling selector.
  2. Ugly and unclear CSS selectors.
  3. Markup doesn’t semantically match the visual order of elements.
  4. Even more ugly workarounds are required when the label is positioned above the field. This doesn’t lead to easily reusable code.

focusify textarea

You can view an example of this CSS technique here.

After weighing the good with the bad, I had little choice but to go with a JavaScript based solution. Luckily, I devised a jQuery plugin that took care of the problem with one line.

$('#fy_form_1').find('.focus-hook').focusify();

The plugin simply appends a class to the adjacent label when it’s corresponding field is in focus, and removes the class when the field blurs. With some optional settings, we can even target the parent element for some fancier effects.

focusify glow

$('#fy_form_2').find('.focus-hook').focusify({parent: '.fy-wrap'});

div.infocus{
	-webkit-box-shadow:3px 3px 10px #bbe9ff, -3px -3px 10px #bbe9ff;
	-moz-box-shadow:3px 3px 10px #bbe9ff, -3px -3px 10px #bbe9ff;
	-o-box-shadow:3px 3px 10px #bbe9ff, -3px -3px 10px #bbe9ff;
	box-shadow:3px 3px 10px #bbe9ff, -3px -3px 10px #bbe9ff;
}
div.infocus label{border-color:#00aeef;}

We can even utilize a siblings selector and target non-adjacent sibling elements, and even target the parent element at the same time.

$('#fy_form_3').find('.focus-hook').focusify({
    parent: 'fieldset',
    sibling: 'label',
    classname: 'multi-focus'
});

Using the Focusify plugin, in combination with CSS, opens up an unlimited number of possibilities for form elements. I imagine we can even create some really neat show/hide interactions with CSS3 transitions. You can download and read the full documentation and demos for the plugin on my Focusify github page.

CSS3 Gradients and Animation

April 12th, 2011 Filed under: Tutorials by Andrew

CSS3 glossy buttons.

Another exercise utilizing some of the new CSS3 features. This example demonstrates the use of gradients, box shadows, and webkit animations. As illustrated, we can get some pretty sophisticated buttons without resorting to the use of images. While using a webkit based browser, you can view a glowing animation affect while focusing or hovering over a button. This is a nice little progressive enhancement touch for the savvy web surfer. View the CSS3 gradient and animation demo here.