Script Elements

Dr. Greg Bernstein

Updated September 12th, 2021

Script Elements

References

Embedded Script

<script>
    // Any JavaScript you like
    let myObj = {board: "Slalom", sail: "TRX 6.6m"}
    function square(x) {
        return x*x;
    }
</script>

External Script

<script src="ExternalScript.js"></script>

Note that you need both opening <script> and closing tags </script> even though the contents are empty.

Example with Internal script

EmbeddedScript.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>A Simple Embedded Script Example</title>
        <meta name="description"
              content="Demonstrating some simple DOM manipulation">
        <meta name="author" content="Dr. Greg M. Bernstein">
        <style><!-- Just a bit of style -->
            body {margin: 2em;}
            section {
                min-height: 50px;
                border: blue 1px solid;
            }
            .anoying {
                background-color: fuchsia;
                color: aliceblue;
                font-weight: bold;
            }
        </style>
    </head>

    <body>
        <h1>Embedded JavaScript Example</h1>
        <p>Here we will show running some simple
        functions. The first will run automatically and
        add some elements to the next section.</p>
        <section id="First">
            <h2>Below is Stuff Added By the Script</h2>
        </section>
        <p>To add stuff to the next section call the <code>second()</code>
            function from the console.</p>
        <section id="Second">
        </section>

        <script>
            let firstSection = document.getElementById("First");
            let myPara = document.createElement("p");
            // Using a multi-line string here
            myPara.innerHTML = `Hi! This text was automatically generated
                by some javascript`;
            firstSection.appendChild(myPara);

            /*  A function that inserts some text specifically for
                the user with "name". Note we set a default value
                for the name parameter. */

            function second(name="World") {
                let secSection = document.getElementById("Second");
                let myH2 = document.createElement("h2");
                myH2.innerHTML = `Hello ${name}!`;
                let myPara = document.createElement("p");
                myPara.innerHTML = `This text was generated on the demand just
                        for you ${name}.`;
                secSection.appendChild(myH2);
                secSection.appendChild(myPara);
            }

            function anoy() {
                let secSection = document.getElementById("Second");
                secSection.classList.toggle("anoying");
            }
        </script>

    </body>

</html>

Hands On

Get the file EmbeddedScript.html from the course resources.

  • Open the browser developer tools console. From the console:
  • Run the function second("Your Name Here")
  • Run the function anoy() multiple times

How’s this work?

  • We use the document interface to get specific <section> elements.
  • We use the document.createElement() to create new elements.
  • We set the innerHTML of those elements
  • We use the Node.appendChild() method (on our section elements) to add content.

A slightly Different Example

EmbeddedScript2.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>A Bad Embedded Script Example</title>
        <meta name="description"
              content="Demonstrating some simple DOM manipulation">
        <meta name="author" content="Dr. Greg M. Bernstein">
        <style><!-- Just a bit of style -->
            body {margin: 2em;}
            section {
                min-height: 50px;
                border: blue 1px solid;
            }
            .anoying {
                background-color: fuchsia;
                color: aliceblue;
                font-weight: bold;
            }
        </style>
    </head>

    <body>
        <script>
            let firstSection = document.getElementById("First");
            let myPara = document.createElement("p");
            // Using a multi-line string here
            myPara.innerHTML = `Hi! This text was automatically generated
                by some javascript`;
            firstSection.appendChild(myPara);

            /*  A function that inserts some text specifically for
                the user with "name". Note we set a default value
                for the name parameter. */

            function second(name="World") {
                let secSection = document.getElementById("Second");
                let myH2 = document.createElement("h2");
                myH2.innerHTML = `Hello ${name}!`;
                let myPara = document.createElement("p");
                myPara.innerHTML = `This text was generated on the demand just
                        for you ${name}.`;
                secSection.appendChild(myH2);
                secSection.appendChild(myPara);
            }

            function anoy() {
                let secSection = document.getElementById("Second");
                secSection.classList.toggle("anoying");
            }
        </script>

        <h1>Embedded JavaScript Example</h1>
        <p>Here we will show running some simple
        functions. The first will run automatically and
        add some elements to the next section if it can...</p>
        <section id="First">
            <h2>Below is Stuff Added By the Script</h2>
        </section>
        <p>To add stuff to the next section call the <code>second()</code>
            function from the console.</p>
        <section id="Second">
        </section>

    </body>
</html>

Running it…

Error with script screen

What Went Wrong 1

  • The initial code in the script ran into an error
  • Try clicking on the error message
  • Look at that nice debugger…

What Went Wrong 2

What Went Wrong 3

  • It appears that our variable firstSection is null.
  • How can that be? It’s in the HTML.
  • What’s the difference between EmbeddedScript.html and EmbeddedScript2.html?

Order Matters

  • The browser processes the HTML document from top to bottom including scripts.
  • If the script want access to an HTML element it needs to wait for that element to be created.

