1

I have a question. I'm trying to dynamically add menu elements to my web page. This issue is that I'm handling page navigation through a callback. With the code I'm using right now, only the LAST element of the array is ever functional. I'm not sure why this is, but I'd love some help here. I've also supplied a jsfiddle page so that you can see what's happening.

Code: https://jsfiddle.net/usz2nvqw/

HTML:
<div id='page_nav'>
    <!-- Navigation Elements -->
</div>


JAVASCRIPT:
var pages = {

    "home": {
        "resource_name": "Home",
        "name": "Home Page",
        "header": "Featured"
    },

    "catalogue": {
        "resource_name": "Browse",
        "name": "Browse Catalogue",
        "header": "Public Catalogue"
    }

};


$(document).ready(function () {
    for (var key in pages) {
        if (pages.hasOwnProperty(key)) {
            //Add a new link for the Menu Navigation Element
            document.getElementById('page_nav').innerHTML += "<a id='nav_" +     key + "'>" 
            + pages[key].name + "</a><br /><br />";

            //Create a new callback for the Menu Navigation Element
            $('#nav_' + key).click(createCallBack(key));
        }
    }

});

//Function for returning a callback
function createCallBack(key) {
    return function () {
        alert("Callback fired");
    }
}
Nathan F.
  • 3,250
  • 3
  • 35
  • 69
  • you can find answer why innerHTML doesn't work http://stackoverflow.com/questions/5113105/manipulating-innerhtml-removes-the-event-handler-of-a-child-element – xinyuan Aug 15 '15 at 04:37

2 Answers2

1

If you replace your link creation with jQuery it works

$(document).ready(function () {
    for (var key in pages) {
        if (pages.hasOwnProperty(key)) {

            $('#page_nav').append($('<a />', {
                id: 'nav_' + key
            }).text(pages[key].name))
                .append($('<br />'))
                .append($('<br />'));

            //Create a new callback for the Menu Navigation Element
            $('#nav_' + key).click(createCallBack(key));
        }
    }

});

https://jsfiddle.net/usz2nvqw/1/

Alternatively if you want the creation to be in plain javascript use

$(document).ready(function () {
    document.getElementById('page_nav').innerHTML = '';
    for (var key in pages) {
        if (pages.hasOwnProperty(key)) {
            //Add a new link for the Menu Navigation Element
            var nav = document.createElement("A");
            nav.id = "nav_" + key;
            var text = document.createTextNode(pages[key].name);
            nav.appendChild(text);
            document.getElementById('page_nav').appendChild(nav)
            //Create a new callback for the Menu Navigation Element
            $('#nav_' + key).click(createCallBack(key));
        }
    }

});

It seems to be a problem with using innerHTML, if you log $('#nav_' + key) before trying to add the first click handler you will see it doesn't exist yet

DGS
  • 6,015
  • 1
  • 21
  • 37
  • That leaves me curious. Do you know of any documentation that might explain why this is? And why my last element would always work? – Nathan F. Aug 15 '15 at 18:59
  • "-adding a string to the innerHTML property of an element will destroy all event handlers that were set on the descendants of that element. Holy cow! Now I know" -Sime Vidas Good to know :) – Nathan F. Aug 15 '15 at 19:51
-1
$(document).ready(function () {
    for (var key in pages) {
        if (pages.hasOwnProperty(key)) {
            //Add a new link for the Menu Navigation Element
            document.getElementById('page_nav').innerHTML += "<a id='nav_" +     key + "'>" 
            + pages[key].name + "</a><br /><br />";

            //Create a new callback for the Menu Navigation Element
            $('#nav_' + key).click(function(event){
                  // here your code
            });
        }
    }

});
Oleh Kurpiak
  • 1,339
  • 14
  • 34
  • The idea was to add a dynamic callback, this doesn't accomplish anything more than what I was already doing. – Nathan F. Aug 15 '15 at 18:58