New jQuery plugin: Object Cache
Inspired by Benjamin Sterling‘s “Better jQuery Code” article I decided to develop a simple plugin to make his first point (Caching) easier… nothing fancy, just a few methods, but you will hopefully find it useful.
Its objective is to let you store a jQuery object with a simple key in a global cache,
so that you can access the same object easily, without having to write the same selection, filtering or traversing code (i.e: $(“#main > p”) or $(“#main”).children(“.selected”).eq(0)).
Here is how it works:
// Store in cache - Returns current object
$("#mainNav").cache("main_navigation");
// Retrieve from cache - Returns cached object
$$("main_navigation"); // or jQueryCache("main_navigation");
// Remove from cache
$$.remove("main_navigation");
// Clear Cache
$$.clear();
// Load jQueryCache with noConflict to avoid overriding window.$$
$$.noConflict();
There is a lot of room for improvement, which will be done depending on the feedback I get, so feel free to contact me with any ideas or corrections you might come up with.
You can get the Jquery Object Cache plugin here.
That is actually a very great idea, I like this a lot.
you should implement auto caching by stringifying selectors into valid keys so that you can input any valic slelector into $$ and it will always rerieve fresh dom or cached if its there, and allow a boolian for forcing an refresh lookup for those times when you need to update the dom and thus the cached lookup.
@andrew, that is actually a good idea. I first thought of making the plugin work that way but I decided to change it to the current one. So I will probably be adding this during this week
. thanks for your feedback!
what do you think of this it may be a tiny bit faster theres less type checking, it auto caches your lookups uisng the selector as the key and points back to a regular jquery object if the argument is not a string, also added a refresh method
; if(window.jQuery) {_$$ = window.$$; //in case overwrite
window.jQueryCache = window.$$ = window.$c = function($) {
// Add object_cache dictionary to jQuery
$.extend({
object_cache: {}
});
$.fn.extend({
cache: function (selector) {
return $.object_cache[selector] = this;
}
});
// $$() function and methods
var jQueryCache = function(selector) {
if (typeof selector == "string") {
return $.object_cache[selector] || $(selector).cache(selector);
} else {
return $(selector);
}
};
jQueryCache.refresh = function(selector) {
return $(selector).cache(selector);
};
jQueryCache.remove = function(selector) {
$.object_cache[selector] = null;
};
jQueryCache.clear = function() {
$.object_cache = [];
};
jQueryCache.noConflict = function() {
window.$$ = _$$;
return jQueryCache;
}
return jQueryCache;
}(jQuery);
}
@andrew, sorry I didn’t get back to you sooner.
A few weeks ago I was going to implement something like this, but then I realized we are thinking of different goals. This plugin’s goal is caching jQuery objects to allow more manageability (instead of having to write a selector several times, just reference a key) and some faster responses (but all in all, speed was not the main goal). You would use it only for particular objects you know won’t be changing regularly and you’ll be referencing a lot.
On the other hand, what you want (I think) is a selector cache, and from my point of view that should be done at the selector’s engine level. Otherwise, it’d be useless for stuff like $(“.class_something”).children(“.selected”). Also having to manually refresh cached items doesn’t look too good (what will happen when you have 10+ cached items?).
I know Sizzle had a caching system but it’s been removed recently (explanation here: http://groups.google.com/group/jquery-dev/browse_thread/thread/bf2a17146c5c1ca5). However, I guess that doesn’t mean it can’t be done.
Anyway, I would like to know your (and everybody’s) thoughts on this. I believe this plugin shouldn’t do much, or try to be too clever. I just wanted a way to avoid doing “var obj = $(…)” and I think the plugin the way it is right now does exactly that.
All very good points Luciano, I was unaware of the defunct cacheing code removed from sizzle. I agree for the purposes you have laid my auto-caching scheme would be of no benefit, however it does not preclude you from continued use of that functionality. In the cases where I want to cache a more complex jquery chained lookup or some other object I just fall back to the .chache(“someuniquename”);
I my case when using the object cache I found myself facing the same annoyances i faced when I used var blah = $(“#blah”). Namely i had to come up with a unique name for the item to be cached and I had to write unique code in the right place to cache an item. In my coding style I found that I was often using some derivation of the class or id as a name. So from a coding standpoint I found tha I was noy improving my code greatly over var = …. I was just using different syntax.
I defense of using a selector as a key I do like how it is more self documenting that some variable name you come up with. Secondly its easy to convert existing code with a simple find and replace because $$ will cache and retrieve, no need to know when and where to cache, you just use it. Again theres always the option to fall back to .cache(key).
With all that said jQuery allows a huge range of approaches to grabbing DOM elements which leads to different approaches to designing that interface between the DOM and the js code. Some people like one way of doing things some like another, so much of this just comes down to personal taste.
Cheers!
[...] New jQuery plugin: Object Cache [...]
What happens in this case :
1 : $JQ1 = $$(“#mydiv”)
2: $JQ2 = $$(“#mydiv”)
3: $JQ1.remove() ;
4: $JQ2.show() ; // ??????
Also , if we replace line 2: wit this :
2: $JQ2 = $JQ1
Are we going to do anything different ?
Not sure I’m getting your point.
The cache returns an object reference, which is assigned to $JQ1 and $JQ2. This means that by line 3, they both point to the same object. So doing #3 and #4, would be the same as doing $(“#mydiv”).remove().show()
Is that what you were asking?
[...] there are more jQueryish ways of doing this but come on, you can’t beat that [...]