Solution #1

  • To avoid this problem you can put your <script> elements at the end of your HTML file before the closing </body> tag.
  • But doesn’t this go against the concept of unobtrusive JavaScript. Yes, but sometimes its easiest. I do this with prism.js to add code highlighting to my otherwise static HTML files.

Solution #2 and #3

  • Set the window.onload function to initialize document dependent variables.
  • Create an event listener function to to initialize document dependent variables, and use window.addEventListener("load", callback)

Solution #2A

ExternalScript.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>A Bad Embedded Script Example</title>
        <meta name="description"
              content="Demonstrating some simple DOM manipulation">
        <meta name="author" content="Dr. Greg M. Bernstein">
        <!-- Including a stylesheet and our JavaScript code below -->
        <link rel="stylesheet" href="ExternalScript.css">
        <script src="ExternalScript.js"></script>
    </head>

    <body>
        <h1>Embedded JavaScript Example</h1>
        <p>Here we will show running some simple
        functions. The first will run automatically and
        add some elements to the next section if it can...</p>
        <section id="First">
            <h2>Below is Stuff Added By the Script</h2>
        </section>

        <p>To add stuff to the next section call the <code>second()</code>
            function from the console.</p>
        <section id="Second">
        </section>
    </body>
</html>

Solution #2B

ExternalScript.js

/*  Wrapped up initial script stuff into a function */
function first() {
    let firstSection = document.getElementById("First");
    let myPara = document.createElement("p");
    // Using a multi-line string here
    myPara.innerHTML = `Hi! This text was automatically generated
    by some javascript`;
    firstSection.appendChild(myPara);
}

/*  A function that inserts some text specifically for
    the user with "name". Note we set a default value
    for the name parameter. */

function second(name = "World") {
    let secSection = document.getElementById("Second");
    let myH2 = document.createElement("h2");
    myH2.innerHTML = `Hello ${name}!`;
    let myPara = document.createElement("p");
    myPara.innerHTML = `This text was generated on the demand just
            for you ${name}.`;
    secSection.appendChild(myH2);
    secSection.appendChild(myPara);
}

function anoy() {
    let secSection = document.getElementById("Second");
    secSection.classList.toggle("anoying");
}

/*  The only line of code that actually is executed in this
    file. It assigns the window onload function to the
    function *first*. *first* will be called when the window
    has finished loading. You'll get used to passing around
    functions.
*/
window.onload = first;

How Does This Work 1

  • The script element was in the <head> before any of the body contents were defined.

  • Look at the last line of the script: window.onload = first;

  • When the document finishes loading the window object calls its onload function which we have assign to our first function.

How Does This Work 2

  • Hence the first function won’t be called till after all the elements in the body are created.

Solution #3A

ExternalScript2.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>A Bad Embedded Script Example</title>
        <meta name="description"
              content="Demonstrating some simple DOM manipulation">
        <meta name="author" content="Dr. Greg M. Bernstein">
        <!-- Including a stylesheet and our JavaScript code below -->
        <link rel="stylesheet" href="ExternalScript.css">
        <script src="ExternalScript2.js"></script>
    </head>

    <body>
        <h1>Embedded JavaScript Example</h1>
        <p>Here we will show running some simple
        functions. The first will run automatically and
        add some elements to the next section if it can...</p>
        <section id="First">
            <h2>Below is Stuff Added By the Script</h2>
        </section>

        <p>To add stuff to the next section call the <code>second()</code>
            function from the console.</p>
        <section id="Second">
        </section>
    </body>
</html>

Solution #2B

ExternalScript2.js

/*  Wrapped up initial script stuff into a function */
function first() {
    let firstSection = document.getElementById("First");
    let myPara = document.createElement("p");
    // Using a multi-line string here
    myPara.innerHTML = `Hi! This text was automatically generated
    by some javascript`;
    firstSection.appendChild(myPara);
}

/*  A function that inserts some text specifically for
    the user with "name". Note we set a default value
    for the name parameter. */

function second(name = "World") {
    let secSection = document.getElementById("Second");
    let myH2 = document.createElement("h2");
    myH2.innerHTML = `Hello ${name}!`;
    let myPara = document.createElement("p");
    myPara.innerHTML = `This text was generated on the demand just
            for you ${name}.`;
    secSection.appendChild(myH2);
    secSection.appendChild(myPara);
}

function anoy() {
    let secSection = document.getElementById("Second");
    secSection.classList.toggle("anoying");
}

/*  The only line of code that actually is executed in this
    file. It sets up the event listener for the windows "load"
    event that is fired when the document finishes loading. */
window.addEventListener("load", first);

Advantages of Event Listener

  • Multiple JavaScript files can add an event listener for window “load” events
  • Setting the window.onload function in a JavaScript file would override that function set in another JavaScript file.
// reveal.js plugins