Monday, February 27, 2012

TextMate-like ⌘T & ⇧⌘T in Chrome Dev Tools & Other New Features

Introduction


For the past year or so I've used Google Chrome Canary as my primary web browser, however, about a month ago I temporarily switched to the stable build of Chrome because of some instability in the dev tools. I just recently switched back to Canary and was pleasantly surprised to see numerous new features in the dev tools there were very welcome indeed!

This post only covers the extreme latest in Chrome Dev Tools. There are so many more rich features that can be found. If you are interested about more helpful features you might be interested in a post I did last year entitled 7 Chrome Tips Developers & Designers May Not Know

If you are not familiar with the Canary build of Chrome, it is a extremely dev version of the browser. You should be cautious because it does update almost every day, but at the same time you get first in line to see all the new features. Unlike the dev or beta builds of Chrome you can actually install Canary side-by-side next to your Stable or Beta build of Chrome. This makes switching between versions very convenient.

The features I am about to describe are currently only available in the dev or canary builds of Chrome. If you have the Beta or Stable builds then you will not see these yet, but hopefully they'll make their way to those builds sooner than later. At least this will wet your appetite ;)

Scripts Explorer


A welcome change to the Scripts tab is a new Scripts Explorer (as seen in the below image). The previous way to navigate through the scripts of a webpage was to open a HUGE drop down containing tons of script files. Chrome kept reorganizing that huge drop-down list to make it more usable, but in the end it wasn't optimal when dealing with a site with lots of JavaScript fiels.

The new Scripts Explorer nicely separates the Scripts used on the webpage from the Content Scripts used in all of the Chrome Extensions you have installed in your browser. Historically, it was slightly annoying to see all those Content Scripts alongside your main JavaScript files in that huge drop down mentioned above. Again, over time Chrome moved those Content Scripts to the bottom of that drop down instead of intermingled, but this move to the Scripts Explorer is head over heals WAY better... YAY!

In addition, you can also choose to dock the Scripts Explorer to the left side of the dev tools (by clicking the little icon in the upper right) or have it auto-close when you are done finding what you need.


TextMate's ⌘T "Go to File" Feature


I don't know about you, but I'm one of those keyboard shortcut junkies, so I am always on the lookout on how to do my job without using the mouse. So, I was even more excited to see support for quickly finding a JavaScript file by only using the keyboard! Chrome call's this feature "Go to Script" and it is similar to what you may have experience in TextMate using ⌘T or maybe in Sublime Text 2 with ⌘P.

Since ⌘T is already reserved for creating a new tab in Chrome, they have chosen ⌘O for this feature. As soon as you type ⌘O you will see the following dialog displaying JavaScript files. As you type the list will filter to only the files that match what you are typing. You can arrow up or down to narrow the selection even more and then click "enter" to open that script file.


TextMate's ⇧⌘T "Go to Symbol" Feature


Now, if the "Go to Script" feature wasn't enough, there is also the "Go to Function", which is similar to the "Go to Symbol" feature of TextMate using ⇧⌘T or ⌘R in Sublime Text 2.

Once you are in a JavaScript file you can press ⇧⌘O to bring up the "Go to Function" dialog. This works in a very similar way as the "Go to Script" dialog as we saw previously, but this time instead of looking for files, it helps you track down functions! Navigating through your JavaScript files to find a specific function has now become a breeze!


Dock Dev Tools to the Right


The last feature that stood out to me as really cool, was the new setting to "Dock to right". Many people these days have a wide-screen monitor and having the dev tools docked at the bottom of the screen sometimes feels a little scrunched. If I have my browser maximized there is usually tons of room to the left or right of the website I am viewing.

Thankfully, with this new feature I can now choose to dock the dev tool to the right of my screen to give some breathing room for development!

Note: I undrestand some like to undock the dev tools to solve this issue, but I usually tend to like keeping them docked so this new feature is very handy for me.


In order to turn on this feature, you'll need to go into the Settings dialog. You can access this by clicking on the gear icon located at the bottom right of your dev tools. Once the dialog has been launched you should see a General section with the "Doc to right" option listed.


Conclusion


I find the the above JavaScript enhancements to the dev tools have really made navigating through scripts to be much more enjoyable. If you have noticed any other new features that I have missed please let me know. They keep cropping up all the time... which is AWESOME!

If you have Chrome Canary then you can start using the above features right way, otherwise they should make it in a Beta or Stable build in the near future.

Monday, February 13, 2012

Find the jQuery Bug #4: Animations Gone Wild

Introduction


