TypeError: Argument 1 of Node.appendChild does not implement interface Node

kawerewagaba picture kawerewagaba · Apr 24, 2014 · Viewed 16.9k times · Source

Hi. I am new to object oriented JavaScript, and i cannot figure out what are interface nodes? Below is my code with the error is on line 96.

What may be the reason of this error and how to fix it?

window.onload=initAll;
////////////////////////////////////////////////////////////////////
var msg_dialog=new DialogBox();
var send_msg_but=new Button();
////////////////////////////////////////////////////////////////////
msg_dialog.tit="New Message";
msg_dialog.bod="The Message Body Shall Reside Here";
msg_dialog.fot=send_msg_but;
////////////////////////////////////////////////////////////////////
send_msg_but.label="Send";
send_msg_but.action=msg_dialog.done();
////////////////////////////////////////////////////////////////////
function initAll(){
    getDef();
}
function $(x){
    return document.getElementById(x);
}
function _(x){
    return document.createElement(x);
}
function getDef(){
    var xhr;
    var url="json/def.json";
    if(window.XMLHttpRequest){
        xhr=new XMLHttpRequest();
    }
    else{
        xhr=new ActiveXObject("Microsoft:XMLHTTP");
    }
    xhr.open("GET", url);
    xhr.onreadystatechange=function(){
        //creating the buffer div here creates 3 instances of the same object         because the state changes from 0 (initial) to 1, 2 then 3
        if(xhr.readyState==4 && xhr.status==200){
            var buffer=$("buffer");
            $("body_wrapper").removeChild(buffer);
            var data=xhr.responseText;
                data=JSON.parse(data);
            for(var i in data){
                var article=_("div");
                    article.setAttribute("id", "article");
                                                                                            ////////////////////////////////////////////////////////////////////
                var img=_("div");
                    img.setAttribute("id", "img");
                    var img_data=_("img");
                    img_data.src=data[i].img;
                img.appendChild(img_data);
                                                                                   /////////////////////////////////////////////////////////////////
            var caption=_("div");
                caption.setAttribute("id", "caption");
                                                                              //////////////////////////////////////////////////////////////////
            var title=_("div");
                title.setAttribute("id", "title");
                title.innerHTML=data[i].title;
                                                                                        /////////////////////////////////////////////////////////////////
            var story=_("div");
                story.setAttribute("id", "story");
                story.innerHTML=data[i].story;
                                                                                        ////////////////////////////////////////////////////////////////
            var hlink=_("div");
                hlink.setAttribute("id", "hlink");
                var a=_("a");
                a.href=data[i].href;
                a.innerHTML=data[i].htext;
                hlink.appendChild(a);
                                                                                          ///////////////////////////////////////////////////////////////
            caption.appendChild(title);
            caption.appendChild(story);
            caption.appendChild(hlink);
            article.appendChild(img);
            article.appendChild(caption);
            $("body_wrapper").appendChild(article);
        }
    }
}
xhr.send(null);
}
function DialogBox(){
    this.tit; this.bod; this.fot;
    this.render=function(){
    var win_width=window.innerWidth;
    var win_height=window.innerHeight;
    var dialog_box_width=(win_width*0.3); //measurements are in %
    ///////////////////////////////////////////////////////////////
    var dialog_box_overlay=$("dialog_box_overlay");
    dialog_box_overlay.style.display="block";
    ///////////////////////////////////////////////////////////////
    var dialog_box=$("dialog_box");
    dialog_box.style.left=(0.5*(win_width-dialog_box_width))+"px";                       //horizontally centre the div
        dialog_box.style.top=(0.1*win_height)+"px";
    dialog_box.style.width=dialog_box_width+"px";
    dialog_box.style.display="block";
    ///////////////////////////////////////////////////////////////
    $("dialog_box_head").innerHTML=this.tit;
    $("dialog_box_body").innerHTML=this.bod;
    $("dialog_box_foot").appendChild(this.fot);
}
this.done=function(){
    if(typeof $("dialog_box") !="undefined" && $("dialog_box")!=null){
        $("dialog_box").style.display="none";
    }
    if(typeof $("dialog_box_overlay") !="undefined" &&                                 $("dialog_box_overlay")!=null){
            $("dialog_box_overlay").style.display="none";
        }
                    if(typeof $("dialog_box_foot") !="undefined" &&                    $("dialog_box_foot")!=null){
            $("dialog_box_foot").innerHTML="";
        }
    }
} 
function Button(){
    var but_bod=_("span"); but_bod.setAttribute("class", "but");                             but_bod.addEventListener("click", this.action, false);     this.label;
}

Answer

Oriol picture Oriol · Apr 24, 2014

The problem is

function DialogBox(){
    $("dialog_box_head").innerHTML=this.tit;
    $("dialog_box_body").innerHTML=this.bod;
    $("dialog_box_foot").appendChild(this.fot);
}
var msg_dialog=new DialogBox();
msg_dialog.tit="New Message";
msg_dialog.bod="The Message Body Shall Reside Here";
msg_dialog.fot=send_msg_but;

When you use msg_dialog=new DialogBox(),

  • $("dialog_box_foot").appendChild(this.fot) runs first
  • msg_dialog.fot=send_msg_but runs after that

I suggest using

function DialogBox(tit, bod, fot){
    $("dialog_box_head").innerHTML = this.tit = tit;
    $("dialog_box_body").innerHTML = this.bod = bod;
    $("dialog_box_foot").appendChild( this.fot = fot );
}
var msg_dialog=new DialogBox(
    "New Message";
    "The Message Body Shall Reside Here";
    send_msg_but
);

Moreover, in Button you forgot to return the HTML element, in order to make send_msg_but a node, which can be appended:

function Button(){
    var but_bod=_("span");
    but_bod.setAttribute("class", "but");
    but_bod.addEventListener("click", this.action, false); // Note `this.action` is undefined
    this.label; // This does nothing, so better remove it
    return but_bod; // Add this
}