Dr. Frankenstein
Dr. Frankenstein

Reputation: 4704

storing jquery selectors in an object

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.

Upvotes: 0

Views: 423

Answers (5)

David Hellsing
David Hellsing

Reputation: 108530

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();
});

Upvotes: 1

Ian Clelland
Ian Clelland

Reputation: 44192

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.

Upvotes: 2

Dr. Frankenstein
Dr. Frankenstein

Reputation: 4704

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.

Upvotes: 0

yonkeltron
yonkeltron

Reputation: 643

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.

Upvotes: 1

Russ Bradberry
Russ Bradberry

Reputation: 10875

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.

Upvotes: 3

Related Questions