Skip to main content

Cache your jQuery selectors, without messy code.

/*
 * jQuery Selector Cache
 *
 * Cache your selectors, without messy code.
 * https://github.com/farzher/jQuery-Selector-Cache
 *
 * Usage:
 *
 * // Instead of
 * $('div')
 *
 * // Use
 * $$('div')
 *
 * The next time you call $$('div') it will be instantly fetched from the cache.
 *
 * ## Documentation
 *
 *  - `$$('div')` The next time you call `$$('div')` it will be fetched from the cache.
 *  - `$$clear('div')` Invalidates the cache. The next time you call `$$('div')` It will return fresh results.
 *  - `$$fresh('div')` Shortcut for `$$clear('div')` `$$('div')`
 *
 * ### Advanced usage
 *
 *  - `$$('div', '#context')` Find within a context
 *  - `$$clear('div', '#context')` Invalidates query on the context
 *  - `$$clear('#context')` Invalidates the cache, and all queries on the context
 *  - `$$clear()` Invalidates all of the cache
 *  - `$$fresh('div', '#context')` Shortcut for `$$clear('div', '#context')` `$$('div', '#context')`
 *  - OOP syntax `$$('p').$$('a')` `$$('p').$$clear('a')` `$$('p').$$fresh('a')`
 *
 * ## Alternatives
 *
 * [jQache](https://github.com/danwit/jQache) is more popular, and does
 * more. Although, if this works for you and you're hardcore about performance,
 * this plugin is less heavy (because it's more simple).
 *
 * Or just don't use a library:
 * `let $mybutton = $('#mybutton'); $mybutton.click(); $mybutton.hide()`
 *
 * @author Stephen Kamenar
 */

(function($, undefined) {
  // '#a': $('#a')
  var cache = {};

  // '#context': (a cache object for the element)
  var cacheByContext = {};

  // Here for performance/minification
  var tmp, tmp2;

  $$ = function(selector, context) {
    if (context) {
      if ((tmp = context.selector)) context = tmp;

      // tmp2 is contextCache
      tmp2 = cacheByContext[context];
      if (tmp2 === undefined) {
        tmp2 = cacheByContext[context] = {};
      }

      tmp = tmp2[selector];
      if (tmp !== undefined) return tmp;

      return (tmp2[selector] = $(selector, $$(context)));
    }

    tmp = cache[selector];
    if (tmp !== undefined) return tmp;

    return (cache[selector] = $(selector));
  };

  $$clear = function(selector, context) {
    if (context) {
      if ((tmp = context.selector)) context = tmp;

      if (selector) {
        if ((tmp = cacheByContext[context])) tmp[selector] = undefined;
      }
      cacheByContext[context] = undefined;
    } else {
      if (selector) {
        cache[selector] = undefined;
        cacheByContext[selector] = undefined;
      } else {
        cache = {};
        cacheByContext = {};
      }
    }
  };

  $$fresh = function(selector, context) {
    $$clear(selector, context);
    return $$(selector, context);
  };

  $.fn.$$ = function(selector) {
    return $$(selector, this);
  };
  $.fn.$$clear = function(selector) {
    $$clear(selector, this);
  };
  $.fn.$$fresh = function(selector) {
    return $$fresh(selector, this);
  };
})(jQuery);