In this open-ended series I'll be showcasing a snippet of buggy jQuery code that you might encounter, explain what the problem is, and then identify how you can easily resolve the issue.

You can view other posts in this series...

The Desired Feature


We want to take the following HTML and build a simple jQuery menu that will reveal sub-menus when you hover over each item.


The Buggy Code


The following code snippet is our first attempt at solving the problem, but there is a subtle error. Do you see it?


If you start playing with the menu it appears that it works as intended, but as you continue to use the menu an annoying problem raises its ugly head. If you move your mouse really quick from right to left over the menu you'll see the problem :(



The Underlying Problem


If you played with the example above you'll have noticed that if you interact with the menu really quickly side-to-side then the animations continue over and over and over again, even after you've moved off the menu completely!

At the root of the problem is an animation queue that has gotten out of hand. jQuery keeps an internal queue to help it know what animation to run next. When you take an element and call one of the animation methods ( .animate(), .slideDown(), .slideUp(), .slideToggle(), etc... ) what really happens is that effect gets added to the default "fx" animation queue that is attached to the element. As each effects completes jQuery will move on to the next effect in the queue until all animations are complete.

The magic that we need is to somehow interrupt the queue system. Thankfully, there is an API just for that and in the next section we will show how to use it.

A Solution


The solution to fix this problem is really simple and straightforward. In the words of Bob Newhart, we need the animation to STOP IT!

Of course, we can tell our program to STOP IT!, but they are usually to stubborn to heed to our warnings. Thankfully there is a method we can utilize in jQuery coincidentally called .stop() which we can use to solve our animation problem!

The following is the documentation from jQuery's website about the .stop() method that we will use.

.stop( [clearQueue] [, jumpToEnd] )
version added: 1.2
clearQueue - A Boolean indicating whether to remove queued animation as well. Defaults to false.
jumpToEnd - A Boolean indicating whether to complete the current animation immediately. Defaults to false.

.stop( [queue] [, clearQueue] [, jumpToEnd] )
version added: 1.7
queue - The name of the queue in which to stop animations.
clear - QueueA Boolean indicating whether to remove queued animation as well. Defaults to false.
jumpToEnd - A Boolean indicating whether to complete the current animation immediately. Defaults to false.

--http://api.jquery.com/stop/

As you see above there are 2 "overloaded" methods both with optional parameters. The important parameters that we will use to fix our code snippet are the clearQueue and jumpToEnd booleans. In order to get rid of the huge queue of animations on an element and complete whatever animation that was started all we need to do is pass true as both parameters... $element.stop( true, true )!


If you test out the code again below you'll notice that it works just as before, but this time the bug we found when moving our mouse quickly back and forth across the menu is now gone!



A Fancy Solution


If we wanted to get fancy, we could choose to update the animation easing algorithm. An easing algorithm is a mathematical equation that defines the animation path of an effect. Wow, that was a mouth full. Let's try that again, but this time with something visual. The following demo, from jQuery UI, is a great visualization of the various easing algorithms. Click the image to launch the jQuery UI Easing Demo and then click on each square to view the easing in action. I think my favorite is "easeOutBounce" ;)


With these easing options in mind, let's update our example above and use "easeOutBounce" instead of the default "swing" option that is default in jQuery.

NOTE: "The only easing implementations in the jQuery library are the default, called swing, and one that progresses at a constant pace, called linear."

-- http://api.jquery.com/slideDown


You might notice that I also added some other parameters to the .slideDown() and .slideUp() methods. All of the parameters are optional, but if we want we can provide our own values such as a duration, easing algorithm, and a callback to invoke when the animation is complete. In the code above, I trigger a custom event depending if the sub-menu was opened or closed and then I delegate to those events using the .on() method on line 19.

.slideDown( [duration] [, easing] [, callback] )
version added: 1.4.3
.slideUp( [duration] [, easing] [, callback] )
version added: 1.4.3
duration - A string or number determining how long the animation will run.
easing - A string indicating which easing function to use for the transition.
callback - A function to call once the animation is complete.

-- http://api.jquery.com/slideDown/ & http://api.jquery.com/slideUp/

Now you can test the changes we made. The effect may be too adventurous for most production business web applications, but the one I chose is just one of the many easing algorithms provided by jQuery UI that you can pick from. Also, if you are a math wizard you can come up with your algorithm!



Refactoring the Code


If you are anything like me you probably noticed a code smell. Much of the code from the previous examples looks very redundant. Let's take a stab at refactoring the code somewhat to reduce the "duplicated code" smell and made the code DRY (don't repeat yourself).

