Skip to content

Instantly share code, notes, and snippets.

@louisremi
Created August 14, 2009 23:53
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save louisremi/168158 to your computer and use it in GitHub Desktop.
Save louisremi/168158 to your computer and use it in GitHub Desktop.
(function(jQuery){
// This shortTermMemory will contain the last parsed simple selector.
// To be usefull it needs to be accessed faster than it would take to re-parse the selector.
// Selectors are to complex to serve as keys of a hash, and a bi-dimensional array would be too slow.
// I'm wondering if .data() would be fast enough for that purpose.
var shortTermMemory = [];
jQuery.fn.extend({
closest: function( selector, context ) {
var pos, closer = 0, re, split,
// Fetch the last succesfully parsed selector
memory = shortTermMemory;
// We are lookig for simple selectors such as "div", ".class" or "div.class"
// If the selector has not previously been parsed
if (selector != memory[0]) {
// We will parse the selector and stop parsing as soon as possible, to do as few tests as possible
split = selector.split('.');
if (split.length < 3) {
re = /^(?:[\w\u00c0-\uFFFF-]|\\.)*$/;
// The selector begins with a tag (memory[1] = TAG) or with a "." (memory[1] = true)
if (memory[1] = split[0] != ""? (re.test(split[0])? split[0] : false) : true) {
// The second part of the selector is a class (memory[2] = class) or there is no second part (memory[2] = true)
if(memory[2] = split[1]? (re.test(split[1])? " " + split[1] + " " : false) : true) {
// If we arrived that far, we found a simple selector
memory[0] = selector;
shortTermMemory = memory;
}
}
}
}
// If we haven't memorized the new selector, it wasn't simple
if(selector != memory[0]) {
// discard the memory
memory[0] = false;
// check for a position selector
pos = jQuery.expr.match.POS.test( selector ) ? jQuery(selector) : null;
}
return this.map(function(){
var cur = this;
while ( cur && cur.ownerDocument && cur !== context ) {
// the selector was a position
if ( pos? pos.index(cur) > -1 : (
// the selector was simple
memory[0]? ( (memory[1] === true || jQuery.nodeName(cur, memory[1])) && (memory[2] === true || (" " + cur.className + " ").indexOf(memory[2]) != -1))
// The selector was complex
: jQuery(cur).is(selector))) {
jQuery.data(cur, "closest", closer);
return cur;
}
cur = cur.parentNode;
closer++;
}
});
}
});
})(jQuery);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment