failboat_cpt
failboat_cpt

Reputation: 57

JavaScript onclick functions unbound due to innerHTML usage

I have a function in javascript that I intend to use to create/add a link to a 'subLink' div, and add an onclick event to this link that loads associated 'content' to a contentDiv:

function addSubLink(text, name, content) {
// append programLink span to subLinks:
    document.getElementById("subLinks").innerHTML += "<span class=\"programLink\" id=\"" + name + "\">" + text + "</span>";
// load program content onclick:
    document.getElementById(name).onclick = function () {
        // set value of programContent to content's value
        document.getElementById("programContent").innerHTML = content;
    }
}

This function would be called, for example, by loadAboutPage() to populate the subLink div

var whatContent = "<p>A website!</p>";
var whyContent = "<p>Recreation!</p>";
var howContent = "<p>Kludges.</p>";
addSubLink("WHAT", "whatLink", whatContent);
addSubLink("WHY", "whyLink", whyContent);
addSubLink("HOW", "howLink", howContent);

The problem is that only the last subLink has an onclick event attached to it (content is loaded and css class changed). That is, it creates WHAT, WHY, and HOW links, but only appends the onclick function to the last called: HOW, in this case.

I'm very rusty when it comes to JavaScript, so I have no idea if it's a result of my lack of knowledge about anonymous functions, or using the local 'name' variable incorrectly, or anything else completely different. I've searched for awhile, but it seems I'm too ignorant to even figure out what a similar problem would be!

Anyway, I greatly appreciate your help! Thanks in advance!

EDIT:

Here's a complete HTML example:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>

        <title>Stack Overflow Example</title>
        <script type="text/javascript">

            function addSubLink(text, name, content) {
                document.getElementById("subLinks").innerHTML += "<span class=\"programLink\" id=\"" + name + "\">" + text + "</span>";
                document.getElementById(name).onclick = function () {
                    document.getElementById("program").innerHTML = content;
                }
            }

            window.onload = function() {
                var whatContent = "<p>A website!</p>";
                var whyContent = "<p>Recreation!</p>";
                var howContent = "<p>Kludges.</p>";
                addSubLink("WHAT", "whatLink", whatContent);
                addSubLink("WHY", "whyLink", whyContent);
                addSubLink("HOW", "howLink", howContent);
            }

        </script>
    </head>

    <body>
        <div id="container">
            <div id="programWindow">
                <div id="subLinks"> </div>
                <div id="program"> </div>
            </div>
        </div>
    </body>
</html>

Upvotes: 1

Views: 2710

Answers (1)

Jonathan Lonowski
Jonathan Lonowski

Reputation: 123443

The issue is due to:

....innerHTML += "...";

By setting innerHTML, all existing child elements are first removed, then the markup is parsed to create new elements. So, while the original "WHAT" and "WHY" spans did have onclick bindings, they've being replaced by similar elements that don't.

To append a new element and keep state, you'll want to use DOM methods like createElement(), appendChild(), and createTextNode() (or set textContent/innerText):

function addSubLink(text, name, content) {
    var span = document.createElement('span');
    span.className = 'programLink';
    span.id = name;
    span.appendChild(document.createTextNode(text));

// append programLink span to subLinks:
    document.getElementById('subLinks').appendChild(span);

// load program content onclick:
    span.onclick = function () {
        // set value of programContent to content's value
        document.getElementById("programContent").innerHTML = content;
    };
}

Example: http://jsfiddle.net/bG7Dt/

Upvotes: 6

Related Questions