views:

67

answers:

2

I've updated the script here to give a better example. For $header I've got an anonymous function now returning $("#header"). Although this works I'm sure its not efficient as it calls $header every time it's used - so its the same as just using $("#header") throughout the code.

What I really want is to store $("header") in a variable. When I try to do this with $header2 (below) it fails. #header is red not blue.

When I use firebug to output lib.page.$header2.selector is correctly displays #header. As you can see the script which calls lib.page.init is at the bottom of the DOM.

Any ideas?

<script type="text/javascript">

        var lib = {
            page : {

                $header  : function() { return $("#header")},
                $header2 : $("#header"),

                init: function() {

                    lib.page.$header().css("background","red");
                    lib.page.$header2.css("background","blue");
                    console.log(lib.page.$header2.selector);

                }

            }
        }

</script>
</head>
<body>

    <div id="wrapper">
        <div id="header">
            <em>Example!</em>
        </div>  
    </div>      

    <script type="text/javascript">
        $(function() { lib.page.init(); });
    </script>

</body>
+1  A: 

Because when you define $header : $('#header') that element is not available? and when you call lib.page.init it is? I am not sure when you call lib.page.init, but I bet it's in $(document).ready() right? And you define the object literal before the dom is ready.

Ok, your div#header is not available by the time you want to assign it to $header, you have two options and I will show you the best option first. It's what I meant with 'put all scripts at the bottom'!

<head>
    <!-- dont put scripts here if you can avoid it, it's bad! -->
</head>
<body>

    <div id="wrapper">
        <div id="header">
            <em>Example!</em>
        </div>  
    </div>      


    <!-- keep scripts at the end of the page just before the </body> tag -->
    <script type="text/javascript">

            var lib = {
                page : {
                    // div#header is available
                    $header  : $("#header"),
                    init: function() {
                        lib.page.$header().css("background","red");
                    }

                }
            }
            // you don't need onDomReady anymore.
            lib.page.init();

    </script>

</body>

Another option if you want to keep scripts in the header, is to assign $header in your onDomReady call.

<script>
    // create lib etc here

    $(function(){ // this is an onDomReady call in jQuery
        lib.page.$header = $('#header');
        lib.page.init();
    });
</script>
BGerrissen
How can I define the object literal after the dom is ready?
Meander365
When I console.log(lib.page.$header) in firefox I get a jQuery object returned and the selector is #header.Any ideas?
Meander365
The presence of the jQuery object is no guarantee it's populated with DOM elements. You need to check the length on that. Also, moving all your javascript to the end of the document before the </body> tag fixes these kind of problems entirely.
BGerrissen
I've updated the code with a better example - any ideas?
Meander365
updated my awnser
BGerrissen
A: 

"This happens because the variables are instantiated at the time the script is interpreted. So at the time of the parser gets to the script the $("#header") isn't in the DOM yet."

Meander365