Script Elements

Dr. Greg Bernstein

September 3rd, 2019

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…

What Went Wrong?

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

What Went Wrong?

What Went Wrong?

  • 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.

External Scripts

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>

External Scripts

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?

  • 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 window finishes loading the HTML document it calls its onload function which we have assign to our first function.

How Does This Work?

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