Tuesday, January 31, 2012

How to Access jQuery's Internal Data

As you may or may not be aware as of jQuery 1.7 the whole event system was rewritten from the ground up. The codebase is much faster and with the new .on() method there is a lot of uniformity to wiring up event handlers.

One used to be able to access the internal events data and investiate what events are registered on any given element, but recently this internal information has been hidden based on the following ticket...

"Ticket #8921: jQuery Private Data Should Stay Private

It seems that the "private" data is ALWAYS stored on the .data(jQuery.expando) - For "objects" where the deletion of the object should also delete its caches this makes some sense.

In the realm of nodes however, I think we should store these "private" members in a separate (private) cache so that they don't pollute the object returned by $.fn.data()"

--http://bugs.jquery.com/ticket/8921

Although I agree with the above change to hide the internal data, I have found having access to this information can be helpful for debugging and unit testing.


Thankfully, if you still need access to the internal data it is still accessible, however, you need to use a method that isn't officially documented... which means that you should be cautious about using it. I would encourage you to not use the undocumented ._data() method in production code.


You can view, run, and edit the above code sample from JSBin.

On the plus side, if you access the old .data() method with "events" as a parameter that will retrieve the internal data containing events and event handlers.

As a side note, if you are looking for events attached using the .live() or .delegate() methods then you will need to look at either the document element or whatever element you delegated against.

Update: Rick Waldron informed me on twitter that the jQuery Core team plans on creating a supported plugin to access the internal data that jQuery maintains. This would be a much better solution than using the above undocumented ._data() method because undocumented methods are also unsupported methods ;) I only use the ._data() method for debugging or testing. You should try to avoid using it in any of your production code for this reason.

Monday, January 30, 2012

Find the jQuery Bug #3: Give Me Truth

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 div and build a simple popover module that uses the jQuery UI Dialog widget.


The Buggy Code


The intent of the following code snippet is to verify that the div being used in the modal dialog exists in the DOM and that it has not been already initialized. We have an init method that should initialize the widget and then an open method that should launch the dialog. The code snippet has some problems. Do you see them?


You can view, run, and edit the above code sample from JSBin.

When we run the code, things seem pretty much like what we expected. The widget seems to have been initialized and then opens as expected. We don't actually see the error visually, but there is a problem hidden in the init() code. If you debug through the code you'll notice something odd when calling init() again. We put in checks to verify for the existence of the DOM element and that it hasn't been initialized yet, right? Well, that is where the problem lies. Do you see the problem now?

The Underlying Problem


At the root of the problem is how we are testing for truth! Both the ways we are checking for existence and initial state are flawed.

"jQuery( selector [, context] ) Returns: jQuery
Description: Accepts a string containing a CSS selector which is then used to match a set of elements." --http://api.jquery.com/jquery

The check for existence is incorrect, because just checking the result of $( "dialog-modal" ) doesn't get you anywhere. Where does it get you? It always evaluates as true because a call to $( selector ) returns the jQuery object and based on our truthy/falsey rules an object is always truthy! What does this mean? Well, it means the code to initialize the DOM element would execute even if it didn't exist at all!

".not( selector ) Returns: jQuery
Description: Remove elements from the set of matched elements." --http://api.jquery.com/not

In a similar fashion the check we were making for the initial state of the DOM element is incorrect. The intent was to check if the element did not have a particular class (.ui-dialog-content), which is added by jQuery UI when it initializes the dialog widget. If we take a look at the documentation for the .not() method we'll see that it too returns the jQuery object! The purpose of the method is to filter down the matches by removing elements that match the selector provided. So, we run into the same problem as above where we are always evaluating as truthy!

A Solution


The solution to fix these problems are really simple and straightforward. All you really need to do is to check how many items where matched by a jQuery selection and to use the .is() method instead of the .not() method.


You can view, run, and edit the above code sample from JSBin.

If you run the above code again you'll notice that the console.log message only shows up the first time the .init() method is called.

Conclusion


The key concept to remember here is to realize that testing against the jQuery object will always evaluate as true. As shown above it is easy to adjust your code accordingly.

There are other more advanced techniques that can be used for initialization as well. I'd encourage you to look into Doug Neiner's (@dougneiner) Contextual jQuery series (Part 1 and Part 2) that he gave at the jQuery Boston 2010 and 2011 Conferences. In particular he gave some really interesting just-in-time initialization techniques in the 2nd talk. I highly encourage you viewing these if you haven't already.

Until next time...

Friday, January 27, 2012

Having Fun with JavaScript and Skype Emoticons

I was chatting with Jim Cowart (@ifandelse) on Skype today about jQuery. He pasted in a snippet of code and Skype translated part of it into one of it's emoticons. He almost immediately updated the chat message to fix the issue, but it got me starting to think... and that can be very dangerous.

I thought to myself that it would be fun to create a program that intentionally utilize Skype emoticons. The following screenshot is the result of the program I put together. It is a restaurant where you can listen, eat, and drink ;)


