6
\$\begingroup\$

The following code is designed to load and refresh JavaScript code from an external file sandbox.js and allow it to be refreshed dynamically and executed without reloading the entire page. The sandbox.js file is assumed to contain a function sandbox() which may contain arbitrary JavaScript code. As the title within the code below suggests, it's a sandbox intended for rapid testing of JavaScript code, where I can just save code in the IDE and execute the updated code immediately.

The most current version of this code is available here.

<!DOCTYPE html>
<html>
    <head>
        <title>Sandbox</title>
        <meta charset="UTF-8">
        <link rel="stylesheet" href="/JSDev/styles.css">
    </head>
    <body onload="document.getElementById('refreshButton').click()">
        <h1>Sandbox</h1>
        <!--
            Change the parameter in the loadScript() call below to load
            JavaScript from another file. The code is designed to avoid
            repetition of the file name elsewhere in the code by having other
            buttons programmatically trigger this button.
        -->
        <button id="refreshButton" onclick="loadScript('sandbox.js')">
            Refresh script
        </button>
        <button id="runButton" onclick="sandbox()">
            Run script
        </button>
        <br>
        <button id="refreshRunButton" style="font-weight:bold"
                onclick="document.getElementById('refreshButton').click();
                         sandbox();">
            Refresh and run script
        </button>

        <script>
            function loadScript(location) {
                // Check for existing script element and delete it if it exists
                var js = document.getElementById("sandboxScript");
                if(js !== null) {
                    document.body.removeChild(js);
                    console.info("---------- Script refreshed ----------");
                }

                // Create new script element and load a script into it
                js = document.createElement("script");
                js.src = location;
                js.id = "sandboxScript";
                document.body.appendChild(js);
            }
        </script>
    </body>
</html>
\$\endgroup\$
5
\$\begingroup\$

This code is very clean, and I believe that it is a very useful tool for any JavaScript developer.


This is not very efficient:

<body onload="document.getElementById('refreshButton').click()">

Why? Well, think about what your code has to do:

  1. Locate refreshButton.

  2. Wait for refreshButton to load.

  3. Find its onclick method and call it.

Sure, this isn't terribly inefficient, but it can be made simpler.

I see what you are trying to do by not having the HTML code memorize anything; everything is handled in references which all boils down to a few elements.

While this is nice, it would be much more efficient if you called refreshButton's onclick method itself. So, you would just call loadScript:

<body onload="loadScript('sandbox.js')">

This:

if(js !== null)

Can be reduced to this:

if(js)

I think the way I wrote it is better, because the way I read your code is like this:

If the functions that JS is loaded with returned null...

And I read what I wrote as:

If JS exists...

This may just be me, however.

The reason why you can make this change is because, in JavaScript, null is a falsey value and therefore can be treated as though it were false.


Be careful with that runButton button. If the user acts too fast by quickly reloading the script and then trying to run it, there could be some problems; what if the script has not loaded yet?

Rather than silently failing and leaving a non-technically inclined user dumbfounded, it would be better to notify the user of problem (and prevent failing due to an attempt at trying to run a currently non-existent function).

Read this StackOverflow post for some ways you could check if the script has loaded.

In your case, you already have your work laid out for you: the sandbox.js source file creates a global sandbox function that you try to call.

Therefore, you can write this to make sure that the script has loaded:

if(typeof sandbox !== "undefined") {
    sandbox();
} else {
    window.alert("The script has not been loaded yet!");
}

In response to this comment:

"append the newly-created script element to the head": I'm following the JS book I'm studying from (I'm a neophyte at JS and the DOM, coming from C++). In fact, JS may not necessarily be best in head. (//stackoverflow.com/q/10994335)

This is a different response to that comment.

It doesn't matter where you put the scripts now that the browser has already fully loaded. The browser is not going to stop again and load the code (even if it did, that would be good (referencing to my response comment)).

\$\endgroup\$
3
  • \$\begingroup\$ "append the newly-created script element to the head": I'm following the JS book I'm studying from (I'm a neophyte at JS and the DOM, coming from C++). In fact, JS may not necessarily be best in head. stackoverflow.com/questions/10994335/… \$\endgroup\$ – bwDraco Jul 21 '15 at 22:58
  • \$\begingroup\$ @DragonLord Thanks for that tip! I don't believe I've seen that SO before. I have edited my answer and replaced that tip with a brand new one. \$\endgroup\$ – SirPython Jul 21 '15 at 23:06
  • \$\begingroup\$ @DragonLord About that SO post: while putting the code in the head forces the browser to "hang-up" a bit while trying to load the code, that may actually be a good thing; it would be bad to try and make function calls to libraries that do not exist yet because they haven't been loaded yet. For major libraries, you should put the script tag in the head, but if it's just something small, it's probably safest in the body. I'm going to edit that last tip back into my question. \$\endgroup\$ – SirPython Jul 21 '15 at 23:08

Not the answer you're looking for? Browse other questions tagged or ask your own question.