/*\
title: js/HTML.js
Represents a fragment of HTML as a JavaScript object tree structure. Helper methods are provided to simplify
constructing HTML trees and to render the tree as an HTML string.
The nodes in the tree have a `type` field that is the name of the node for HTML elements:
{type: "br", attributes: {name: "value"}}
Attributes values can be strings, arrays of strings or hashmaps. String arrays are
rendered by joining them together with a space. Hashmaps are rendered as `attr="name1:value1;name2:value2;"`.
Elements with child nodes are expressed as:
{type: "div", children: []}
Text nodes are represented as:
{type: "text", value: "A string"}
HTML entities are represented as:
{type: "entity", value: "quot"}
It is sometimes useful to be able to mix raw strings of HTML too:
{type: "raw", value: "Something
"}
Other types of node can also be placed in the tree, but they will be ignored by the built-in render function.
For example, nodes of type `"macro"` are used by the WikiTextParser.
\*/
(function(){
/*jslint node: true */
"use strict";
var utils = require("./Utils.js");
/*
Constructs an HTMLParseTree from a tree of nodes. A single node or an array of nodes can be passed.
As a shortcut, the constructor can be called as an ordinary function without the new keyword, in which case
it automatically returns the `text/html` rendering of the tree.
*/
var HTML = function(tree,type) {
if(this instanceof HTML) {
// Called as a constructor
this.tree = tree;
} else {
// Called as a function
type = type || "text/html";
return (new HTML(tree)).render(type);
}
};
/*
Static method to simplify constructing an HTML element node
type: element name
attributes: hashmap of element attributes to add
options: hashmap of options
The attributes hashmap can contain strings or hashmaps of strings, (they are processed to attr="name1:value1;name2:value2;")
The options include:
content: a string to include as content in the element (also generates closing tag)
classes: an array of classnames to apply to the element
selfClosing: causes the element to be rendered with a trailing /, as in
insertAfterAttributes: a string to insert after the attribute section of the element
*/
HTML.elem = function(type,attributes,children) {
var e = {type: type};
if(attributes) {
e.attributes = attributes;
}
if(children) {
e.children = children;
}
return e;
};
/*
Static method to construct a text node
*/
HTML.text = function(value) {
return {type: "text", value: value};
};
/*
Static method to construct an entity
*/
HTML.entity = function(value) {
return {type: "entity", value: value};
};
/*
Static method to construct a raw HTML node
*/
HTML.raw = function(value) {
return {type: "raw", value: value};
};
/*
Static method to construct a macro call
*/
HTML.macro = function(name,params,children,dependencies) {
var m = {type: "macro", name: name, params: params, dependencies: dependencies};
if(children) {
m.children = children;
}
return m;
};
/*
Static method to construct a split label
*/
HTML.splitLabel = function(type,left,right,classes) {
classes = (classes || []).slice(0);
classes.push("splitLabel");
return HTML.elem("span",{
"class": classes
},[
HTML.elem("span",{
"class": ["splitLabelLeft"],
"data-tw-label-type": type
},left),
HTML.elem("span",{
"class": ["splitLabelRight"]
},right)
]);
};
/*
Static method to construct a slider
*/
HTML.slider = function(type,label,tooltip,body) {
var attributes = {
"class": "tw-slider",
"data-tw-slider-type": type
};
if(tooltip) {
attributes.alt = tooltip;
attributes.title = tooltip;
}
return HTML.elem("div",
attributes,
[
HTML.elem("a",
{
"class": ["tw-slider-label"]
},[
HTML.text(label)
]
),
HTML.elem("div",
{
"class": ["tw-slider-body"],
"style": {"display": "none"}
},
body
)
]
);
};
/*
Render the HTML tree to a string, either of "text/html" or "text/plain"
*/
HTML.prototype.render = function(targetType) {
if(targetType == "text/plain") {
return this.renderPlain().join("");
} else if(targetType == "text/html") {
return this.renderHtml().join("");
} else {
return null;
}
};
/*
Render the HTML tree to a "text/html" string, returned as a string array
*/
HTML.prototype.renderHtml = function(output,node) {
output = output || [];
node = node || this.tree;
if(node instanceof Array) {
for(var t=0; t");
if(node.children) {
this.renderHtml(output,node.children);
output.push("",node.type,">");
}
break;
}
}
return output;
};
/*
Render the HTML tree to a "text/plain" string, returned as a string array
*/
HTML.prototype.renderPlain = function(output,node) {
output = output || [];
node = node || this.tree;
if(node instanceof Array) {
for(var t=0; t