I have the following code which inserts a new element of the same type over and over again to the parent element. I am new to JavaScript so was wondering if there was a better way of doing this. I apologise for the variable names, I'll get around to changing those later, just allows me to see the flow better. I'm trying to write this in pure js.
//Add a new lobby element
document.getElementById("addLobby").addEventListener("click", function(e) {
var layer1 = document.createElement("div");
layer1.setAttribute("class","col-wd-12 col-md-6 col-sm-4");
var layer2 = document.createElement("div");
layer2.setAttribute("class","col lobby");
var layer3 = document.createElement("div");
layer3.setAttribute("class","col lobby-infoPanel");
var layer3v2 = document.createElement("div");
layer3v2.setAttribute("class","overlay lobby-overlay");
var layer3v2v1 = document.createElement("a");
layer3v2v1.setAttribute("href","#");
var l3v2v1v1 = document.createElement("span");
l3v2v1v1.setAttribute("class", "overlay-options lobby-overlay-options");
var layer4 = document.createElement("div");
layer4.setAttribute("class","col lobby-info-count");
var layer4v2 = document.createElement("div");
layer4v2.setAttribute("class","col lobby-info-count lobby-info-users");
var l3v2v1v1Text = document.createTextNode("+");
var l4text = document.createTextNode("5/5");
var l4v2text = document.createTextNode("@User1");
layer4v2.appendChild(l4v2text);
layer4.appendChild(l4text);
layer3.appendChild(layer4);
layer3.appendChild(layer4v2);
l3v2v1v1.appendChild(l3v2v1v1Text);
layer3v2v1.appendChild(l3v2v1v1);
layer3v2.appendChild(layer3v2v1);
layer2.appendChild(layer3);
layer2.appendChild(layer3v2);
layer1.appendChild(layer2);
var lastNode = document.getElementById("addLobby").parentElement;
lastNode.parentElement.insertBefore(layer1, lastNode);
});
-
1\$\begingroup\$ Try a loop. They are great and do all things. \$\endgroup\$user95591– user955912016年03月31日 17:39:34 +00:00Commented Mar 31, 2016 at 17:39
1 Answer 1
First suggestion
One first refactoring idea is to create a function that creates an element, sets its attributes and adds it to a parent element.
function createElement(elementType, classes, parent) {
var e = document.createElement(e);
e.setAttribute('class', classes);
parent.appendChild(e);
return e;
}
You could also separate your structure from your DOM manipulation. I suggest you create your structure as a JSON, and then create the nodes recursively.
For example, you could define your structure as:
{
element: 'div',
class: 'col-wd-12 col-md-6 col-sm-4',
children: [{
element: 'div',
class: 'col loby',
children: [
//...
]
},
// ...
}
and then:
function createDOMElements(data) {
// ...
// create the element
var elem = document.createElement(data.element);
// add its attributes
for (var attribute in data) {
if (data.hasOwnProperty(attribute) && attribute !== 'element' && attribute !== 'children') {
var attributeValue = data[attribute];
elem.setAttribute(attribute, attributeValue);
}
}
// ...
// add the children (forEach is from ES5 on)
data.children.forEach(function(child) {
// recursive call to create child elements
var childElement = createDOMElements(child);
elem.appendChild(childElement);
});
return elem;
}
Here is a jsfiddle with the whole working example.
Second suggestion (less JS)
You could create a hidden HTML 'template' and display it when needed.
You can set:
visibility
tohidden
if you still want to affect the layout (take the space needed)or
display
tonone
in css (more info here) directly in the style attribute or through a class. On the click event you make this element visible.
The HTML:
<div id="template" class="col-wd-12 col-md-6 col-sm-4" style="display:none;">
<!-- all the children -->
</div>
And then in the JS:
document.getElementById("addLobby").addEventListener("click", function(e) {
document.getElementById("template").style.display = "initial";
});
If you need to add the template multiple times, or if you have multiple templates on your page, you should define them at the end on the page. When needed, clone the template and append it to the desired parent.
Conclusion
If you don't have a particular need to create the elements in the JS, I think the second solution it's more elegant (and less code ;) )