How to correctly load dependent JavaScript files - javascript

I am trying to extent a website page that displays google maps with the LabeledMarker. Google Maps API defines a class called GMarker which is extended by the LabeledMarker.
The problem is, I cant seem to load the LabeledMarker script properly, i.e. after the Google API loads and I get the 'GMarker not defined' error.
What is the correct way to specify the scripts in such cases?
I am using ASP.NET's ClientScript.RegisterClientScriptInclude() first for the google API url and then immediately after with the LabeledMarker script file.
The initial google API loader writes further script links that load the actual GMarker class. Shouldnt all those scripts be executed before the next script block(LabeledMarker script) is processed.
I have checked the generated HTML and the script blocks are emitted in the right order.
<script src="google api url" type="text/javascript"></script>
...
(the above scripts uses document.write() etc to append further script blocks/sources)
...
<script src="Scripts/LabeledMarker.js" type="text/javascript"></script>
Once again, the LabeledMarker.js seems to get executed before the google API finishes loading.

I think that is the problem. I was calling google.load() in the body.onload which happened after loading the scripts. Resolved by emitting script tag for the LabeledMarker from within the onload handler.

Related

Embedding external script into Next.js application

I've been trying to embed an external JavaScript source into my Next.js application and keep receiving following error:
Failed to execute 'write' on 'Document': It isn't possible to write
into a document from an asynchronously-loaded external script unless
it is explicitly opened.
The code I am trying to use can be found here - The map with the vessel has an option to embed it. So far the component that generates this error looks like this:
<div className={styles['container']}>
<Script type="text/javascript">
var width="100%";var height="400"; var mmsi=228402900;
</Script>
<Script
type="text/javascript"
src="https://www.vesselfinder.com/aismap.js">
</Script>
</div>
If I copy the embed code into CodePen it works just fine - link to my codepen with the embedded map here.
Does somebody know what could be the problem here?
The issue occurs because the external script is being loaded asynchronously by next/script, thus ignoring the document.write() call present in the script.
From Document.write() MDN documentation:
Note: Using document.write() in deferred or asynchronous scripts will
be ignored and you'll get a message like "A call to document.write()
from an asynchronously-loaded external script was ignored" in the
error console.
You'll need to set the Script strategy to beforeInteractive so the script is added to <head>, and explicitly set the defer property to false to prevent the script from being loaded asynchronously.
<Script
type="text/javascript"
src="https://www.vesselfinder.com/aismap.js"
strategy="beforeInteractive"
defer={false}
></Script>

Make Google Tag Manager (GTM) pageview wait for spa url title

I have a React SPA that handles all the url's titles on the frontend, so the historyChange event regsitered on GTM is getting all the visited urls with their titles right.
However, on first load of the SPA, let's say, reload with F5, you can see how it takes some time until our code on the frontend is able to set the correct title. It looks like by that time, the pageview or the historyChange event has already been registered.
Here you can see how we load our GTM script, which loads analytics.js automatically because we have it linked from the GTM dashboard.
<script type="text/javascript" async="" src="https://www.google-analytics.com/analytics.js"></script>
<script type="text/javascript" async="" src="https://www.googletagmanager.com/gtm.js?id=GTM-WNJK84D"></script
Is there any way to wait for the title and avoid these incorrect data being registered?
Thanks a lot
In your GTM config, you need to get rid of the "All Pages" trigger for the GA tag (that loads analytics.js).
Then you'll want to replace that with a custom data layer event that your SPA will push to the datalayer e.g. datalayer.push({event:'my-app-load'}) then trigger your GA tag off of this new trigger.

ReferenceError: google is not defined (error after ajax call)

I got this error message for the google map after using ajax call.
ReferenceError: google is not defined
What I'm doing is I put the link "<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>" inside the file(showMap.php) being called by ajax.
However, if i refresh the page, the google map work fine. And if I put the link mentioned outside the file being called by ajax, for example(mainPage.php) , the google maps work fine also. Any idea on how to make the link working inside the showMap.php file?
What's happening is your code is executing before the Google library is loaded.
In order to execute the code for the map, reference it as a callback function on the Google Maps API URL.
For example: <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false&callback=init">/script>
<script>
function init() {
//doStuffWithMapsAp
};
</script>

