Calling jQuery's Data() Method Without Arguments

Posted February 1, 2010 at 10:10 AM

Tags: Javascript / DHTML

With jQuery 1.4, I was very happy to see that they finally gave us the ability to invoke the data() method without arguments. Calling the data() method in this way returns an object containing all of the keys stored using the data() method on this object. When I was working on my jQuery image zoom experiment, I made heavy use of this feature to store data points without having to call the data() method each end every time. I was able to do this because the object returned by the data() method is the actual data cache object - passed by reference - and not a copy of it. As such, once you have the data cache, direct changes to it will be reflected in all subsequent calls to the data() method on that object.

 
 
 
 
 
 
 
 
 
 

Of course, it never is quite that straightforward. jQuery's data() method only returns the object's data cache if the cache exists; and, the cache only exists if a value is currently being stored in it. If no keys have been stored in the cache, or all the keys have been deleted (using removeData()), then the data() method will return null, not an empty cache object. I assume that they are doing this for optimization purposes, but there's something I don't like about it; it makes the data() method's behavior dependent on the previous uses of data() and this difference in data() potential just seems dangerous.

To make the data() method's behavior uniform, we can override the original data() method to apply some intercepting business logic. In the following demo, you'll see that I wrap the original data method using my own data method (is that AOP - Aspect Oriented Programming??). My version of the data method then applies the call to the original data method and, if the data method returns a null cache object, I store a data point in the elements data cache before returning the data cache. While this definitely feels sloppy in and of itself, storing this bunk name/value pair forces the data cache to become sticky.

 Launch code in new window » Download code as text file »

  • <!DOCTYPE HTML>
  • <html>
  • <head>
  • <title>Calling jQuery's Data() Method Without Arguments</title>
  • <script type="text/javascript" src="jquery-1.4.js"></script>
  • <script type="text/javascript">
  •  
  • // Here, we want to override the data() method so that
  • // non-argument calls to it will always return the data
  • // store object.
  • (function( $ ){
  •  
  • // Get a reference to the original data method.
  • var originalData = jQuery.fn.data;
  •  
  • // Override the data method to ensure that the data
  • // store is always returned.
  • jQuery.fn.data = function(){
  •  
  • // Check to see if there are any arguments passed
  • // in. This is the only case we care about.
  • if (!arguments.length){
  •  
  • // Get the storage object.
  • var dataStore = originalData.apply( this );
  •  
  • // Check to see if the dataStore exists. If
  • // it does, then just return it; otherwise,
  • // we'll have to create one.
  • if (dataStore){
  •  
  • // Return current store.
  • return( dataStore );
  •  
  • }
  •  
  • // If we made it this far, then the data store
  • // returned was null which means it has never
  • // be accessed before. To create it, we
  • // actually have to set a key in it. We also
  • // have to keep the key in there, otherwise
  • // jQuery will try to delete the data store.
  • originalData.apply( this, [ "_", "_" ] );
  •  
  • // Now that the dataStore object has been set
  • // as the hash, return it.
  • return( originalData.apply( this ) );
  •  
  • } else {
  •  
  • // No special case, simply pass method call
  • // to original method and return the result.
  • return(
  • originalData.apply( this, arguments )
  • );
  •  
  • }
  •  
  • };
  •  
  • })( jQuery );
  •  
  •  
  • // -------------------------------------------------- //
  • // -------------------------------------------------- //
  •  
  •  
  • // When the DOM is ready, init the scripts.
  • jQuery(function( $ ){
  •  
  • // Get a reference to the P tag.
  • var para = $( "p:first" );
  •  
  • // Get a reference to the data storage struct.
  • // When you call the data() method without any
  • // arguments, jQuery returns the actual storage
  • // object, not a duplicate of it.
  • dataStore = para.data();
  •  
  • // Now that we have the data storage object, we
  • // can update the values in it directly.
  • dataStore.name = "Tricia";
  • dataStore.isSexy = true;
  •  
  • // Now that we have updated the store object, let's
  • // update the text of the paragraph by re-referencing
  • // the data storage mechanism.
  • //
  • // NOTE: We did NOT have to re-store the data object
  • // in order to make these values available.
  • para.text(
  • para.data( "name" ) +
  • " is " +
  • (para.data( "isSexy" ) ? "" : " not " ) +
  • "sexy!"
  • );
  •  
  • });
  •  
  • </script>
  • </head>
  • <body>
  •  
  • <h1>
  • Calling jQuery's Data() Method Without Arguments
  • </h1>
  •  
  • <p>
  • <!-- Will be populated dynamically. -->
  • </p>
  •  
  • </body>
  • </html>

