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,572 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,572 Comments

@Peter,

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


Post Comment  |  Ask Ben

Recent Blog Comments
Mar 21, 2010 at 8:57 PM
The Bourne Ultimatum Starring Matt Damon And Julia Stiles
late to the party, but my observation is this: rewatch carefully for the platonic nature of the relationship between nicki and jason. she never flirts with him. he never comes on to her. they alway ... read »
Mar 21, 2010 at 7:40 PM
Is Simulating User-Input Events With jQuery Ever A Good Idea?
A couple of things. One you embed the initial state of of more-info in the CSS. IMHO, that behavior should be in jQuery: moreInfo.hide(); It shows that the behavior your toggling and closing is mor ... read »
Mar 21, 2010 at 3:59 PM
Exploring ColdFusion Component Runtime Class Properties And Serialization
@Elliott, according to Ben's experiment, serializeJSON() doesn't access the private data by default - it doesn't even access the getHair() method - so trying to clone a Girl.cfc via serializeJSON/des ... read »
Mar 21, 2010 at 3:49 PM
Ask Ben: Javascript String Replace Method
I'm confused a bit by what you are asking, but if had this sentence: The color, red, is in the style statement; style: red;. and wanted to remove all or change all of the commas, colons, and semi-c ... read »
Mar 21, 2010 at 3:13 PM
Ask Ben: Javascript String Replace Method
I am trying to make a java program to count the number of times that these punctuation marks occur in a body of text: , : ; . ! - ' " ? / \ I am using this piece to ferret out the commas: numcommas ... read »
Mar 21, 2010 at 11:13 AM
A New Wrist Pain
@chiropractor suwanee, Spoken like someone trying to sell something. Other than for minor, temporary relief from some back pain, chiropractic treatment is nothing but placebo effect and quackery. ... read »
Mar 21, 2010 at 6:32 AM
ColdFusion CFPOP - My First Look
Apologies... The field name in the db for C. is "BounceCode" It stores the code / message which is returned in the email. Sorry for the confusion. ... read »
Mar 21, 2010 at 6:29 AM
ColdFusion CFPOP - My First Look
@Jose Galdamez, Hi Ben and Jose 1st of all.. big thanks to Jose for his Skype chat a few weeks back. Your time was much appreciated. I have come up with a rather unelegant solution to my problem a ... read »