If you look through your vast code base, And notice code repeated here and there.
You might consider refactoring soon, Or you'll experience maintenance despair!

Previously we were passing two functions to the .hover() method. The 1st function parameter was to handle mouseover events and the other was to handle mouseout events. Thankfully, there is another "overloaded" version of .hover() that takes just 1 function parameter. This 1 function will be invoked on both mouseover events and mouseout events!


You may also notice that we are using a different method to actually perform the sub-menu animation. jQuery includes a .slideToggle() method that will either .slideDown() or .slideUp() depending on the state of the element.

The last thing to take into consideration is how to know which custom event to trigger. Previously I knew which event to trigger because opened was associated with .slideDown() and closed was associated with .slideUp(), but what about now? Thankfully that is easily solved by looking at the event object passed to the hover event handler. The event object has a type property which tells what type of event was originally fired. So, I can do something like this... e.type === "mouseover" ? "opened" : "closed" -- http://jsfiddle.net/ujsfH/

Conclusion


The key concept to remember here is that jQuery has an internal animation queue that you should be aware of. If you need to clear out that queue you can use the .stop() method. Also, you can modify the duration of animation, change the animation easing algorithm, and also respond to an event when the animation is complete.

Things we didn't cover in this post are how to create your own queue, how to create your own easing algorithm, how to modify the default animation duration, and several other concerns.

Until next time...

NOTE: The CSS I used as the base for the example menu above is a modified version from a blog post on @Kriesi's website. I removed the hover styles and replaced his jQuery code with mine for this Find the jQuery Bug post.

Wednesday, February 08, 2012

Regular Expressions in CoffeeScript are Awesome

Let's face it, regular expressions aren't for everyone. It takes a special breed of developer to actually enjoy writing regular expressions. Although I enjoy them, the developer that comes after me may find that they are cryptic and hard to read. And yes, sometimes it takes me a little bit to decipher through an old regular expression that I wrote a while ago.

Take for example, the following regular expression. Can you tell what it is doing? If so... then great, but what about the developers you work with?


One of the very cool things I like about CoffeeScript is that you can annotate your regular expressions! The following snippet of CoffeeScript compiles down to the equivalent JavaScript as seen in the above code sample. Yay ;)


Which code sample would you rather maintain? And more importantly which one would your co-worker be more likely to understand?

NOTE: The above email regular expression is very naive in it's logic. I based the above snippet from a Nettuts+ post entitled, 8 Regular Expressions You Should Know. There are much more comprehensive email regular expressions available on the internet, but I used the above one to show the value of annotation.

As a side note, some tools that I find helpful are Grant Skinner's Online RegExr Tool and I sometimes get inspiration for regular expressions at RegExLib.com. What tools or resources do you use for regular expressions?

Monday, February 06, 2012

Differences Between jQuery .bind() vs .live() vs .delegate() vs .on()

Introduction


I've seen quite a bit of confusion from developers about what the real differences are between the jQuery .bind(), .live(), .delegate(), and .on() methods and when they should be used.

If you want, you can jump to the TL;DR section and get a high-level overview what this article is about.

Before we dive into the ins and outs of these methods, let's start with some common HTML markup that we'll be using as we write sample jQuery code.


Using the Bind Method


The .bind() method registers the type of event and an event handler directly to the DOM element in question. This method has been around the longest and in its day it was a nice abstraction around the various cross-browser issues that existed. This method is still very handy when wiring-up event handlers, but there are various performance concerns as are listed below.


The .bind() method will attach the event handler to all of the anchors that are matched! That is not good. Not only is that expensive to implicitly iterate over all of those items to attach an event handler, but it is also wasteful since it is the same event handler over and over again.

Pros
  • This methods works across various browser implementations.
  • It is pretty easy and quick to wire-up event handlers.
  • The shorthand methods (.click(), .hover(), etc...) make it even easier to wire-up event handlers.
  • For a simple ID selector, using .bind() not only wires-up quickly, but also when the event fires the event handler is invoked almost immediately.

Cons
  • The method attaches the same event handler to every matched element in the selection.
  • It doesn't work for elements added dynamically that matches the same selector.
  • There are performance concerns when dealing with a large selection.
  • The attachment is done upfront which can have performance issues on page load.

Using the Live Method


The .live() method uses the concept of event delegation to perform its so called "magic". The way you call .live() looks just like how you might call .bind(), which is very convenient. However, under the covers this method works much different. The .live method attaches the event handler to the root level document along with the associated selector and event information. By registering this information on the document it allows one event handler to be used for all events that have bubbled (a.k.a. delegated, propagated) up to it. Once an event has bubbled up to the document jQuery looks at the selector/event metadata to determine which handler it should invoke, if any. This extra work has some impact on performance at the point of user interaction, but the initial register process is fairly speedy.


