-1

I have written the following block of code and it works in my scenario but I know it is dirty:

var navbarModule = (function($) {
    var self = {};
    var $login;

    self.hideLogin = function() {
        $login.hide();
    };

    self.showLogin = function() {
        $login.show();
    };

    $(document).ready(function() {
        $login = $(".navbar-form");
    });

    return self;
}(jQuery));

My goals for the code are:

  1. Only select the DOM element if necessary
  2. Cache the selected DOM element
  3. Guarantee that the cached DOM element exists

My code fails to achieve #1, achieves #2, and circumstantially achieves #3. I.e., for requirement #3, navbarModule.hideLogin() works if the DOM has fully loaded but does not if you call it before the navbar is present in the DOM.

Is there a way to achieve true lazy loading and caching that meets my goals without circumstantially working?

David Peden
  • 17,596
  • 6
  • 52
  • 72
  • 1
    Try this for "true" lazy loading selectors : http://www.bucketsoft.com/blog/post/lazy-loading-jquery-selector – Goran.it Feb 15 '14 at 22:42
  • It is not clear what your problem is that you want help with. Are you simply calling `.hideLogin()` or `.showLogin()` before the DOM is ready? What does "only select the DOM element if necessary" mean? Where do you want to guarantee that the cached DOM element exists? In what piece of code. This question does not have enough info for us to know what you want help with. – jfriend00 Feb 15 '14 at 22:42
  • @jfriend00 For #1, my goal is not to execute the selector for the navbar at all unless either hideLogin or showLogin are called. If either function is called, I want to cache the navbar so that if either function is called more than once, I do not run through the jQuery selector again. – David Peden Feb 15 '14 at 22:47
  • Don't think you'll be really gaining any performance there. Load the script before the closing body tag, cache the selector first thing, then use that. – elclanrs Feb 15 '14 at 22:48
  • @Goran.it Thanks, I had seen the SO post that drove the blog post. That implements caching once the selector is executed but it does not provide lazy evaluation of the selector. – David Peden Feb 15 '14 at 22:51
  • Anonymous down-voter, please ask for clarification and I will happily amend my question. Thanks. – David Peden Feb 15 '14 at 22:52

1 Answers1

1

OK, now that you've explained what you mean by lazy caching, you can do this:

var navbarModule = (function($) {
    var self = {};
    var $login;

    function getLogin() {
        if (!$login || $login.length == 0) {
            $login = $(".navbar-form");
            return $login;
        }
    }

    self.hideLogin = function() {
        getLogin().hide();
    };

    self.showLogin = function() {
        getLogin().show();
    };

    return self;
}(jQuery));

Note:

If you call .showLogin() or .hideLogin() before there is a .navbar-form", then nothing will happen. It will create an empty jQuery object and the .hide() and .show() methods will simply not do anything. If you call it again later, it will see that the jQuery object is empty and look for ".navbar-form" again.

It is unclear why you think caching the login object is even required here. Give it an id value and just find it upon demand with document.getElementById() and it will be plenty fast.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • My question was more out of curiosity than to achieve a specific performance target. I agree that idiomatically getting the element by ID would be sufficient. – David Peden Feb 15 '14 at 22:57