User:Mike Dillon/Scripts/easydom-dev.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"
    ];
 
    // 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) {
        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>