Document CreateTag Function

As I worked on the GameEngine improvements, I realized that it would be nice to have a menu and several other DOM elements. Since the engine will be standalone, it is necessary to dynamically create the DOM elements required to run the game. For this task, I have use a method "document.createTag()", which I often refactor for various projects. In its most basic form, it looks like the following:

Example 1: document.createTag

YAHOO.lang.augmentObject(document, {
/**
 * Creates and returns an html element and adds attributes from the hash.
 *
 * @method createTag
 * @param tagName {String} Required. Tag name to create.
 * @param h {Object} Optional. The hashtable of attributes, styles, and classes; defaults is empty object.
 * @return {Element} The newly created element; returns null otherwise.
 * @static
 */
createTag: function(tagName, h) {
	var Dom = YAHOO.util.Dom,
		node = document.createElement(tagName),
		hash = isType(h, object) ? h : {};

	// iterate through the possible attributes
	for (var k in hash) {
		var v = hash[k];
		k = k.toLowerCase();
		
		if (isType(v, string) || (style === k && isType(v, object))) {
			switch (k) {
				case classname:
				case klass:
				case class:
				case cls:
					Dom.addClass(node, v);
					break;

				case cellpadding:
					node.cellPadding = v;
					break;

				case cellspacing:
					node.cellSpacing = v;
					break;

				case colspan:
					node.colSpan = v;
					break;

				case checked:
				case disabled:
					node[k] = v;
					break;

				case rowspan:
					node.rowSpan = v;
					break;

				case style:
					// iterate through the style object
					for (var t in v) {
						var s = v[t];

						if (isType(s, string) || isType(s, number)) {
							Dom.setStyle(node, t, s);
						}
					};
					break;

				case innerhtml:
				case text:
					if (isType(v, string) && ! v.match(/< .*?>/) && ! v.match(/&.*?;/)) {
						node.appendChild(document.createTextNode(v));
					}
					else {
						node.innerHTML = v;
					}
					break;

				default:
					node.setAttribute(k, v);
					break;
			}
		}
	};

	return node || null;
}
});

To use this method, simply include it in your JavaScript source files, then call "document.createTag" passing in two parameters: 1st parameter is the tag name you wish to create, and the 2nd is an Object where the keys are tag attribute names and the values are the attribute values. Using a for … in loop we iterate on each key in the Object, evaluating only those values that are strings and numbers, or an object in the case of the style attribute. The switch statement then, normalizes the keys, so the key checked does the same thing as cHeCkEd, because capitalization does matter.

Over the years I have added each case of the switch statement based on issues experienced in various browsers. Most attributes seem to be applied just fine, when you use the setAttribute method, so this is the default case. Some attributes such as checked and disabled do not work in all browsers with setAttribute, so they are applied only with dot notation. Some attributes such as cellPadding and cellSpacing are case-sensitive in certain browsers (and capitalizing them doesnt break the browsers that lower-case worked in), and/or can only be applied via dot notation, so we special-case each of them. The word class is a reserved word in at least IE, so you cannot do "object.class", instead you need to use "object.className", and this seems to be supported by all browsers; I also support various ways of storing the classname as a key, because different projects have different naming conventions. Style is a special-case that must contain an object, where the keys are style names, and the values are what you want to set the style to (strings and integers are acceptable). Lastly, the text or innerhtml key will attempt to append the provided value as a text node, unless the value: isnt a string, contains HTML elements, or contains HTML special characters; in those cases it uses innerHTML, because it will render HTML and special characters correctly, while a text node will simply print the text as is.

Now, this method probably isnt perfect, but it works with all the browsers that I have ever needed to support. Feel free to chime in, if you know of any other special-case situations or browsers that you believe this method wont work with.

This solution is homegrown, and there may exist better DOM node creation methods, with more exposure and support. I know the Framework Ext.js has a DOM node creation method, and I wouldn&rsquot;t be surprised if Dojo or jQuery have a plugin solution as well.