Inserting a script tag with an external source and waiting for it to run

Is there a way to dynamically inject a

<script src="https://remote.com/"></script>
element into my page, wait for it to run, and then access the functions it defines?

Just to note, the script will handle credit card processing in certain cases, so I prefer not to include it unless necessary. I aim to include it swiftly when the user initiates a change-credit-card-options dialog, and then transmit the new credit card details to it.

Additional information: I do not possess the remote script.

Answer №1

You have the option to implement tracking via Google Analytics or utilize Facebook's approach:

(function(d, script) {
    script = d.createElement('script');
    script.type = 'text/javascript';
    script.async = true;
    script.onload = function(){
        // executed after the remote script is loaded
    };
    script.src = 'http://www.google-analytics.com/ga.js';
    d.getElementsByTagName('head')[0].appendChild(script);
}(document));

UPDATE:

Here's the updated Facebook method; it leverages an existing script tag instead of inserting it in the <head>:

(function(d, s, id){
    var js, fjs = d.getElementsByTagName(s)[0];
    if (d.getElementById(id)){ return; }
    js = d.createElement(s); js.id = id;
    js.onload = function(){
        // executed after the remote script is loaded
    };
    js.src = "//connect.facebook.net/en_US/sdk.js";
    fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
  • Make sure to replace facebook-jssdk with your unique script identifier to prevent duplication.
  • Also, update the URL of the script with your own.

Answer №2

Here is an alternative approach using event listeners and modern ES2015 syntax:

function loadExternalScript(src) {
    return new Promise((resolve, reject) => {
        const scriptElement = document.createElement('script');
        scriptElement.src = src;
        scriptElement.addEventListener('load', resolve);
        scriptElement.addEventListener('error', e => reject(e.error));
        document.head.appendChild(scriptElement);
    });
}

loadExternalScript('https://example.com/script.js')
    .then(() => {
        console.log('Script has been successfully loaded!');
    }).catch(error => {
        console.error(error);
    });

Answer №3

Here is a method to dynamically load and execute a series of scripts sequentially. It is necessary to add each script tag to the DOM while explicitly setting its async attribute to false:

script.async = false;

By default, injected scripts in the DOM are executed asynchronously, so manually setting the async attribute to false is essential to ensure synchronous execution.

Illustrative Example

<script>
(function() {
  var scriptNames = [
    "https://code.jquery.com/jquery.min.js",
    "example.js"
  ];
  for (var i = 0; i < scriptNames.length; i++) {
    var script = document.createElement('script');
    script.src = scriptNames[i];
    script.async = false; // Ensures synchronous execution
    document.head.appendChild(script);
  }
  // jquery.min.js and example.js will be executed in order and synchronously
})();
</script>

<!-- Note: these two script tags could still be executed before `jquery.min.js`
     and `example.js` -->
<script src="example2.js"></script>
<script>/* ... */<script>

References

Answer №4

Exploring Dynamic import()

With the help of dynamic import functionality, you can effortlessly load modules and wait for them to execute, like so:

import("http://example.com/module.js").then(function(module) {
  alert("module ready");
});

If the module has already been loaded and executed, it won't be reloaded and executed again. Nevertheless, the promise returned by import will still be resolved.

It's important to note that the file is loaded as a module, not simply as a script. Modules are run in strict mode, and they are loaded in module scope, which prevents variables from automatically becoming global as they would in traditionally loaded scripts. To share a variable with other modules or scripts, use the export keyword in a module.

Additional Resources:

Answer №5

Here's a simple solution for you:

(function() {
    // Creating a new script element
    var newScript = document.createElement("script");
    newScript.type = "text/javascript";
    newScript.onload = function() {
        // Removing onload handler
        newScript.onload = null;

        // Perform actions with the loaded script!

    }

    // Appending the script to the document
    (document.getElementsByTagName("head")[0]).appendChild(newScript);

    // Assign the source URL to start loading
    newScript.src = "https://example.com/";
})();

Hope this provides some assistance. Cheers!

Answer №6

Developing a Loading Function

To efficiently load scripts, it is advisable to organize the process within a loading function.

It is crucial to be aware that dynamically loaded scripts generally run after statically loaded scripts (such as

<script src="My_script.js"></script>
) regardless of the order in which they are injected into the DOM:

For example, consider the following loader.js script:

function loadScript(url){
   let script = document.createElement("script");
   script.src = url;
   script.async = false; //CRITICAL
   /*Node Insertion Point*/.appendChild(script);
}
loadScript("my_script1.js");
loadScript("my_script2.js");

The execution of my_script1.js will occur before my_script2.js, which is beneficial when there are dependencies between the two scripts.

It is emphasized to set script.async = false because dynamically loaded scripts default to async = true, which does not ensure the order of loading.

Answer №7

Here is an updated version of the code that includes a new expression to evaluate:

static async importScript(src, expressionToEvaluateAndReturn){

        return new Promise((resolve, reject) => {
            const script = document.createElement('script');
            script.async = true;
            script.src = src;
            script.addEventListener('load', (event)=>{
                if(expressionToEvaluateAndReturn){
                    try{
                        let result = eval(expressionToEvaluateAndReturn);
                        resolve(result);
                    } catch(error){
                        reject(error);
                    }
                    
                } else {
                    resolve();
                }
            });
            script.addEventListener('error', () => reject('Error loading script "' + src + '"'));
            script.addEventListener('abort', () => reject('Script loading aborted for "' + src + '"'));
            document.head.appendChild(script);
        });    
        
    }   

Here is an example of how to use this updated function:

let d3 = await importScript('/bower_components/d3/d3.min.js','d3')
                    .catch(error => {
                        console.log(error);
                        throw error;
                    });

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Retrieve a DOCX file via AJAX response

I am encountering an issue with a Django function that returns a file: ... return FileResponse(open('demo.docx', 'rb')) I am using ajax to fetch it on the client side. Now, I need to download it on the client side. This is the code I a ...

``To increase a value within an array object in MongoDB with the use of nodejs, what steps should be

Within my node.js application, I have a MongoDB post model that includes an array of comments. Each comment has a "likes" field representing the number of likes it has received. I want to increment this value for each comment individually. How can I achiev ...

Move content off the screen using CSS3 translation

Throughout various projects, I have encountered the need to make elements on a webpage translate out of view (essentially making them fly out of the document). The idea was that by simply adding a class to the element, the CSS would take care of the animat ...

Troubleshooting React Native in VS Code using Node shims

I recently started working on a React Native project using the Ignite CLI 2.0.0 default boilerplate, and I find myself in need of some dependencies from node-based packages. To address this, I created files named transformers.js, babel-transform.js, and r ...

Calculating the average value of an attribute in an array using Mongodb (Mongoose)

Seeking assistance with a query to find sellers near users based on location input and sorting them by average rating. Is this achievable? Snippet of the model including an array of reviews: const sellerSchema = new mongoose.Schema({ _id: Mongo ...

Engage in a conversation with a specific individual on the internet using node.js

Looking to implement a chat feature with specific online users similar to Facebook or Gmail using node.js and socket.io. Can anyone assist me with this? Thanks in advance! Client.html <html> <head> <title>My Chat App</title> <d ...

Do you only need to utilize Provider once?

When using the redux module in react-native, it is common practice to utilize createStore from 'redux'. I am curious, is it sufficient to use <Provider/> just once to make the Redux store accessible throughout our app? import ReactDOM from ...

Issue with React app: IconMenu does not expand when clicked

Seeking assistance with a react app and IconMenu from material-ui. I've been researching similar issues extensively but haven't found a solution yet :( In the code below, I am looking to manually trigger the expansion of a menu - this is essenti ...

The functionality of loading images with Jquery Ajax seems to only be working in Firefox. I have a feeling it may be due to a

I recently developed a web application that successfully loads images using a combination of jquery, ajax, and json. While it functions flawlessly in Firefox, Safari and Chrome present some stubborn challenges. The issue seems to stem from a "race conditi ...

Tips for repositioning a node element as the first child within its parent element

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div id='parent'> <div>B</div> <div>C</div> <div onload='this.parentNode.prependChild();'>A&l ...

Unlocking the potential of Node.js: Mastering the art of passing extra parameters in async

Exploring JavaScript and Node.js I'm currently working on developing some javascript / node.js code with a specific purpose in mind: To retrieve keys from a redis database and extract relevant information from the hash. Here is an example of what ...

Ways to utilize a string as an object?

Hey there! I'm just getting started with software development and currently working on an application using React Native. The backend is sending me a large data set, but here's a snippet of it. My challenge is that I want to access the first ele ...

During the process of adding a new template to my Angular project, I came across an issue within the core.min.js and script.js files

index.html <html class="wide wow-animation" lang="en"> <body> <app-root></app-root> <!-- Javascript--> <script src="assets/js/core.min.js"></script> <script src="assets/js/script.js"></script& ...

Understanding the Event Context of Elements using Browser Development Tools

I'm currently investigating the functionality of the search feature on the React Documentation page: https://reactjs.org/ . It's known that they utilize DocSearch, but I'm interested in understanding the inner workings. At the moment, I&ap ...

Is it possible to create a Facebook reveal tab using either Javascript or .NET?

As a developer who jumped into Facebook development just before the recent changes, I am feeling lost when it comes to building apps now. I see many questions similar to mine about creating fan-gating features using Javascript only. Is there an up-to-date ...

Modify the state's value by updating it when your information is stored in an array

I am currently working with contact numbers stored in an array and utilizing native-base for data viewing. this.state = { leadProfile: { contactNumber: [ { "lead_contact_number": "0912 312 412312", "lead_contact_nu ...

Interactive Map Displayed within a Pop-up Window

Recently, I developed a custom Google map where points are plotted and an HTML popup window appears when the image is clicked. Now, my goal is to open a file with JavaScript functions inside a lightbox/fancybox when a user clicks on an image. Below is th ...

Exploring Next.js: Advanced capabilities of shallow routing in combination with dynamic routes

Many people seem to be confused about the behavior of shallow routing with dynamic routes in Next.js. When attempting shallow routing, the page is refreshed and the shallow option is ignored. Let's consider a scenario where we start on the following ...

Expand and enhance your content with the Vue Sidebar Menu plugin

Recently, I integrated a side-bar-menu utilizing . My goal is to have a sidebar menu that pushes its content when it expands. Any suggestions on which props or styles I should incorporate to achieve this effect? Below is my Vue code: <template> ...

What is the process for submitting a record to a table following the activation of a JavaScript link or button

I am working on creating a like-unlike button below each post for registered users to interact with. I have successfully created the button itself, but now I need to figure out how to store records when a user clicks the button. My idea is to utilize a tab ...