Angular 15: Scripts not loading correctly from angular.json - javascript

I have imported some js files into angular.json but I don't know why some work and others not.
angular.json:
"styles": ["src/styles.scss", "src/assets/css/all.min.css"],
"scripts": [
"./src/assets/global_assets/js/main/jquery.min.js",
"./src/assets/global_assets/js/main/bootstrap.bundle.min.js",
"./src/assets/global_assets/js/plugins/visualization/d3/d3.min.js",
"./src/assets/global_assets/js/plugins/visualization/d3/d3_tooltip.js",
"./src/assets/global_assets/js/plugins/ui/moment/moment.min.js",
"./src/assets/global_assets/js/plugins/pickers/daterangepicker.js",
"./src/assets/js/app.js",
"./src/assets/global_assets/js/demo_pages/dashboard.js",
"./src/assets/global_assets/js/plugins/visualization/echarts/echarts.min.js",
"./src/assets/global_assets/js/demo_charts/echarts/light/bars/columns_basic.js",
"./src/assets/global_assets/js/demo_charts/echarts/light/bars/columns_stacked.js",
"./src/assets/global_assets/js/demo_charts/echarts/light/bars/columns_thermometer.js",
"./src/assets/global_assets/js/demo_charts/echarts/light/bars/columns_stacked_clustered.js",
"./src/assets/global_assets/js/demo_charts/echarts/light/bars/waterfall_compositive.js",
"./src/assets/global_assets/js/demo_charts/echarts/light/bars/waterfall_change.js",
"./src/assets/global_assets/js/demo_charts/echarts/light/bars/columns_timeline.js",
"./src/assets/global_assets/js/plugins/tables/datatables/datatables.min.js",
"./src/assets/global_assets/js/demo_pages/datatables_basic.js"
]
What's going wrong and how can I fix it?
edit:
Sory for the vague question.
My file structure: File structure of angular project
chart.component.html:
<div class="chart-container">
<div class="chart has-fixed-height" id="columns_timeline"></div>
</div>
I call chart in test-dashboard.component.html:
<app-chart></app-chart>
After a while I realized that when script run at that time my "columns_timeline" node is not been created in DOM, I try to add initial function in setTimeout() and it work after I reload the page but not work for the first time:
columns_timeline.js:
var EchartsColumnsTimelineLight = (function () {
//...code
})();
document.addEventListener('DOMContentLoaded', function () {
setTimeout(() => {
EchartsColumnsTimelineLight.init();
}, 1000);
});
How can I make it run correctly!

sadly this doesn't show enough information about the issue. but something to bring to your attention which could fix your problem is the order in how these imports are placed could affect how they are working. scripts are loaded synchronously, in-order, so if script B has a dependency on script A then you should ensure that the tag for A appears before that for B.

Related

data-main attribute on <script> tag that doesn't load require.js works

