AngularJS - Include <script> after all directives have rendered - javascript

Apologies if this is an old question. I have spent a few hours searching for an answer but had no luck.
I'm attempting to convert an existing (primarily jQuery) application to use AngularJS. I've hit a problem where a JavaScript file I am including in index.html is being run too early when being included in my AngularJS application. i.e. by using a <script> tag:
<script type="text/javascript" src="/components/js/theme.js"></script>
This file contains a lot of jQuery which needs the rest of the page to have been rendered to have an effect. So is there a way I can include this script and ensure it is only loaded after the rest of the page has finished loading? I have a set of directives on the page and the script is being loaded before these are rendered.
Update:
Here is the structure of my index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<title>App Title</title>
<base href="/">
<!-- icons and CSS -->
<link href="/img/ico/favicon.ico" rel="shortcut icon"
type="image/vnd.microsoft.icon">
<link href="/css/bootstrap.min.css" media="screen" rel="stylesheet"
type="text/css">
<!-- External Libraries -->
<script type="text/javascript" src="/external/jquery/dist/jquery.min.js"></script>
<script type="text/javascript" src="/external/angular/angular.js"></script>
<!-- Angular Components -->
<script type="text/javascript" src="/components/services/ui.js"></script>
<script type="text/javascript"
src="/components/navigation/js/navigation.js"></script>
<!-- App set and config -->
<script type="text/javascript" src="/js/app/app.js"></script>
<script type="text/javascript" src="/js/app/config.js"></script>
<script type="text/javascript" src="/js/app/routes.js"></script>
<!-- endbuild -->
<!-- Precompiled HTML templates -->
<script type="text/javascript" src="/js/templates.module.js"></script>
</head>
<body ng-cloak>
<!-- directive -->
<top-nav-bar></top-nav-bar>
<div class="content">
<div class="container">
<!-- directive -->
<side-nav-bar></side-nav-bar>
<!-- angular view -->
<div ng-view></div>
</div>
</div>
<!-- directive -->
<adysis-footer></adysis-footer>
<!-- Bootstrapper -->
<script src='/js/app.bootstrap.js' type='text/javascript'></script>
<!-- JAVASCRIPT FILE WHICH NEEDS TO RUN AFTER PAGE HAS LOADED! -->
<script type="text/javascript" src="/components/js/theme.js"></script>
</body>
</html>
As you can see, the "theme.js" file is the last item of the <body>. I have stopped in the file to ensure it is being loaded. But this is always done before the rest of the page has rendered. Could some other JavaScript be interfering upsetting things? Note that I have not included all of the JavaScript files that are being included.
Update 2:
I've added further break points in the JavaScript functions for the directives you can see in my index.html. Each of them is stopped in after the theme.js is executed. I don't know why this is, so I'm mentioning this in case it gives more clues as to the problem.
Update 3:
The first line of the "theme.js" file is:
jQuery(document).ready(function($)
And then the function contains a long series of jQuery selectors to setup events and so on. My understanding is the point of this line is to wait until the document has been loaded. But could something in my setup, e.g. Angular, be preventing this from happening?
I've tried changing this line to:
angular.element(document).ready(function($)
and whilst this does lead to the content on the function to be run later, it's still not after the whole document has loaded.

Make sure it's at the end of your HTML Body and not in the header section. If it's in the head section it'll load before the page renders.

Related

How to fix bootstrap path not working when I put it inside a folder

It is my first time using bootstrap 3, what I want to do is to make a header so that I will just call the file whenever I will create a new page but the problem is that when I created a folder and inside is index.php when I put the code from the original file it didn't work.
Here is the image of what I did
Here is the image of the original
Here is the code in html (only the link and script)
<link href="vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
<link
href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i"
rel="stylesheet">
<!-- Custom styles for this template-->
<link href="css/sb-admin-2.min.css" rel="stylesheet">
<script src="vendor/jquery/jquery.min.js"></script>
<script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- Core plugin JavaScript-->
<script src="vendor/jquery-easing/jquery.easing.min.js"></script>
<!-- Custom scripts for all pages-->
<script src="js/sb-admin-2.min.js"></script>
<!-- Page level plugins -->
<script src="vendor/chart.js/Chart.min.js"></script>
<!-- Page level custom scripts -->
<script src="js/demo/chart-area-demo.js"></script>
<script src="js/demo/chart-pie-demo.js"></script>
I don't clearly get it, I mean I accessed the file path and try to recode it but still it won't show the design and functions in jquery, I hope someone can explain me since I am new to this.
add / to all src or href. it's different between /vendor and vendor.
you need to access file at root but not page/vendor

absolute path in HTML is not working

I'm trying to build a HTML template with a small javascript code. Here is the stuff... At the root, I built two files :
index.html
<!DOCTYPE html>
<html lang="fr">
<head>
<title>HTML Template</title>
<!-- Header initialized with /header-footer.js -->
</head>
<body>
<footer>
<!-- Footer initialized with /header-footer.js -->
<script type="text/javascript" src="/headerfooter.js"></script>
</footer>
</body>
</html>
headerfooter.js
(function () {
/*************** HEADER *****************/
const headerBeforeAppend = document.querySelector('head')
document.querySelector('head').innerHTML = `
${headerBeforeAppend.innerHTML}
<meta charset="UTF-8">
<meta content="width=device-width,initial-scale=1" name="viewport">
<!-- CSS -->
<!-- Google fonts -->
<link href="https://fonts.googleapis.com/css?family=Montserrat:100,400,700" rel="stylesheet">
<!-- Bootstrap, Materialize, etc... you see the idea -->
<!-- Javascript -->
<!-- Fontawesome -->
<script src="https://use.fontawesome.com/45d80bbe59.js"></script>
<!-- jQuery, Bootstrap scripts, etc... you see the idea -->
`
/*************** FOOTER *****************/
const footerBeforeAppend = document.querySelector('footer')
document.querySelector('footer').innerHTML = `
${footerBeforeAppend.innerHTML}
<!-- JQuery (for Bootstrap) -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<!-- Bootstrap CDN v4 alpha-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js" integrity="sha384-b/U6ypiBEHpOf/4+1nzFpr53nxSS+GLCkfwBdFNTxtclqqenISfwAzpKaMNFNmj4" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/js/bootstrap.min.js" integrity="sha384-h0AbiXch4ZDo7tp9hKZ4TsHbi047NrKGLO3SEJAg45jXxnGIfYzk4Si90RDIqNm1" crossorigin="anonymous"></script>
`
})()
The idea is, when I load the index.html in a browser, to have the headerfooter.js script to write my <head> section and my <footer> section with the <links> and <script> I need.
It's actually working perfectly when, for the script, the code I write is the relative path to the script : <script type="text/javascript" src="headerfooter.js"></script>, but it's not working with the absolute path to the root: <script type="text/javascript" src="/headerfooter.js"></script>.
This is a problem, because I would like this to be a template, so that I include this script in every html page I will create in my web folder without having to re-write the path everytime. Did I make a mistake somewhere ?
(PS: is it a bad practice trying to build a template like that ?)
How you run your page will matter.
If you're trying to run it with the file:// protocol (by just opening index.html), an absolute path won't resolve correctly. You'll want to somehow run an local server (there are dozens of ways to do this, depending what all you're using, too large a scope for this question).
If you are running some kind of local server (i.e., http://localhost), then try opening the file directly with http://localhost/headerfooter.js. If that doesn't work, your file isn't quite where you think it is.

Get progress for site - loading scripts & libraries

I have quite a bunch of script and libraries that I am using in my website, which takes like 5 to 8 seconds to load.
ex.
<script type="text/javascript" src="../lib_components/jquery/dist/jquery.min.js"></script>
<script type="text/javascript" src="../lib_components/bootstrap/dist/js/bootstrap.min.js"></script>
<script type="text/javascript" src="../lib_components/angular/angular.js"></script>
<script type="text/javascript" src="../lib_components/angular-resource/angular-resource.min.js"></script>
<script type="text/javascript" src="../lib_components/angular-bootstrap/ui-bootstrap-tpls.min.js"></script>
<script type="text/javascript" src="../lib_components/angular-cookies/angular-cookies.min.js"></script>
<script type="text/javascript" src="../lib_components/angular-ui-router/release/angular-ui-router.min.js"></script>
<script type="text/javascript" src="../lib_components/lodash/dist/lodash.min.js"></script>
<script type="text/javascript" src="../scripts/js/overdo.js"></script>
I want to show a loading bar till all the scripts have been loaded, can anyone guide me on whats needs to be done for that?
There is very simple approach you can use in case when all the scripts you want to load are loaded synchronously (you don't use modules loader, async attributes, etc) - like in your example.
The trick is add progress indicator script the very first on the page, before all your heavy scripts. It is also make sense to inline this script (because it shouldn't be too big ideally):
<script>
// some progress bar implementation progress.show()
console.log('showing progress, loading bar, etc.');
</script>
<script src="../lib_components/jquery/dist/jquery.min.js"></script>
<script src="../lib_components/bootstrap/dist/js/bootstrap.min.js"></script>
<script type="text/javascript" src="../lib_components/angular/angular.js"></script>
<script src="../lib_components/angular-resource/angular-resource.min.js"></script>
<script src="../lib_components/angular-bootstrap/ui-bootstrap-tpls.min.js"></script>
<script src="../lib_components/angular-cookies/angular-cookies.min.js"></script>
<script src="../lib_components/angular-ui-router/release/angular-ui-router.min.js"></script>
<script src="../lib_components/lodash/dist/lodash.min.js"></script>
<script src="../scripts/js/overdo.js"></script>
<script>
// hiding loading bar
console.log('scripts loaded')
</script>
Now, for the implementation of the actual progress bar, it's up to you how and what to render. However, remember that depending on where you put those scripts DOM tree might not be loaded yet (if scripts are in <head>). I would anyway recommend to place scripts before closing </body>. The ideal structure for this approach would be:
<!DOCTYPE html>
<html>
<head>
<!-- some styles, no scripts here -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.css" />
<link rel="stylesheet" href="assets/styles.css" />
</head>
<body>
<div class="loading" hidden>Loading...</div>
<!-- Some application HTML code -->
<script>
// show/create progress/loading
var loading = document.querySelector('.loading')
loading.hidden = false
</script>
<!-- many script tags ... -->
<!-- ... -->
<script>
// hide/remove progress/loading
loading.parentNode.removeChild(loading)
</script>
</body>
</html>

HTML Tail Tag to complement Head Tag

So typically, in our HTML files, the general structure looks a bit like this:
<!DOCTYPE HTML>
<html lang="en">
<head>
<!-- Favicon -->
<!-- Meta Stuff -->
<!-- Title -->
<!-- CSS Files -->
<!-- JavaScript Files -->
<!-- Other Header Stuff -->
</head>
<header>
<!-- Navbar & Header Stuff -->
</header>
<body>
<!-- Body Stuff -->
</body>
<footer>
<!-- Copyright & Footer Stuff -->
</footer>
</html>
However, I often find myself using JavaScript Files that need to be loaded after the body, or whatever element it interacts with. As such, the body may end up looking like this:
<body>
<!-- Body Stuff -->
<script src="..."></script>
<script src="..."></script>
<script src="..."></script>
...
<script src="..."></script>
</body>
Sure, I could merge all of that stuff into one large Script File, either manually or using some sort of compiler. I could even wrap all of my scripts into a separate div so that I can mark that as "separate" in my mind.
However, all I'm really doing is injecting a bunch of scripts at the end of my document. This stuff shouldn't really go in a body tag, because it's not actual content, just code.
To rectify this, I often use a tail tag, like so:
<!DOCTYPE HTML>
<html lang="en">
<head></head>
<header></header>
<body>
<!-- Body Stuff -->
</body>
<footer></footer>
<tail>
<script src="..."></script>
<script src="..."></script>
<script src="..."></script>
...
<script src="..."></script>
<script>(function() { console.log('Custom code'); })();</script>
</tail>
</html>
Browsers seem to be fine with this, and I'm happy with this solution. However, the tail tag isn't a part of the HTML specifications, and I've seen little to no usage of a tail tag, except old HTML4 stuff that used a tail tag as a footer tag.
So what I'm wondering is: Is this good practice? Are there any downsides to this approach?
I see where you're going with this. I've considered the same concept. There are valid cases for putting <script> tags at the bottom of a document, and they don't really need to be in the <body> tag -- except that there is no other valid place to put them (save the <head>). In lieu of creating invalid tags for organizational purposes, I have done the following:
<section id="tail">
...
</section>
</body>
With some CSS like
section#tail { display: none; }
to ensure there are no errant display effects.
Is this good practice?
No.
Are there any downsides to this approach?
You would have to perform exhaustive browser testing to see whether this worked, including text browsers and screen readers. Also, people may laugh at you, and Steve Faulkner will create an amusing meme about you... which is a downside if that may offend you.
Put all of your content in the body tag, and just place all of the scripts before the </body> tag, not wrapped in anything. They are not displayed, so there is no need to group them in an element.
<!DOCTYPE HTML>
<html lang="en">
<head></head>
<body>
<header></header>
<!-- Body Stuff -->
<footer></footer>
<script src="..."></script>
<script src="..."></script>
<script src="..."></script>
...
<script src="..."></script>
<script>(function() { console.log('Custom code'); })();</script>
</body>
</html>
Not good practice. As an alternative to including scripts within the <body></body> tags, you could leave them in the <head></head> section and the code you want after the page has loaded could be called using the following Jquery:
$( document ).ready(function() {
});
Or the following javascript:
window.onload = function() {
};
HTML Tail defines the HTML code to insert at the bottom of each HTML document, usually to include a link back to your home page or insert a small graphic. It is inserted as a table data element and is right aligned with the page.
Sorry, but I don't agree with your method.
Basic structure:
<!DOCTYPE html>
<html>
<head>
<!-- Some meta data -->
<!-- Title -->
<title></title>
<!-- Link to css script -->
<link rel="stylesheet" type="text/css" href="example.css"/>
</head>
<body>
<!-- Some Content -->
<!-- Script tag to .js source script -->
<script src="example.js"></script>
</body>
</html>
And simple explanation of a proper basic-page load:
When browser goes through that HTML script,
it first recognizes the type of a script defined,
then it runs onto a LINK tag, which directs it to the .css script. Browser reads it and first displays a style on a page,
then it goes through a BODY tag and displays a content,
and let's say at last, it runs onto a SCRIPT tag, which directs the browser to a .js script, reads it, and as last loads the interactivity to a page.
Which gives a user nicer experience when visiting some page.

Scripts in body tag aren't loading

I'm trying to load up angular inside my body tag but for some reason nothing is getting loaded, when I check the resources panel it only contains files from the head. If I move all this stuff to the head It shows up in resources and its loaded, but when in the body, it's unloaded.
<body>
<section ui-view=""></section>
<!-- inject:js-->
<script src="/angular/angular.js"></script>
<script src="/json3/lib/json3.js"></script>
<script src="/es5-shim/es5-shim.js"></script>
<script src="/jquery/dist/jquery.js"></script>
<script src="/angular-resource/angular-resource.js"></script>
<script src="/angular-cookies/angular-cookies.js"></script>
<script src="/angular-sanitize/angular-sanitize.js"></script>
<script src="/angular-animate/angular-animate.js"></script>
<script src="/angular-touch/angular-touch.js"></script>
<script src="/angular-ui-router/release/angular-ui-router.js"></script>
<!-- endinject-->
<!-- inject:files:js-->
<script src="/js/app.js"></script>
<!-- endinject-->
</body>
What's going on here? why is this not being loaded into the page?
I'm using gulp and gulp-webserver but that shouldn't be the cause.
<base href="http://localhost:9000">
was my problem. A difficult find, it was
<base href="localhost:9000">
before making the root directory obsolete!
Thanks for the help all!

Categories