Lazyloading Google API not working

Here's the deal. I've tried a number of methods of lazy loading the Google Maps API JavaScript, and every time in do it, with any Lazy Loader I use, FireFox "blocks." It lazy loads just fine in Chrome.
What I mean by "blocks" is that the elements in the HTML don't display, and instead, the browsers spin trying to make a connection to download the Maps JavaScript.
The code follows. Put it in an HTML file and open it in your browser:
<html>
<head>
<script type="text/javascript" src="http://github.com/rgrove/lazyload/raw/master/lazyload.js"></script>
</head>
<body>
Open your console. Wait for "entering debugger..." message.<br />
You can't see me in FireFox, can you?
<script type="text/javascript">
// If I remove the `sensor` from the query string key and value,
// Google rejects the request and alert() does occur
LazyLoad.js("http://maps.google.com/maps/api/js?sensor=false", function() {
console.log("entering debugger...");
});
</script>
</body>
</html>
In Chrome, I see the "Open your console..." contents of the page, and the JavaScript is requested and downloaded, async, in the background.
In FireFox, the "Open your console..." contents never appear, and it hangs (status bar says "Read" from a Google DNS), never finishing or displaying the page contents.
Are you sure you need to write your own loader? What about using a previously tested implementation: Lazy Load
Are you trying to load Google Maps on demand? To load the API dynamically, pass a callback parameter, as shown on the Example
I think you'll need to rename your LazyLoad script, because it already exists. :) Speaking of which, it already exists, so why write it again?
If you just want to see how it's done, the source code is available.
Yeah, why reinvent the wheel. You seem to be using jQuery.
try this plugin:
Load image only when it is viewable?
Found a solution:
Check the URL:'http://maps.google.com/maps/api/js?sensor=true'
You would find main.js is being imported by it . A simple getScript for sensor=true will not give whole google object so next import also required.
var t=setTimeout(function(){
jQuery.getScript('http://maps.google.com/maps/api/js?sensor=true');
jQuery.getScript('http://maps.gstatic.com/intl/en_us/mapfiles/api-3/10/20/main.js');
},1000);
PS: Similar issue thread Lazy loading google map api

Can I inject google AJAX API autoload anywhere else than globally?

There is this issue I am struggling with. I know that the autoload for the google visualization geomap must be in the part of your document.
The thing is every time I reload some other pages in my application the google reloads everything and this I want to take out. So I tried taking the :
<script type="text/javascript" src="http://www.google.com/jsapi?autoload=%7B%22modules%22%3A%5B%7B%22name%22%3A%22visualization%22%2C%22version%22%3A%221%22%2C%22packages%22%3A%5B%22geomap%22%2C%22table%22%5D%7D%5D%7D"></script>
out of my global template and inject it when the page call happens. So to only load the google API when I need it so to keep loading times to an absolute low. I want to know if this is do-able and if the google autoload MUST exist in the global at all times.
I am using Prototype Javascript framework and here is my code to inject the autoload :
var element = new Element('script', {
src: "http://www.google.com/jsapi?autoload=%7B%22modules%22%3A%5B%7B%22name%22%3A%22visualization%22%2C%22version%22%3A%221%22%2C%22packages%22%3A%5B%22geomap%22%2C%22table%22%5D%7D%5D%7D",
type: 'text/javascript'
});
$$('head')[0].appendChild(element);
This keeps it out of the rest of the site but doesn't work at all. Am I thinking about this wrong or is there some possibility of me only loading the API in one place and not everywhere.
Thank you
It seems like if you do it in the template of the view you are using it works fine. Every time the template gets rendered it refreshes the page resulting in the Google API code loading.

Categories