If you are using PrototypeJS, you might also want to add script.aculo.us to your project. Builder in script.aculo.us provides a nice way to build complex DOM structures like so:
var myList = Builder.node("ul", {
id: "dom_a"
},[
Builder.node("li", "foo"),
Builder.node("li", "bar"),
]);
After this, you can insert this object which should be rendered as HTML anywhere in the DOM with any insert/update functions (of PrototypeJS) or even standard JavaScript appendChild.
$("my_div").insert({After: myList});
Note that in PrototypeJS insert comes in 4 different modes: After, Before, Top and Bottom. If you use insert without specifying a "mode" as above, the default will be Bottom. That is, the new DOM code will be appended below existing contents of the container element as innerHTML. Top will do the same thing but add it on top of the existing contents. Before and After are also cool ways to append to the DOM. If you use these, the content will be added in the DOM structure before and after the container element, not inside as innerHTML.
With Builder however, there is one thing to keep in mind, .. okay two things really:
i. You cannot enter raw HTML in the object as content... This will fail:
Builder.node("ul", "<li>foo</li>");
ii. When you specify node attributes, keep in mind that you must use className to signify HTML attribute class (and possibly also htmlFor for for attribute... although for attribute seems to be deprecated in HTML5(?), but who does not want to use it for labels)
Builder.node("ul", {
id: "dom_a",
className: "classy_list"
});
I know you are scratching your head because of point i. > What, no raw HTML, dang!
Not to worry. If you still need to add content which might contain HTML inside a Builder created DOM, just do it in the second stage using the insert({Before/After/Top/Bottom: string}). But why'd you want to do it in the first place? It would be really good practice if you wrote an once for all function that generates all kinds of DOM elements rather than stitching in all sorts of strings. The former approach would be neat and elegant. This is something like the inline style versus class type of question. Good design should after all separate content from meta content, or formatting markup / markdown.
One last thing to keep handy in your toolbox is Protype's DOM traversal in case you want to dynamically insert and delete content like a HTML Houdini. Check out the Element next, up, down, previous methods. Besides the $$ is also kinda fun to use, particularly if you know CSS3 selectors.