As you can tell, it is a silly little program. The code for the above screenshot can be found below. Some of the icons I used are secret emoticons that you can lookup.


If you'd like to come up with your own Skype-enabled JavaScript program, then I'd like to see it. Share it in the comments. Have fun!

Wednesday, January 25, 2012

Find the jQuery Bug #2: Point of No Return

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 my other post in this series...

The Desired Feature


We want to take the following HTML unordered list and build a JavaScript function that will determine if a specific value is present.


The Buggy Code


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


You can view, run, and edit the above code sample from JSBin.

The results that we expected were false, true, true, true, false, but instead the output in the console is false, false, false, false, false.

The Underlying Problem


At the root of the problem is the special jQuery .each() method we are using. The .each() method is a very handy way to iterate over the jQuery collection, however there is a special meaning to return false within a .each() method.

"We can stop the loop from within the callback function by returning false." --http://api.jquery.com/each

Upon further examination of the code it even makes further sense why it wouldn't work. Most of us are familiar that a return statement exists the current function, but in this case we aren't invoking the function... jQuery is! So, jQuery has control over what happens when you exit your function prematurely and it recognizes return false to mean something special.

A Solution


The solution to fix this problem is really simple and straightforward. All you really need to do is to introduce another variable hasNumber. If the number was found, then set the hasNumber variable to true and then return false; to exit the .each() method.


You can view, run, and edit the above code sample from JSBin.

If you test out the code again below you'll notice that now that we are getting the expected output of false, true, true, true, false.

An Alternate Solution


An alternate way to solve this problem would be to use another technique completely. In the following example we will use the jQuery.grep method. The jQuery.grep method is defined as the following:

"Finds the elements of an array which satisfy a filter function. The original array is not affected." --http://api.jquery.com/jquery.grep/


You can view, run, and edit the above code sample from JSBin.

Although the code looks shorter, it is less performant than the previous solution. Can you tell why? The code is not exiting once the number has been found, but instead goes through each array item and executes the callback function. We get the correct answer, but for a price.

Conclusion


The key concept to remember here is to be aware of the special mean of return false; inside of a jQuery .each() method to exit the loop. Even if you have never made this mistake before, maybe it has opened up your eyes to the fact you can exit out of a .each() method!

Until next time...

Thursday, January 19, 2012

Daily and Weekly Front-End Dev Resources

If you are anything like me, you love and thrive on what is new in the front-end world. What is the latest in HTML5 buzz, what is the newest library that will solve all my needs, what is that new jQuery plugin that will make my client drool, and things of the like.

I used to scour the internet for things like that myself and share them on Twitter and elsewhere, but I've recently changed focus so that I can blog more frequently. My desire for tech news has not diminished in the least, I am still a junkie for new articles and libraries.

So, what am I to do? Well, that is easy. There are many fine resources that have been around for years and there are also some that have cropped up recently that should provide just the right amount of geek influx to quench my thirst and I hope yours as well.

Daily Technology News


Twitter


Blogs


Weekly Technology News


Newsletters


Blogs


Podcasts


[Cross posted from Fresh Brewed Code.]

Monday, January 16, 2012

Bye Bye Tech Tweets

As you probably noticed I haven't been blogging as much as I used to. With church, family, work, and tech tweets it seems my free time has dwindled down to nothing.

I want to refocus on blogging again for this year. Not only do I enjoy sharing the things that I learn, but by doing so I tend to learn the topic even better than I did in the first place. Also, many of my conference presentations are based off blog posts that I've authored previously. 

So, something needs to give for me to have extra time for blogging and giving up Tech Tweets is what I've chosen. Giving up Tech Tweets wasn't an easy decision for me because I've lived and breathed it for probably the past 5 years or so. It is now in my nature to scour the internet for the latest in front-end news. In order for this to work like I want to I'll need to resist the urge to research everything and share it immediately. I'll need to now depend on the others who are currently doing the research. 

Thankfully there are many other avenues to get similar information that I've been providing. Many great resources have cropped up recently that allow you to get front-end news, articles, and library information in a daily or weekly manner. I'll be blogging about what resources I recommend you to follow in the near future. These are the same resources that I'll be using to keep myself up to speed on what is going on.

I am not giving up Twitter or anything. I still will be active on social media, but any tech tweets you see from me will probably be retweets from other resources or just interesting things that I came across that day. Who knows, I might get pulled back into the whole tech tweeting again, but even if I do I'd like to keep it somewhat unstructured.

Thank you all for following me and for regularly retweeting my tech tweets. I do appreciate it. My habbits are changing, but hopfully the posts will be of value to you as well. I have planned out numerous jQuery and jQuery Mobile posts that should keep me busy for quite some time. 

In addition to a renewed interest in blogging I will also focus on posting some content to the newly created Fresh Brewed Code website where many of my friends from the Nashville area are now blogging. I don't have any posts there yet, but expect some very soon!