User:Mike Dillon/Scripts/easydom.js

This is an old revision of this page, as edited by Mike Dillon (talk | contribs) at 15:18, 23 October 2006 (return after using direct property set to assign event handlers instead of allowing setAttribute to be called erroneously). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
// <pre><nowiki>

function createEasyDomFunction(name) {
    var stringType = typeof '';
    var functionType = typeof function() {};

    // Creates the DOM element
    var createDomElement = function(name) {
        var elem = document.createElement(name);
        return elem;
    };

    var attrNameTranslations = {
        // Aliases for old common HTML attribute typos
        "onClick" : "onclick"
    };

    // Conditionally add I.E. name overrides
    /*@cc_on
    attrNameTranslations["for"] = "htmlFor";
    attrNameTranslations["maxlength"] = "maxLength";
    attrNameTranslations["class"] = "className";
    attrNameTranslations["accesskey"] = "accessKey";
    @*/

    var processSingleDomAttribute = function(elem, attrName, attrValue) {
        // Translate DOM attribute name to match implementation
        if (attrNameTranslations[attrName] != null) {
            attrName = attrNameTranslations[attrName];
        }

        // Invoke function callbacks and use their result as the value,
        // unless the attribute name starts with "on" (i.e. an event handler)
        if (typeof attrValue == functionType) {
            // Use direct object property assignment for "on" attributes
            if (attrName.indexOf("on") == 0) {
                elem[attrName] = attrValue;
                return;
            }

            // Invoke the callback otherwise, passing null for "this"
            attrValue = attrValue.call(null, elem);
        }

        // Skip null values
        if (attrValue == null) {
            return;
        }

        // Set the attribute
        elem.setAttribute(attrName, 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;
        }

        // Detect string arguments
        var firstArgType = typeof args[0];
        if (firstArgType == stringType) {
            return 0;
        }

        // Detect function arguments
        if (firstArgType == functionType) {
            return 0;
        }

        // Detect DOM nodes
        if (typeof args[0].nodeType != 'undefined') {
            return 0;
        }

        // Assume that we got a hash of attributes as the first arg...
        var attrs = args[0];
        for (var attrName in attrs) {
            processSingleDomAttribute(elem, attrName, attrs[attrName]);
        }

        // Return the number of arguments processed
        return 1;
    };

    // Return the function that creates new DOM elements
    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 (typeof child == stringType) {
                child = document.createTextNode(child);
            }
            elem.appendChild(child);
        }

        return elem;
    };
}

var easyDomTags = [
    "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",
    "table", "tbody", "tfoot", "tr", "th", "td", "col", "colgroup", "caption",
    "form", "input", "select", "option", "optgroup", "button",
    "h1", "h2", "h3", "h4", "h5", "h6",
    "label"
];

var easyDom = {};
for (var i in easyDomTags) {
    easyDom[easyDomTags[i]] = createEasyDomFunction(easyDomTags[i]);
}

// Namespace pollution
var easydom = easyDom;
var easyDOM = easyDom;

// </nowiki></pre>