I did somewhat an accident discovery that I was able to load my data-main js file in a file that doesn't load requireJS
<script type="text/javascript" src="requirejs.config.js" data-main="theme.js"></script>
<script type="text/javascript" src="requirejs.js"></script>
and it perfectly loads my theme.js file
is this an intentional feature of requirejs? or a bug?
I hope this isn't a bug.
the contents of my requirejs.config.js are below
var require = {
baseUrl: '/js/',
paths: {
'jquery': "lib/jquery/jquery",
'bootstrap': "lib/bootstrap/js/bootstrap"
},
shim: {
'bootstrap': ['jquery']
},
map: {
'*': {
'jquery': 'jQueryNoConflict'
},
'jQueryNoConflict': {
'jquery': 'jquery'
}
}
}
I check every samples here and seems they are not doing what I accidentally discovered.
http://requirejs.org/docs/api.html#data-main
I've been able to reproduce the behavior your report with RequireJS 2.1.20. You can see here the code that performs the check:
if (isBrowser && !cfg.skipDataMain) {
//Figure out baseUrl. Get it from the script tag with require.js in it.
eachReverse(scripts(), function (script) {
The eachReverse loop looks at all script elements in reverse order. Due to the way the DOM works, only the script element that loads RequireJS and those elements before it in the HTML will be looped over because the HTML is still in the process of being parsed by the browser when this code executes. (Consequently, the DOM nodes for the script elements after the one that loads RequireJS do not exist yet.) The function in the loop searches until it runs into a script element that has data-main. It could be the one that loaded RequireJS, or it could be any before it.
I don't know whether to consider this a bug or a feature with an unexpected side-effect. One might want to change the logic to check that the src attribute of the script element also points to a file containing RequireJS. However, it seems to me this would be brittle. (It cannot be just a naive file name comparison because if you decide to change the file name, the code will break.)
Your data-main is on the wrong script tag
<script type="text/javascript" src="requirejs.config.js"></script>
<script type="text/javascript" src="requirejs.js" data-main="theme"></script>
Also you don't need the .js
as per the require.js docs
<!--when require.js loads it will inject another script tag
(with async attribute) for scripts/main.js-->
<script data-main="scripts/main" src="scripts/require.js"></script>
EDIT:
Applogies... I misread the question.
I just had a quick look at the requirejs source code and the reason why this works is because it is finding all script elements (document.getElementsByTagName('script');) and iterating over them to find a data-main attribute. So actually in theory you could define more than one script with a data-main and it will load all of them.

Script that handles a tag that is within a angular template file does not work

I have this giant code, which is not necessary show here, but he will manipulate this div:
<div data-calendar="true"></div>
Finding like this:
var calendar = $('[data-calendar]');
The script works if the tag is within my main angular layout file, but when the tag is within a angular template file, the script does not work at all.
How fix that? I already put this script after the angular scripts, in order to make the angular scripts run before, but didn't work at all.
Including the script in the template is never going to work, you need to be able to control when it runs so that it will run any time that div is added, replaced, etc which could happen any time a digest happens.
The best way to do that in this case would be with a directive.
<div calendar></div>
.directive('calendar', function() {
return {
link: function (scope, element) {
element.jqCalendar(); // jQuery plugin should be avail here, if you included jQuery and the plugin before angular.
}
};
});

Link + on(pagecontainershow) fail

I have a simple app done with jQuery Mobile, in some point I have this:
Start!
which loads a new HTML with a lot of jquery mobile pages:
<div data-role="page">
I have defined, in my external JS file, an global variable:
var startTimeQuestion;
And this method, which is inside my HTML (test_es.html):
<script>
$(document).on('pagecontainershow', function() {
console.log("Storing time..");
startTimeQuestion = new Date().getTime();
});
</script>
The problem is that when I click on the button it loads correctly the file but it seems like it don't load the JS or the function or I don't know, because when I'm going to use my startTimeQuestion variable it says UNDEFINED and it don't show in the console the 'Storing time..'. If a reload the page, it works fine.
I have tried to do an '$.(document).ready()' function for the first time I load the page but still not working. It looks like test_es.html it isn't loading my custom.css and my test.js file until I reload completely the page. So I supposed that the error is in how I call my test_es.html, it isn't this:
Start!
the correct way to do it?
Thanks.
Thanks to the comment before I found the solution, it was as simple as put the 'data-ajax' attribute to false this way:
Start!

How to wait until DOM has loaded before adding script tags to <head>?

I'm implementing this Developr theme from themeforest into a Meteor app.
I'm currently accomplishing this by placing the javascripts in question to /public and appending them using jQuery:
Meteor.startup(function() {
$('head').append('<script src="/template_stuff.js"></script>');
// .. all 7 scripts or so
});
If the required scripts are placed in /client/js/, it appears that they either run too early or before the DOM is done loading. If they are placed directly in the header of the main html file, they seem to bug out the same way.
Am I missing something here - is there a more elegant way to make the scripts load after DOM has loaded?
There are several methods for waiting until the DOM has loaded to inject your scripts:
Meteor.startup (as you illustrated)
jQuery's document ready: $(function () { ... })
script tag at the bottom of your layout template
Regarding elegance, I use a handlebars helper as it allows me to consolidate all 'after body' code in one place. Then use jQuery's document ready as needed.
For example,
// in client/handlebars.js
Handlebars.registerHelper('afterBody', function(name, options) {
function isMobileSafari() {
return navigator.userAgent.match(/(iPod|iPhone|iPad)/) &&
navigator.userAgent.match(/AppleWebKit/)
}
if (isMobileSafari()) {
$(function () {
FastClick.attach(document.body)
})
}
//// load scripts however you want...
// $(function () {
// $.getScript as Daniel suggests
// $('body').append as you have
// pure js: document.createElement('script')
// })
})
// in client/main.html (using mini-pages router)
<template name="layout_no_header">
{{{yield}}}
{{afterBody}}
</template>
<template name="layout">
{{> header}}
{{{yield}}}
{{afterBody}}
</template>
Use jQuery getScript()
(function ($) {
$.getScript("/template_stuff.js");
})(jQuery);
I think you might have a different problem. It sounds like the 3rd party code is being wrapped in a closure and is not working correctly. Try and place them inside the client/compatibility folder. This will prevent it from being wrapped in a closure, which can solve 3rd party problems. Be sure the load order inside of here is correct, it loads files in alphabetical order inside of a folder. (load order)
If that doesn't work, find out where the code is being executed and comment out the call. Then load your html inside of a template, even if it's just a 'page' template with all the html. Create a js file for the template and call the methods in the templates rendered callback.
// Execute this function when myPage template is rendered
Template.myPage.rendered = function() {
stuff.init();
stuff2.run();
};
Note, the to call stuff2, etc.. you'll likely need to have it's script in the compatibility folder so you can reach the namespaces from the template_stuff.js.

How can I use an external js file for my popcorn.js script?

So it works perfectly when it's inline between tags, but how can I put this in an external js file and have it run? I copied it verbatim and it won't work. What's the issue?
edit: you can see the tutorial I'm working off of here: http://popcornjs.org/popcorn-101
code:
// ensure the web page (DOM) has loaded
document.addEventListener("DOMContentLoaded", function () {
// Create a popcorn instance by calling Popcorn("#id-of-my-video")
var pop_Stephen = Popcorn("#vid_Stephen");
// add a footnote at 2 seconds, and remove it at 6 seconds
pop_Stephen.footnote({
start: 2,
end: 6,
text: "Pop!",
target: "pop"
});
// play the video right away
// pop_Stephen.play();
}, false);
edit: OK it seems that it just doesn't work within CODA2, which is a bummer. Any idea why this is?
I'm betting that your <script /> tags have you loading your external file before the Popcorn library.
Make sure you load
<script src="http://popcornjs.org/code/dist/popcorn-complete.min.js"></script>
before your external file.
Perhaps use the Utility Method Popcorn.getScript?
http://popcornjs.org/popcorn-docs/utility-methods/#Popcorn.getScript
from the site:
Popcorn.getScript("yourscript.js");

Categories