Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/**
* @class Jaml
* @author Ed Spencer (http://edspencer.net)
* Jaml is a simple JavaScript library which makes HTML generation easy and pleasurable.
* Examples: http://edspencer.github.com/jaml
* Introduction: http://edspencer.net/2009/11/jaml-beautiful-html-generation-for-javascript.html
*/
Jaml = function() {
return {
templates: {},
/**
* Registers a template by name
* @param {String} name The name of the template
* @param {Function} template The template function
*/
register: function(name, template) {
this.templates[name] = template;
},
/**
* Renders the given template name with an optional data object
* @param {String} name The name of the template to render
* @param {Object} thisObj Optional data object
* @param {Object} data Optional data object
*/
render: function(name, thisObj, data) {
var template = this.templates[name],
renderer = new Jaml.Template(template);
return renderer.render.apply(renderer, Array.prototype.slice.call(arguments, 1));
}
};
}();
/**
* @constructor
* @param {String} tagName The tag name this node represents (e.g. 'p', 'div', etc)
*/
Jaml.Node = function(tagName) {
/**
* @property tagName
* @type String
* This node's current tag
*/
this.tagName = tagName;
/**
* @property attributes
* @type Object
* Sets of attributes on this node (e.g. 'cls', 'id', etc)
*/
this.attributes = {};
/**
* @property children
* @type Array
* Array of rendered child nodes that will be included as this node's innerHTML
*/
this.children = [];
};
Jaml.Node.prototype = {
/**
* Adds attributes to this node
* @param {Object} attrs Object containing key: value pairs of node attributes
*/
setAttributes: function(attrs) {
for (var key in attrs) {
//convert cls to class
var mappedKey = key == 'cls' ? 'class' : key;
this.attributes[mappedKey] = attrs[key];
}
return this;
},
/**
* Adds a child string to this node. This can be called as often as needed to add children to a node
* @param {String} childText The text of the child node
*/
addChild: function(childText) {
this.children.push(childText);
return this;
},
/**
* Renders this node with its attributes and children
* @param {Number} lpad Amount of whitespace to add to the left of the string (defaults to 0)
* @return {String} The rendered node
*/
render: function(lpad) {
lpad = lpad || 0;
var node = [],
attrs = [],
textnode = (this instanceof Jaml.TextNode),
multiline = this.multiLineTag();
//add any left padding
if (!textnode) node.push(this.getPadding(lpad));
//open the tag
node.push("<" + this.tagName);
for (var key in this.attributes) {
attrs.push(key + "=\"" + this.attributes[key] + "\"");
}
attrs.sort()
//add any tag attributes
for (var i=0; i\n");
} else {
node.push(">");
if (multiline) node.push("\n");
this.renderChildren(node, this.children, lpad);
if (multiline) node.push(this.getPadding(lpad));
node.push("", this.tagName, ">\n");
}
return node.join("");
},
/**
* Renders an array of children
* @node {Array} the current array of rendered lines
* @children {Array} the child nodes to be rendered
* @param {Number} lpad Amount of whitespace to add to the left of the string
*/
renderChildren: function(node, children, lpad) {
var childLpad = lpad + 2;
for (var i=0; i < children.length; i++) {
var child = children[i];
if (child instanceof Array) {
var nestedChildren = child;
this.renderChildren(node, nestedChildren, lpad)
} else {
node.push(child.render(childLpad));
}
}
},
/**
* Returns true if this tag should be rendered with multiple newlines (e.g. if it contains child nodes)
* @return {Boolean} True to render this tag as multi-line
*/
multiLineTag: function() {
var childLength = this.children.length,
multiLine = childLength > 0;
if (childLength == 1 && this.children[0] instanceof Jaml.TextNode) multiLine = false;
return multiLine;
},
/**
* Returns a string with the given number of whitespace characters, suitable for padding
* @param {Number} amount The number of whitespace characters to add
* @return {String} A padding string
*/
getPadding: function(amount) {
return new Array(amount + 1).join(" ");
},
/**
* Returns true if this tag should close itself (e.g. no element)
* @return {Boolean} True if this tag should close itself
*/
isSelfClosing: function() {
for (var i = this.notSelfClosingTags.length - 1; i >= 0; i--) {
if (this.tagName == this.notSelfClosingTags[i]) return false;
}
return true;
},
/**
* @property selfClosingTags
* @type Array
* An array of all tags that should be self closing
*/
notSelfClosingTags: ['textarea', 'script', 'em', 'strong', 'option', 'select']
};
Jaml.TextNode = function(text) {
this.text = text;
};
Jaml.TextNode.prototype = {
render: function() {
return this.text;
}
};
/**
* Represents a single registered template. Templates consist of an arbitrary number
* of trees (e.g. there may be more than a single root node), and are not compiled.
* When a template is rendered its node structure is computed with any provided template
* data, culminating in one or more root nodes. The root node(s) are then joined together
* and returned as a single output string.
*
* The render process uses two dirty but necessary hacks. First, the template function is
* decompiled into a string (but is not modified), so that it can be eval'ed within the scope
* of Jaml.Template.prototype. This allows the second hack, which is the use of the 'with' keyword.
* This allows us to keep the pretty DSL-like syntax, though is not as efficient as it could be.
*/
Jaml.Template = function(tpl) {
/**
* @property tpl
* @type Function
* The function this template was created from
*/
this.tpl = tpl;
this.nodes = [];
};
Jaml.Template.prototype = {
/**
* Renders this template given the supplied data
* @param {Object} thisObj Optional data object
* @param {Object} data Optional data object
* @return {String} The rendered HTML string
*/
render: function(thisObj, data) {
data = data || (thisObj = thisObj || {});
//the 'data' argument can come in two flavours - array or non-array. Normalise it
//here so that it always looks like an array.
if (data.constructor.toString().indexOf("Array") == -1) {
data = [data];
}
with(this) {
for (var i=0; i < data.length; i++) {
eval("(" + this.tpl.toString() + ").call(thisObj, data[i], i)");
};
}
var roots = this.getRoots(),
output = "";
for (var i=0; i < roots.length; i++) {
output += roots[i].render();
};
return output;
},
/**
* Returns all top-level (root) nodes in this template tree.
* Templates are tree structures, but there is no guarantee that there is a
* single root node (e.g. a single DOM element that all other elements nest within)
* @return {Array} The array of root nodes
*/
getRoots: function() {
var roots = [];
for (var i=0; i < this.nodes.length; i++) {
var node = this.nodes[i];
if (node.parent == undefined) roots.push(node);
};
return roots;
},
tags: [
"html", "head", "body", "script", "meta", "title", "link",
"div", "p", "span", "a", "img", "br", "hr", "em", "strong",
"table", "tr", "th", "td", "thead", "tbody", "tfoot",
"ul", "ol", "li",
"dl", "dt", "dd",
"h1", "h2", "h3", "h4", "h5", "h6", "h7",
"form", "fieldset", "input", "textarea", "label", "select", "option"
]
};
/**
* Adds a function for each tag onto Template's prototype
*/
(function() {
var tags = Jaml.Template.prototype.tags;
/**
* This function is created for each tag name and assigned to Template's
* prototype below
*/
var makeTagHelper = function(tagName) {
return function(attrs) {
var node = new Jaml.Node(tagName);
var firstArgIsAttributes = (typeof attrs == 'object')
&& !(attrs instanceof Jaml.Node)
&& !(attrs instanceof Jaml.TextNode);
if (firstArgIsAttributes) node.setAttributes(attrs);
var startIndex = firstArgIsAttributes ? 1 : 0;
for (var i=startIndex; i < arguments.length; i++) {
var arg = arguments[i];
if (typeof arg == "string" || arg == undefined) {
arg = new Jaml.TextNode(arg || "");
}
if (arg instanceof Jaml.Node || arg instanceof Jaml.TextNode) {
arg.parent = node;
}
node.addChild(arg);
};
this.nodes.push(node);
return node;
};
};
for (var i = 0, tag; tag = tags[i]; i++) {
Jaml.Template.prototype[tag] = makeTagHelper(tag);
};
})();
var Jaml;