Suggested Extensions to MochiKit.DOM
Below follows a few suggested extensions to the MochiKit.DOM namespace. Please discuss bugs or issues with these on the mailing list and feel free to add any additional code snipplets here.
Predicate functions for DOM nodes
The MochiKit.DOM.isDOM function doesn't currently exist, but the typeof(obj.nodeType) == "number" and obj.nodeType > 0 tests are used all in a number of MochiKit functions handling DOM nodes. It would probably be a good idea to formalize the definition of what "looks like a DOM node" into a proper public API function.
// Namespace constants (already lives privately in MochiKit bootstrap code) MochiKit.DOM.NS = { HTML: [null, '', "http://www.w3.org/1999/xhtml"], XHTML: "http://www.w3.org/1999/xhtml", XLINK: "http://www.w3.org/1999/xlink", SVG: "http://www.w3.org/2000/svg", XUL: "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" }; /** * Returns true if the specified object looks like a DOM node. * Otherwise, false will be returned. Any non-null object with a * nodeType > 0 will be considered a DOM node by this function. * * @param {Object} obj the object to check * * @return {Boolean} true if the object looks like a DOM node, or * false otherwise */ MochiKit.DOM.isDOM = function(obj) { return typeof(obj) !== "undefined" && typeof(obj.nodeType) === "number" && obj.nodeType > 0; } /** * Returns true if the specified object looks like an HTML or XHTML * DOM node. Otherwise, false will be returned. Any non-null object * with a nodeType > 0 will be considered a DOM node, but only those * with a matching namespaceURI will be considered HTML DOM nodes. * * @param {Object} obj the object to check * * @return {Boolean} true if the object looks like an HTML DOM node, * or false otherwise */ MochiKit.DOM.isHTML = function(obj) { var htmlNs = MochiKit.DOM.NS.HTML; return MochiKit.DOM.isDOM(obj) && MochiKit.Base.findIdentical(htmlNs, obj.namespaceURI) >= 0; }
Finding DOM node attributes
An undocumented MochiKit.DOM.attributeArray function already exists in 1.4, but it seems to include all attributes regardless if they are specified in the source HTML/XML or not. Perhaps the function below is a better implementation? See also #288 for discussion.
/** * Returns an array with DOM node attribute name and value pairs. * The name and value pairs are also stored in arrays with two * elements. * * @param {Object} node the HTML DOM node * * @return {Array} an array containing attribute name and value * pairs (as arrays) */ MochiKit.DOM.attributeArray = function(node) { var res = []; node = MochiKit.DOM.getElement(node); for (var i = 0; node != null && i < node.attributes.length; i++) { var a = node.attributes[i]; if (a.specified) { res.push([a.name, a.value]); } } return res; }
Creating nodes with non-default namespace
When creating DOM nodes with non-default namespaces, the usual MochiKit.DOM.createDOM and MochiKit.DOM.createDOMFunc functions are not sufficient. This is a problem when inlining SVG content for example. Below follows two new functions that work in similar ways, but provides additional support for namespaces and required function arguments.
/** * Creates a DOM node with a namespace. * * @param {String} ns the DOM namespace * @param {String} tag the DOM tag name * @param {Object} [attrs] the node attributes, or null for none * @param {Object} [...] the nodes or text to add as children * * @return {Object} the DOM node created */ MochiKit.DOM.createDOMExt = function(ns, tag, attrs/*, ...*/) { var doc = MochiKit.DOM.currentDocument(); var node = (ns) ? doc.createElementNS(ns, tag) : doc.createElement(tag); MochiKit.DOM.updateNodeAttributes(node, attrs); var children = MochiKit.Base.extend([], arguments, 3); MochiKit.DOM.appendChildNodes(node, children); return node; } /** * Returns a function for creating a specific kind of DOM nodes. The * returned function will optionally require a sequence of non-null * arguments that will be added as attributes to the node creation. * The returned function will otherwise work similar to the * createDOM() function, taking attributes and child nodes. * * @param {String} ns the DOM namespace, or null for HTML * @param {String} tag the DOM tag name * @param {Array} [args] the array with required arguments, or null * for no required arguments * @param {Object} [attrs] the default node attributes, or null for * none * @param {Object} [...] the default nodes or text to add as children * * @return {Function} the function that creates the DOM nodes */ MochiKit.DOM.createDOMFuncExt = function(ns, tag, args, attrs/*, ...*/) { args = args || []; attrs = attrs || {}; var children = MochiKit.Base.extend([], arguments, 4); return function(/*arg1, ..., argN, attrs, ...*/) { var myAttrs = MochiKit.Base.update({}, attrs); for (var pos = 0; pos < args.length; pos++) { if (arguments[pos] == null) { throw new Error("Argument '" + args[pos] + "' cannot be null"); } myAttrs[args[pos]] = arguments[pos]; } MochiKit.Base.update(myAttrs, arguments[args.length]); var myChildren = MochiKit.Base.extend([], children); MochiKit.Base.extend(myChildren, arguments, args.length + 1); return MochiKit.DOM.createDOMExt(ns, tag, myAttrs, myChildren); } }
