User:Mike Dillon/Scripts/easydom.js
From Wikipedia, the free encyclopedia
Note: After saving, you have to bypass your browser's cache to see the changes. Firefox/Mozilla/Safari: hold down Shift while clicking Reload (or press Ctrl-Shift-R), Internet Explorer: press Ctrl-F5, Opera/Konqueror: press F5.
// <pre><nowiki> function buildEasyDomNamespace(namespace, options) { var isType = function (o, t) { return typeof o == t }; var isBool = function (o) { return isType(o, typeof true); }; var isString = function (o) { return isType(o, typeof ''); }; var isNumber = function (o) { return isType(o, typeof 0); }; var isFunction = function (o) { return isType(o, typeof function () {}); }; var isObject = function (o) { return isType(o, typeof new Object()); }; var isUndefined = function (o) { return isType(o, (function (x) { return typeof x })()); }; var isDefined = function (o) { return !isUndefined(o); }; // NOTE: null is "defined" var isPrimitive = function (o) { return isString(o) || isNumber(o) || isBool(o) || isFunction(o); } var isNode = function (o) { return isDefined(o) && o != null && isNumber(o.nodeType); } // Default tag names to be installed into the namespace as functions var defaultTagNames = [ "bdo", "script", "object", "param", "iframe", "link", "meta", "p", "pre", "a", "div", "span", "ul", "ol", "li", "img", "hr", "br", "em", "strong", "sup", "sub", "tt", "abbr", "acronym", "del", "ins", "cite", "blockquote", "code", "table", "tbody", "tfoot", "tr", "th", "td", "col", "colgroup", "caption", "form", "input", "select", "option", "optgroup", "button", "textarea", "h1", "h2", "h3", "h4", "h5", "h6", "label", "canvas" ]; // Default event types var defaultEventTypes = [ // HTML 4.0 "Abort", "Blur", "Change", "Click", "DblClick", "DragDrop", "Error", "Focus", "KeyDown", "KeyPress", "KeyUp", "Load", "MouseDown", "MouseMove", "MouseOut", "MouseOver", "MouseUp", "Move", "Reset", "Resize", "Select", "Submit", "Unload" ]; // Create an anonymous namespace if none was provided if (isUndefined(namespace)) namespace = {}; // Settings var settings = { "namespaceUri": "http://www.w3.org/1999/xhtml", "invokeFunctions": true, "tagNames": defaultTagNames, "eventTypes": defaultEventTypes }; // Override default settings with specified options if (options) { for (var p in options) { settings[p] = options[p]; } } // Creates the DOM element var createDomElement = function(name) { var elem = document.createElementNS(settings.namespaceUri, name); return elem; }; var defaultAttributeHandler = function (elem, attrName, attrValue) { // Invoke function callbacks of zero or one argument and use their result as the new attrValue if (settings.invokeFunctions && isFunction(attrValue) && attrValue.length <= 1) { attrValue = attrValue(elem); } // Skip null values if (attrValue == null) { return; } // Stringify non-string values if (!isString(attrValue)) { attrValue = attrValue.toString(); } // Set the attribute elem.setAttribute(attrName, attrValue); }; var createAttributeOverrideHandler = function (overrideName) { return function (elem, attrName, attrValue) { defaultAttributeHandler(elem, overrideName, attrValue); }; }; var createEventHandlerAttributeHandler = function (overrideName) { return function (elem, attrName, attrValue) { if (!isFunction(attrValue)) { attrValue = new Function(attrValue); } elem[overrideName || attrName] = attrValue; }; }; var attributeHandlers = {}; for (var i in settings.eventTypes) { var handlerName = "on" + settings.eventTypes[i]; var internalName = handlerName.toLowerCase(); // Force lower case attributeHandlers[internalName] = createEventHandlerAttributeHandler(); // Allow mixed case (with lower case internal name) attributeHandlers[handlerName] = createEventHandlerAttributeHandler(internalName); } // Conditionally add I.E. name overrides /*@cc_on attributeHandlers["for"] = createAttributeOverrideHandler("htmlFor"); attributeHandlers["maxlength"] = createAttributeOverrideHandler("maxLength"); attributeHandlers["class"] = createAttributeOverrideHandler("className"); attributeHandlers["accesskey"] = createAttributeOverrideHandler("accessKey"); attributeHandlers["style"] = function (elem, attrName, attrValue) { elem.style.cssText = attrValue; }; @*/ // Detects if the first element is a hash of attributes and if so, // uses it to set attributes on the DOM node // // Returns the number of elements processed to let the caller know // how many of the arguments to skip var processDomAttributes = function(elem, args) { if (args.length == 0) { return 0; } // No attributes to process if null is the first argument if (args[0] == null) { return 0; } // No attributes to process if a "primitive" is the first argument if (isPrimitive(args[0])) { return 0; } // No attributes to process if a DOM node is the first argument if (isNode(args[0])) { return 0; } // Process the first argument as a hash of attributes var attrs = args[0]; for (var attrName in attrs) { if (isUndefined(attributeHandlers[attrName])) { defaultAttributeHandler(elem, attrName, attrs[attrName]); } else { attributeHandlers[attrName](elem, attrName, attrs[attrName]); } } // Return the number of arguments processed return 1; }; // Create the function that creates new DOM element builders var createDomElementBuilder = function (name) { return function() { var elem = createDomElement(name); // Process attribute hash, if any and skip the argument count returned var firstChild = processDomAttributes(elem, arguments); // Process the remaining children, if any for (var i = firstChild; i < arguments.length; i++) { var child = arguments[i]; if (child == null) { continue; } // Convert any non-DOM nodes to text nodes with toString() if (!isNode(child)) { child = document.createTextNode(child.toString()); } elem.appendChild(child); } return elem; }; }; // Populate the namespace for (var i in settings.tagNames) { var tagName = settings.tagNames[i]; namespace[tagName] = createDomElementBuilder(tagName); } // Return the namespace for those relying on anonymous creation return namespace; } // Build the Easy DOM functions in an anonymous namespace easyDom = buildEasyDomNamespace(); // Namespace pollution easydom = easyDOM = easyDom; // </nowiki></pre>