The good thing about this code as compared to the .bind() example above is that it is only attaching the event handler once to the document instead of multiple times. This not only is faster, but less wasteful, however, there are many problems with using this method and they are outlined below.

Pros
  • There is only one event handler registered instead of the numerous event handlers that could have been registered with the .bind() method.
  • The upgrade path from .bind() to .live() is very small. All you have to do is replace "bind" to "live".
  • Elements dynamically added to the DOM that match the selector magically work because the real information was registered on the document.
  • You can wire-up event handlers before the document ready event helping you utilize possibly unused time.

Cons
  • This method is deprecated as of jQuery 1.7 and you should start phasing out its use in your code.
  • Chaining is not properly supported using this method.
  • The selection that is made is basically thrown away since it is only used to register the event handler on the document.
  • Using event.stopPropagation() is no longer helpful because the event has already delegated all the way up to the document.
  • Since all selector/event information is attached to the document once an event does occur jQuery has match through its large metadata store using the matchesSelector method to determine which event handler to invoke, if any.
  • Your events always delegate all the way up to the document. This can affect performance if your DOM is deep.

Using the Delegate Method


The .delegate() method behaves in a similar fashion to the .live() method, but instead of attaching the selector/event information to the document, you can choose where it is anchored. Just like the .live() method, this technique uses event delegation to work correctly.

If you skipped over the explanation of the .live() method you might want to go back up and read it as I described some of the internal logic that happen.


The .delegate() method is very powerful. The above code will attach the event handler to the unordered list ("#members") along with the selector/event information. This is much more efficient than the .live() method that always attaches the information to the document. In addition a lot of other problematic issues were resolved by introducing the .delegate() method. See the following outline for a detailed list.

Pros
  • You have the option of choosing where to attach the selector/event information.
  • The selection isn't actually performed up front, but is only used to register onto the root element.
  • Chaining is supported correctly.
  • jQuery still needs to iterate over the selector/event data to determine a match, but since you can choose where the root is the amount of data to sort through can be much smaller.
  • Since this technique uses event delegation, it can work with dynamically added elements to the DOM where the selectors match.
  • As long as you delegate against the document you can also wire-up event handlers before the document ready event.

Cons
  • Changing from a .bind() to a .delegate() method isn't as straight forward.
  • There is still the concern of jQuery having to figure out, using the matchesSelector method, which event handler to invoke based on the selector/event information stored at the root element. However, the metadata stored at the root element should be considerably smaller compared to using the .live() method.

Using the On Method


Did you know that the jQuery .bind(), .live(), and .delegate() methods are just one line pass throughs to the new jQuery 1.7 .on() method? The same is true of the .unbind(), .die(), and .undelegate() methods. The following code snippet is taken from the jQuery 1.7.1 codebase in GitHub...


With that in mind, the usage of the new .on() method looks something like the following...


You'll notice that depending how I call the .on() method changes how it performs. You can consider the .on() method as being "overloaded" with different signatures, which in turn changes how the event binding is wired-up. The .on method bring a lot of consistency to the API and hopefully makes things slightly less confusing.

Pros
  • Brings uniformity to the various event binding methods.
  • Simplifies the jQuery code base and removes one level of redirection since the .bind(), .live(), and .delegate() call this method under the covers.
  • Still provides all the goodness of the .delegate() method, while still providing support for the .bind() method if you need it.

Cons
  • Brings confusion because the behavior changes based on how you call the method.

Conclusion (tl;dr)


If you have been confused about the various different types of event binding methods then don't worry, there has been a lot of history and evolvement in the API over time. There are many people that view these methods as magic, but once you uncover some of how they work it will help you understand how to better ode inside of your projects.

The biggest take aways from this article are that...
  • Using the .bind() method is very costly as it attaches the same event handler to every item matched in your selector.
  • You should stop using the .live() method as it is deprecated and has a lot of problems with it.
  • The .delegate() method gives a lot of "bang for your buck" when dealing with performance and reacting to dynamically added elements.
  • That the new .on() method is mostly syntax sugar that can mimic .bind(), .live(), or .delegate() depending on how you call it.
  • The new direction is to use the new .on method. Get familiar with the syntax and start using it on all your jQuery 1.7+ projects.





Were there any pros or cons that you would have added to the above lists? Have you found yourself using the .delegate method more recently? What are you thoughts on the new .on method? Leave your thoughts in the comments. Thanks!