0

I am trying to load "header.html" using jquery .load("file") function, apply css to the loaded elements (works) and then apply JS to the loaded elements, functions like floating menu on scroll, etc, this it not working however. This is the order I import the files in the head:

<!-- Elements going to be loaded are using this font-awesome css
so they must be loaded before anything -->
<link rel="stylesheet" href="awesome/css/font-awesome.min.css" />

<!-- Then importing the jquery -->
<script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript"></script>

<!-- This is the point where i load the header.html -->
<script src="js/indexLoad.js"></script>

<!-- Then apply css to the loaded elements (works) -->
<link rel="stylesheet" href="css/index.css" />

<!-- Then apply JS to the loaded elements (doesnt work) -->
<script src="js/index.js"></script>

Inside the header.html I import some elements like nav for example.
Then changing style to nav to display it in red.
When I use var newHeight = $("nav").position().top in the index.js I just get cannot read property value of null... Why did css apply styles to the loaded element and JS coudnt get em?

I properly use $(document).ready( function(){} in both .js files:

indexLoad.js

$(document).ready( function(){
    $("header").load("http://localhost/js/header.html");
});

index.js

$(document).ready( function(){
var newHeight = $("nav").position().top;
});
Alpha2k
  • 2,212
  • 7
  • 38
  • 65

2 Answers2

2

ALWAYS first load all the CSS files, and then the JS scripts. Always.

And all the JS that accesses DOM elements needs to be loaded after the DOM is ready. Either by using one of the handlers (like $(document).ready) or simply putting the script at the very end of the HTML body. (not sure if you were doing that to all the scripts, you probably are)

Since you're using an AJAX call to load the header, you need to wait for it to load in order for the nav element to be available to JS. So use the load() callback function to execute everything that manipulates the header markup.


Key stuff: And since you're loading index.js and indexLoad.js separately, you actually need some kind of coordination between them. I suggest setting up an event listener in the index.js file, and firing that event in the indexLoad.js once the header is ready (in the load() callback). Something like this:

indexLoad.js

$(document).ready( function(){
    $("header").load("http://localhost/js/header.html", function() {
        $('body').trigger('headerReady');
    });
});

index.js

$('body').on('headerReady', function(){
    var newHeight = $("nav").position().top;
    // everything else that requires header elements goes here
    // or under a similar listener
});

Here is a simple snipper that mimics this using a timeout to simulate the async call delay:

setTimeout(function(){
  $('body').append('<nav>Nav here</nav>');
  $('body').trigger('headerReady'); // simulating a 3s delay
  }, 3000);

$('body').on('headerReady', function() {
  alert('header is ready');
  $('nav').css('color', 'green');
  })
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
Shomz
  • 37,421
  • 4
  • 57
  • 85
0

JS is asynchronous, and therefore even if the newHeight measurement is made further down the page, it does not mean that it will be executed/run after the loading has completed. Instead, use callbacks:

$(document).ready( function(){
    $("header").load("http://localhost/js/header.html", function() {
        var newHeight = $("nav").position().top;
    });
});

... or deferred objects: Using jQuery load with promises

Community
  • 1
  • 1
Terry
  • 63,248
  • 15
  • 96
  • 118
  • the thing is that i cant use functions like that, they would be "bound" to that file only. If other functions depend of "nav" position for example, i wont be able to use them. – Alpha2k Dec 14 '14 at 11:42
  • Then your other option is to use deferred objects. When a `.done()` promise is passed, run functions that rely on `newHeight`. See the link in my answer. – Terry Dec 14 '14 at 12:08