Reputation: 260
I'm trying to make a completely pure JavaScript GUI for creating HTML content for learning purposes. The only real html in the file will be one <script></script>
element. I'm almost finished, I think.
I made a custom HTML element constructor, but when I create an object, [object Object]
is displayed instead of [object HTMLWhateverElement]
when I do alert(whatever);
(see the example below). I think that's preventing me from appending child elements to parent elements when both are made by the constructor.
If I could get HTML instances to append to HTML tags and element
instances, then I would be very happy.
function element(tagName) {
var element = document.createElement(tagName);
this.setText = function(elementText) {
if(element.childNodes.length < 1) {
var text = document.createTextNode(elementText);
element.appendChild(text);
} else {
element.childNodes[0].nodeValue = elementText;
}
}
this.removeText = function() {
element.removeChild(element.childNodes[0]);
}
this.setAttribute = function(attribute,value) {
element.setAttribute(attribute,value);
}
this.removeAttribute = function(attribute) {
element.removeAttribute(attribute);
}
this.appendTo = function(parent) { // Works but not on element instances of the constructor
parent.appendChild(element);
}
this.details = function(){
alert(
"Type: " + element +
"\n\"typeof\": " + typeof(element) // Shouldn't need this right?
);
}
}
ul = new element("ul");
ul.appendTo(body); // works fine if BODY is actually an HTML tag
alert(body); // gives me [object HTMLBodyElement] :)
alert(ul); // gives me [object Object] >(
li = new element("li"); // works :)
li.setText("list item text"); // works :)
li.appendTo(ul); // doesn't work >(
If I could just figure out how to append JavaScript-created (child) element
s to other JavaScript-created (parent) element
s, I'd be golden. I think it has to do with the return value of instantiated elements made by the constructor.
1) Possible answer
@carter-sand Thank you.
Adding a new this.appendChild
method works but reinvents the wheel
of HTML object's built in appendChild method.
2) Possible answer
@s4mok Thanks for the hint.
Changing var element
to this.elem
works but creates a
funky interface:
li.appendTo(ul.elem);
vs.
li.appendTo(ul);
I'm trying to emulate a private member.
Both answers work but neither return the value [object HTMLWhateverElement] when I do :
alert(li);
Is there a way to reap the benefits of all of the above?
Upvotes: 2
Views: 2792
Reputation: 1016
Your function returns an instance of itself [object Object] when created using the "new" keyword. You can override that by specifically returning your element. However you will then need to change "this" to your element instead because "this" refers to the function new instance. Also as suggested it may be less confusing if you changed "element" to something else like "newElement".
function element(tagName) {
var element = document.createElement(tagName);
element.setText = function(elementText) {
if(element.childNodes.length < 1) {
var text = document.createTextNode(elementText);
element.appendChild(text);
} else {
element.childNodes[0].nodeValue = elementText;
}
}
element.removeText = function() {
element.removeChild(element.childNodes[0]);
}
element.setAttribute = function(attribute,value) {
element.setAttribute(attribute,value);
}
element.removeAttribute = function(attribute) {
element.removeAttribute(attribute);
}
element.appendTo = function(parent) { // Works but not on element instances of the constructor
parent.appendChild(element);
}
element.details = function(){
alert(
"Type: " + element +
"\n\"typeof\": " + typeof(element) // Shouldn't need this right?
);
}
return element;
}
ul = new element("ul");
ul.appendTo(document.body); // works fine if BODY is actually an HTML tag
alert(document.body);
alert(ul);
li = new element("li");
li.setText("list item text");
li.appendTo(ul);
Upvotes: 2
Reputation: 568
ul = new element("ul");
The above line is instantiating the function element() and the instance which is assigned to ul is an object and not HTMLWhateverElement
ul.appendTo(body); // works fine if BODY is actually an HTML tag
The above works because your code is :
this.appendTo = function(parent) { // Works but not on element instances of the constructor
parent.appendChild(element);
}
whereas the parent is body and an HMTL Element and has a method appendChild, and the element that you are appending is the element from this line:
var element = document.createElement(tagName);
Why the below code does not work?
li = new element("li"); // works :)
li.setText("list item text"); // works :)
li.appendTo(li); // doesn't work >(
The answer to that is first of all li is not a HTML Element which the code
this.appendTo = function(parent) { // Works but not on element instances of the constructor
parent.appendChild(element);
}
will fail since the instance li is not an html element but rather an object instance of function element()
Another error in this code is that you have a circular li.appendTo(li); which if you inspect your code, you are appending as child li to itself. something like a paradox or a circular dependency.
EDIT:
My Recommendation:
Upvotes: 3
Reputation: 1849
If I run your example, I notice the following error message in the console:
Uncaught TypeError: Object #<element> has no method 'appendChild'
This is because your custom element
instance does not have the appendChild
method that you're using in appendTo
. You need to add one to your constructor, like this:
this.appendChild = function(child) {
element.appendChild(child);
}
Upvotes: 1