views:

231

answers:

5

The following does not seem to work -

IT.TopSlide = {

 selectors : {
  div : $('#top-slide'),
  signup : $('#top-slide #signup'),
  login : $('#top-slide #login'),
  signup_trigger : $('#header .top-slide-triggers a.signup-trigger'),
  login_trigger : $('#header .top-slide-triggers a.login-trigger'),
  close : $('a.close')
 },

 init : function (){

  var selectors = IT.TopSlide.selectors;
  selectors.div.hide();
  selectors.login.hide();

 }

};

$(document).ready(function () {
   IT.TopSlide.init();
});

selectors.div returns an empty array. Bare in mind that for each namespace I want to have the first item as a selectors storer that I can access with IT.TopSlide.selectors from any other object. From within the namespace I would like to define it as a var - var selectors = IT.TopSlide.selectors; so I can access the cached selectors.

+3  A: 

you want to be sure to put this in a function that runs once the DOM is ready

$(document).ready(function(){
    IT.TopSlide = {

    selectors : {
        div : $('#top-slide'),
        signup : $('#top-slide #signup'),
        login : $('#top-slide #login'),
        signup_trigger : $('#header .top-slide-triggers a.signup-trigger'),
        login_trigger : $('#header .top-slide-triggers a.login-trigger'),
        close : $('a.close')
     },

     init : function (){

     var selectors = IT.TopSlide.selectors;
     selectors.div.hide();
     selectors.login.hide();

       }

    };


    IT.TopSlide.init();

});

otherwise it tries to add the objects before they are created.

Russ Bradberry
putting the whole lot in doc ready isnt really ideal, if I could just put IT.TopSlide.selectors in doc ready I'd be sorted;
Dr. Frankenstein
But you're trying to cache something that's not even there yet. You're trying to put your mother-in-law's suitcase in the guest room when it's still being mishandled by the baggage claim guys at the airport.
Nosredna
+2  A: 

It looks like your selectors object is being defined at a time when the DOM is not ready. When you write $("selector") in your object like that, the jQuery function is called immediately, and returns an array containing whatever it finds.

I thing that you should do one of two things: Either change your selectors array to contain just the selectors, like this:

selectors : {
    div : '#top-slide',
    signup : '#top-slide #signup',
    login : '#top-slide #login',
    signup_trigger : '#header .top-slide-triggers a.signup-trigger',
    login_trigger : '#header .top-slide-triggers a.login-trigger',
    close : 'a.close'
},

And then when you want to use it, call jQuery at that point:

var selectors = IT.TopSlide.selectors;
$(selectors.div).hide();

or,

Put functions into your selectors object, which you can call whenever you need to get the current list of matched dom elements:

selectors : {
    div : function() { return $('#top-slide') },
    signup : function() { return $('#top-slide #signup') },
    login : function() { return $('#top-slide #login') },
    signup_trigger : function() { return $('#header .top-slide-triggers a.signup-trigger') },
    login_trigger : function() { return $('#header .top-slide-triggers a.login-trigger') },
    close : function() { return $('a.close') }
},

And then, to use it, do this:

var selectors = IT.TopSlide.selectors;
selectors.div().hide();

Either way will work, and will delay actually calling jQuery until the right point -- when you actually want to match what's in the DOM.

Update

If you need to have these functions cached at the time that the document is first loaded, then you will need to have the jQuery function called in a $(document).ready() callback. You can keep the code in your namespace by having a function that calls jQuery and caches all of the results, like this:

IT.TopSlide = {

    ...

    cacheSelectors: function() {
        return {
            div : $('#top-slide'),
            signup : $('#top-slide #signup'),
            login : $('#top-slide #login'),
            signup_trigger : $('#header .top-slide-triggers a.signup-trigger'),
            login_trigger : $('#header .top-slide-triggers a.login-trigger'),
            close : $('a.close')
        }
    },

    ...
}

and then,

$(document).ready(function() {
    ...
    IT.TopSlide.selectors = IT.TopSlide.cacheSelectors();
    ...
}

That way, you have a version cached at the time that the document is loaded and ready, and you have the flexibility of being able to call cacheSelectors() at any other point (say, after you know that the DOM has been modified) and use a new copy, if you need to.

Ian Clelland
yes but as I understand, please correct me if I'm wrong but both of these solutions look like the slector is searched for in the dom by jquery every time the variable is called. I want to access a cached version.
Dr. Frankenstein
nice update - makes a lot of sense
Dr. Frankenstein
+1  A: 

Another answer is that the init function can do the actual setup of the selectors! That way you can still cache the selectors and yet the code doesn't run before the DOM is ready.

yonkeltron
Yeh the whole point is so that I can reuse these cached selectors in all the methods of the TopSlide namespace
Dr. Frankenstein
I think what you are getting at here may be how I came to my answer, though not quite enough detail to award the big tick.
Dr. Frankenstein
A: 
IT.TopSlide = {    
    selectors : {},

    init : function (){    
     IT.TopSlide.selectors =  {
      div : $('#top-slide'),
      signup : $('#top-slide #signup'),
     };
    },

    another_method : function() {    
     selectors = IT.TopSlide.selectors;    
     var height = selectors.div.height();
    }
};

$(document).ready(function () {
    IT.TopSlide.init();
});

I had to define an empty selectors object that gets populated on init. Then I have to declare "selectors" as a variable unless I want to do IT.TopSlide.selectors.div (too long for my liking) every time I want that div. Thanks.

Dr. Frankenstein
Programatically, this is no different than my suggestion. If you define the selectors in init on document.ready, then they are still getting defined in document.ready.
Russ Bradberry
+1  A: 

Two options:

  1. Put the code in the bottom of the page, before closing the body tag.
  2. convert the selectors object to a function and call it on DOM ready. If you want to cache it before running init(), you can do it in the 'ready' event function before calling init():

-

IT.TopSlide = {
    cacheSelectors : function() {
        IT.TopSlide.selectors = {
            div : $('#top-slide'),
            signup : $('#top-slide #signup'),
            login : $('#top-slide #login'),
            signup_trigger : $('#header .top-slide-triggers a.signup-trigger'),
            login_trigger : $('#header .top-slide-triggers a.login-trigger'),
            close : $('a.close')
        }
    },
    selectors : {},
    init : function () {
        var selectors = IT.TopSlide.selectors;
        selectors.div.hide();
        selectors.login.hide();
    }
};

$(function() {
    IT.TopSlide.cacheSelectors();
    IT.TopSlide.init();
});
David