imagineerThat
imagineerThat

Reputation: 5553

Load jquery before the DOM is ready - possible by removing $() alias?

Is it possible to remove the two $() aka ready handlers from the script below? I'd like to load the jquery before the DOM is ready, but still be able to refer to #certification.

    $(function(){
           $("#certification").multiselect({
               minWidth: "500",
               noneSelectedText: "Certification Testing: Start Time - End Time (EST):",
               selectedText: function(numChecked, numTotal, checkedItems){
                   return 'Certification Testing: ' + numChecked + ' of ' + numTotal + ' checked';
               }
           });
    });

EDIT: Please assume #certification appears before the above script (in <head>). I'd like to refer to #certification from the script before the entire DOM is ready. Is it possible to do this without the $ ready handler?

EDIT2: Please assume above is located in <head>

RESOLUTION: From the advice given, I was able to resolve the issue. The $(function(){}) ready handler was removed, with the #certification element appearing before the jquery. The #certification element and jquery were both moved from the <head> to the <body>, where it should be. Now the jquery displays before the rest of the DOM is ready, as intended. Thanks all for your answers.

Upvotes: 0

Views: 1120

Answers (6)

nnnnnn
nnnnnn

Reputation: 150050

"Is it possible to remove the two $() aka ready handlers from the script below?"

Your script contains only one ready handler, but yes, it can be removed.

"Please assume #certification appears before the above script. I'd like to refer to #certification from the script before the entire DOM is ready. Is it possible to do this without the $ ready handler?"

Yes. Code in a script element can refer to elements that appear before that script, because elements higher up in the page source have already been parsed and added to the DOM. So if your script is after the element then you can simply do this:

       $("#certification").multiselect({
           minWidth: "500",
           noneSelectedText: "Certification Testing: Start Time - End Time (EST):",
           selectedText: function(numChecked, numTotal, checkedItems){
               return 'Certification Testing: ' + numChecked + ' of ' + numTotal + ' checked';
           }
       });

"EDIT2: Please assume above is located in <head>"

Huh? This contradicts your previous "Please assume" statement. How can the script be located in the head yet still be located after the #certification element? You are not supposed to include "regular" elements in the head section, just the title element plus base, link, meta, style or script elements as appropriate. If you do include #certification in the head it may work in some browsers, but it's not a good plan.

The rule isn't really very complicated. In order for any given script to refer to an element the script must run after the element has been added to the DOM. So either:

  • include the script element after the element(s) it references
  • include the script in a DOM ready (or onload) handler
  • both of the above

Note that you can include multiple script blocks on the page, so you can include just the $("#certification").multiselect({...}) part in its own script element located immediately after the #certification element and then include other scripts somewhere else (e.g., in a DOM ready handler in the head, or at the end of the body just before the closing </body> tag).

EDIT: From some comments you posted under another answer, "Won't the $ entail waiting for the DOM to finish loading still?" and "So I can't avoid using the $() ready handler? Is there no way to write jquery without it?", and the fact that in your original question you talked about having two "$() aka ready handlers", it seems that you have misunderstood what the $() function does.

$() is just an alias for jQuery(), and creates a DOM ready handler only when passed a function as an argument. When you pass a string, as in $("#certification") that is nothing to do with creating ready handlers.

Upvotes: 1

Yair Nevet
Yair Nevet

Reputation: 13003

I'd like to load the jquery before the DOM is ready, but still be able to refer to #certification

How come?

The #certification is part of the DOM, how do you want to refer it before it's loaded?

If you'll run your script after the element deceleration is will make sense.

Upvotes: 1

user2253634
user2253634

Reputation: 76

No you cannot. Elements will not be available till the DOM is ready. or move the script after the element #certification. in your code. $(function(){}); makes sure that your script referring to the elements run fine (since the ready callback gets executed only when the document is ready), no matter where it is placed.

if you refer to the element via $('#certification') outside document.ready or before the element in DOM it just won't pick the element, same is the case with any selector,except for event delegation where you bind the event to the document head to be delegated to any matching selector(which is a different animal altogether)because document head is something you can refer to all the time.

Upvotes: 2

Jazzuzz
Jazzuzz

Reputation: 490

It depends on exactly what you're trying to do, a little more context would help. it's however worth noting that if you have that JS snippet in the head section (I'm assuming that's where you want to put it based on 'before DOM loads'), #certification will not exist as that refers to a DOM element with ID 'certification'.

More information on exactly what you're trying to do would help advise better.

What I would recommend is to make your block a function and call that on DOM ready as such:

function doMultiSelect(elem) {
  elem.multiselect({
     minWidth: "500",
     noneSelectedText: "Certification Testing: Start Time - End Time (EST):",
     selectedText: function(numChecked, numTotal, checkedItems){
     return 'Certification Testing: ' + numChecked + ' of ' + numTotal + ' checked';
    }
 });
}

and then you can call it on DOM ready with

$(function() {
  doMultiSelect($("#certification"));
});

I just saw your clarification. Do:

<div id="certification""></div>
<script> $("#certification").multiselect.......</script>

That should work just fine

Upvotes: 2

dandavis
dandavis

Reputation: 16726

one universal way is to poll for element availability, and defer until it's there:

(function doit(){
          var fields= $("#certification");
         if(!fields.length){return setTimeout(doit, 50);}
            fields.multiselect({
               minWidth: "500",
               noneSelectedText: "Certification Testing: Start Time - End Time (EST):",
               selectedText: function(numChecked, numTotal, checkedItems){
                   return 'Certification Testing: ' + numChecked + ' of ' + numTotal + ' checked';
               }
           });
    }());

i would prefer to use an event or a delegated observer, but this will work if you can't order the tags in an optimal way.

Upvotes: 1

Jason P
Jason P

Reputation: 27012

The #certification element needs to exist in order to select it. You should be able to put the script after the definition of the element and be ok.

OK:

<script>
    $(function(){
        $('#certification').whatever();
    });
</script>
<div id="certification"></div>

NOT OK:

<script>
    $('#certification').whatever();
</script>
<div id="certification"></div>

OK:

<div id="certification"></div>
<script>
    $('#certification').whatever();
</script>

Upvotes: 5

Related Questions