As you can see, the first part of this script overrides jQuery's native data() method to intercept and manipulate calls to the data() method made without any arguments. If the data() method returns null, I store the key, "_", in the element's data cache before re-querying the data() method to return a valid data cache object reference. In doing so, the rest of the demo can successfully retreive the data cache using the data() object regardless of the current state of the cache. In doing so, I am able to directly mutate the data cache without making unnecessary calls to the data() method. And, since this data cache is returned by reference, my data alterations are reflected in subsequent calls to the data() method.

When we run the above code, we get the following paragraph output:

Tricia is sexy!

As you can see, the direct data manipulation we performed on the data store object was successfully reflected in later calls to the data() method.

jQuery 1.4 finally gave us the ability to directly access the data cache being used by the data() method. The behavior of this method, however, depends tightly on the current state of the cache. To me, this difference in data() behavior feels unnecessary; and, while the above solution is not perfect by any means, I like that it simplifies the way in which the data() method can be used.

Download Code Snippet ZIP File

Post Comment  |  Ask Ben  |  Other Searches  |  Print Page




Learning ColdFusion 9 - ColdFusion 9 tutorials, samples, examples, demos

Reader Comments

Feb 1, 2010 at 11:02 AM // reply »
2 Comments

Hi Ben,

Suggest some good tutors/books to learn this JQuery framework.

Thanks!


Feb 1, 2010 at 11:19 AM // reply »
7,486 Comments

@Dave,

I think the fastest, low-level intro to the language would probably be Cody Lindley's jQuery Enlightenment book:

http://www.bennadel.com/blog/1713-jQuery-Enlightenment-By-Cody-Lindley.htm

Once you are comfortable with that, there are a number of other great jQuery books that I have reviewed on this site:

http://www.bennadel.com/blog/tags/12-Books-blog-entries.htm

Try looking at jQuery Cookbook, jQuery in Action, Learning jQuery, and the jQuery UI books. These are all great books and go into more depth.


Feb 1, 2010 at 12:06 PM // reply »
2 Comments

Thanks Ben!.. Will give them a try!.


Feb 2, 2010 at 12:34 PM // reply »
1 Comments

Is this new in 1.4?


Feb 2, 2010 at 12:43 PM // reply »
7,486 Comments

@Peter,

Calling data() without arguments... but not the data() method itself.


Post Comment  |  Ask Ben

Recent Blog Comments
Mar 12, 2010 at 1:38 AM
Using jQuery's SlideUp() and SlideDown() Methods With Bottom-Positioned Elements
Very nice and useful tutorials for web designers, Thanks for posting. ... read »
Mar 11, 2010 at 11:14 PM
Using The Apple iPod Shuffle Without iTunes
Whoever coded this deserves a pat on the back. I really hated iTunes and this has worked great for me. Thanks! Oh, and thanks for answering the question about file renaming. I was just afraid I woul ... read »
Mar 11, 2010 at 9:29 PM
Tim Cracked The GMail - CFMailPart Puzzle!
I've been wrestling with the CFMAIL tag and CFMAILPARTS for several days now and have found issues with the CF implementation even in CF9! What I have learned so far is: 1. Using only one CFMAILPART ... read »
Mar 11, 2010 at 6:09 PM
Ask Ben: Building An AJAX, jQuery, And ColdFusion Powered Application
@Eric, Neat trick, I was able to get rid of most of the lines of whitespace following your advice. Some whitespace still remains. With a bit of playing around, I found that the remaining whitespa ... read »
Mar 11, 2010 at 4:56 PM
Ask Ben: Building An AJAX, jQuery, And ColdFusion Powered Application
I've struggled with returning JSON from ColdFusion CFCs for a while because I (mysteriously) get lots of white space/new lines that appear before the actual JSON result (check the response in Firebug ... read »
Mar 11, 2010 at 3:24 PM
Ask Ben: Using jQuery To Act On A Click Event Based On The Target Element
@TripeL, Awesome :) Glad it was helpful. ... read »
Mar 11, 2010 at 3:23 PM
Ask Ben: Using jQuery To Act On A Click Event Based On The Target Element
WOW...that's what I'm looking for. The code examples are very helpful. Thanks ... read »
Mar 11, 2010 at 1:20 PM
What Is The Best Time Of Day To Workout?
Well I am glad I stick to mid afternoon / evening work outs. Interesting find! ... read »