User:Mike Dillon/Scripts/easydom.js
From Wikipedia, the free encyclopedia
If a message on your talk page led you here, please be wary of who left it. Code that you insert on this page could contain malicious content capable of compromising your account. If you are unsure whether code you are adding to this page is safe, you can ask at the appropriate village pump. If this is a .js page, the code will be executed when previewing the page.
Note: After saving, you have to bypass your browser's cache to see the changes. In Internet Explorer and Firefox, hold down the Ctrl key and click the Refresh or Reload button. Opera users have to clear their caches through Tools→Preferences, see the instructions for Opera. Konqueror and Safari users can just click the Reload button.
// <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", "style", "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", "fieldset", "legend" ]; // 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]; } } // If the browser doesn't understand createElementNS, fake it (God help them...) if (isUndefined(document.createElementNS)) { document.createElementNS = function (ns, name) { return document.createElement(name); }; } // Creates the DOM element var createDomElement = function(name) { return document.createElementNS(settings.namespaceUri, name); }; 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>

