Third party packages are getting undefined even after script loaded successfully - javascript

Third-party packages are getting undefined even after the scripts loaded successfully.
We are loading 4 third-party packages dynamically(Using CDNs) in React. We show a loading view when these CDNs are fetching, only after all the CDNs are loaded successfully then we show a UI using these packages.
Packages are
jquery-3.0.0.min.js
d3.v2.min.js
jquery.jsPlumb-1.3.10-all-min.js
jquery-ui.min.js
We are loading the scripts in the above order respectively.
Even after all the scripts loaded we are getting the below errors for some users.
$.isArray is not a function.
d3 is not defined
$('#' + domRootID).resizable is not a function.
Even if we are writing our logic after ready like below, the issues aren't resolved
$(document).ready(() => {
// Change the state variable to show the UI.
})
We aren't able to understand why we can't access third-party variables after the scripts are loaded.
Can someone suggest a solution for this?

Related

How to prevent Google Tag Manager overwriting document.write()?

We are using Angular for our Website. As not all Pages have been ported to Angular, we implemented a hybrid approach:
Every request goes to Angular first. When it has been loaded, it checks if the Route exists
If not, the HTML-page is fetched from the backend
The html-Element in the DOM (i.e. the complete page) is replaced with the response's body
ngOnInit() {
this.railsService.fetchRailsPage(this.router.url).subscribe(
(response) => this.replaceDOM(response),
(errorResponse) => this.replaceDOM(errorResponse.error)
);
}
private replaceDOM(newContent: string) {
document.open();
document.write(newContent);
document.close();
}
Since all a-hrefs in old pages are plain old hrefs (not Angular's routerLinks), once the user navigates away, the page is reloaded and Angular kicks in again.
So far, it works, but: I noticed that sometimes the DOM is not replaced with the response body.
Debugging brought us to the conclusion that Google Tag Manager could be the issue. It overwrites document.write() and a lot of other default Javascript functions.
Why is that? And how can this be prevented to get the default version of e.g. document.write()?
Seconding Alan here.
Please make sure you're running two tests:
Block gtm with the request blocking function of the dev tools and try reproducing the issue.
Try creating an empty GTM container, loading it on page and reproduce the issue.
If the first test shows that The issue persists with GTM blocked, then it's not GTM.
If the second test shows that the issue is solved, then it's not about GTM but about the logic used in it's configuration.
If anything, I would first make sure no custom code in GTM additionaly overrides document.write (which I've never seen before, but it's definitely possible). Then I would broadly audit all custom scripts deployed by GTM. After that, I would try pausing all the element visibility triggers if any are deployed and seeing if that helps.
GTM likely would aim to override write to be able to watch DOM changes. But it does so gently, adding a bit of tracking there and not changing the essence of it. It's severely unlikely that GTM's core logic would conflict with Angular.
//UPD just had a chat with a colleague on Measure. It looks like the only scenario when GTM overrides the document.write is when there are Custom HTML tags that have an option to "support document.write". The Element Visibility trigger uses mutation and intersection observers rather than listening to document.writes.

React + Meteor / 3 party jQuery libraries requires full page refresh before they function

I have a react + meteor application, and I'm facing an issue initializing third party jQuery libraries came in with the theme I'm using for my project.
Upon successful login I get redirected to (Dashboard) (3rd party libraries doesn't load).
However If I perform Full page re-fresh after login, all libraries works fine.
I'm wondering if someone has encountered such issue, your suggestions are appreciated.
You can use getScript method of jQuery. It will asynchronously load the script and you can also perform any operation when it is successfully loaded. Following snippet might help.
componentDidUpdate(){
let context = this;
$.getScript(<script source>, function(){
// this is a callback function called upon the script loading is finished
});
}

Dojo timing issue with dijit/registry and dojo/domReady

I am working on a one-page application in Dojo which submits forms via ajax and returns parses the return value before rendering the page. When I go about this I end up with a timing error.
When the following code is included via a script tag, it logs undefined:
require(["dijit/registry", 'dojo/domReady!'], function(registry){ console.log(registry.byId('my-id')) });
When I paste it in the console, I get the expected dijit widget.
I suspect that the problem is that this is firing before the page is rendered. Is there an easy way to ensure that this happens after the current document has been fully parsed and included in the main window?
May be you should try, to add Parser and call the Parser.parse() before trying to access the widget.
This is from Dojo documentation
Note that waiting for dojo/domReady! to fire is often not sufficient
when working with widgets. Many widgets shouldn’t be initialized or
accessed until the following modules load and execute:
dojo/uacss
dijit/hccss
dojo/parser

Uncaught Error: [$injector:modulerr] Failed to instantiate module with LABJS

I keep getting this error when loading my Angular app. In Chrome a couple refreshes and my app will run but IE and FF is a no go.
The error links me to this error page but I don't really understand what it says.
I am loading my app using LabsJS including the controllers and service.
// spAppLoader.js
$LAB
.script("../js/app.js").wait()
.script("../js/controllers/userCtrl.js")
.script("../js/controllers/groupCtrl.js")
.script("../js/controllers/siteCtrl.js")
.script("../js/services/userServices.js")
.script("../js/services/groupServices.js")
.script("../js/services/siteServices.js")
Markup:
<div id="mdContainer" ng-app="spApp" ng-cloak>
...
</div>
<script type="text/javascript" src="../js/spAppLoader.js"></script>
I wanted to post more code but I don't know where to start and with angular everything is in multiple files. I uploaded it through github.
You should manually bootstrap your app because you use an asynchronous script loader:
$LAB
.script("../js/app.js").wait()
.script("../js/controllers/userCtrl.js")
.script("../js/controllers/groupCtrl.js")
.script("../js/controllers/siteCtrl.js")
.script("../js/services/userServices.js")
.script("../js/services/groupServices.js")
.script("../js/services/siteServices.js")
.wait(function(){
var root = document.getElementById('mdContainer')
angular.bootstrap(root ,['spApp']);
})
What is bootstrapping?
angular.bootstrap(root ,['spApp']); is the same as <div id="mdContainer" ng-app="spApp"> only the last one would automatically initialize your app when DOMContentLoaded event occurs.
When using a script loader, DOMContentLoaded event might happen before all scripts are loaded, so you must wait for all your module scripts and then bootstrap your application manually.
In your case, chrome probably cached your scripts so after few refreshes the DOMContentLoaded event happened after all scripts were loaded.
From the docs:
Automatic Initialization
Angular initializes automatically upon DOMContentLoaded event or when the angular.js script is evaluated if at that time document.readyState is set to 'complete'. At this point Angular looks for the ng-app directive which designates your application root...
Manual Initialization
If you need to have more control over the initialization process, you can use a manual bootstrapping method instead. Examples of when you'd need to do this include using script loaders or the need to perform an operation before Angular compiles a page.
This error usually means angular can't find an object you are trying to inject into a controller or some other injectable function. After quickly looking through your code, my guess is that there is a problem with the way the files are being loaded, as you are referencing spApp from multiple files.
What I usually do is move separate files into their own modules, and then require other modules as needed. For example, instead of starting the userService like this:
spApp.factory('userService', function(){
put it into its own module
angular.module('spApp.services.user', [])
.factory('userService', function(){
Then whenever you need to use the userService in another module, add it as a requirement. Eg:
var spApp = angular.module('spApp', ['spApp.services.user']);

forcing page load on an AJAX-loaded page

I have an issue with an third-party integration on an iPad-specific website, which has a number of pages loaded via AJAX.
When I go to the page for the first time the functionality that is expected to be available is not, and only when I do a page refresh in Safari do I see the feature.
In the 3rd party JavaScript there is this sort of code peppered throughout:
script.onload = script.onreadystatechange = function () { // do something }
Here is the full JavaScript included file.
Is there a way that I can either force a page load on the iPad or build in some workaround that means that when I change to the page where the JavaScript is included and fires?
As I mentioned, this is only apparent on an iPad-specific website and the same feature has no problem on a desktop browser where the page is not loaded via AJAX.
i believe web servers allow you to add content dynamically for all pages rendered using the web server. which allows you to insert a code snippet which can ideally check if its a ipad website and do page load as you requested.
follow the below thread
http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/e27f918e-89a9-45a8-8604-2ad2ded09d64.mspx?mfr=true
I have no idea what your code looks like, but, having experienced the same issues repeatedly with jQuery, I would suggest you manually call the initialize function of the 3rd party script within a window ready state function:
$(window).ready(function(e) {
// function that initializes the 3rd party script gets called here.
});

Categories

Resources