JQuery Like getElement Method in YUI

One of the many features that I like about jQuery is the ability to pass in CSS selectors and HTML attributes into the jQuery for retrieving DOM nodes. YUI has methods for fetching elements by their className, but not by their HTML attributes, such as type or name. Today, well cover a method I wrote that supports fetching elements by tagName, className, and/or a collection of attributes. The method getElements returns all nodes that match any of the tagNames and any of the classNames and every type of attribute (you can have multiple attribute types, such as name and type) provided:

Example 1: getElements

Dom.getElements = function(tagNames, classNames, attributes, root) {
	var elems = [],
		nodes = [];
	// does the root exist, then use it
	if (root) {
		root = Dom.get(root);
		// if no root node, then no children; return empty array
		if (! root) {return [];}
	// otherwise use document
	else {
		root = $doc;

	// there are tag names provided
	if (tagNames && tagNames.length) {
		tagNames.batch(function(tag) {
			elems = elems.concat(Array.get(root.getElementsByTagName(tag)));
	// use wildcard * for tag name
	else {
		elems = Array.get(root.getElementsByTagName(*)).slice(1);
		if (! elems.length && root.all) {elems = root.all;} // checking for IE < 6

	if (classNames || (attributes && attributes.length)) {
		var classFn = function(node) {return node;},
			attrFn = function(node) {return node;};

		// update the classFn to look at a list of classes
		if (classNames && classNames.length) {
			classFn = function(node) {
				return classNames.batch(function(klass) {
					if (Dom.hasClass(node, klass)) {
						return node;

		// update the attrFn to look at a list of attributes
		if (attributes && attributes.length) {
			var attributeMap = {},
				attributeTypes = [];

			// iterate on the attributes and create iterables
			attributes.batch(function(attr) {
				if (! attributeMap[attr.attributeName]) {
					attributeMap[attr.attributeName] = [];


			attrFn = function(node) {
				var isMatch = true;

				// iterate on the attribute types to find keys for the attribute value map
				attributeTypes.batch(function(attributeName) {
					// iterate on the values and compare with node
					var n = attributeMap[attributeName].batch(function(attributeValue) {
						if (attributeValue === node[attributeName]) {return node;}

					// node did not match, stop iterating, since this is not a match
					if (! n) {
						isMatch = false;
						return true;

				return isMatch ? node : null;

		// iterate on the nodes found by tags
		elems.batch(function(el) {
			if (classFn(el) && attrFn(el)) {nodes.push(el);}

		return nodes;
	else {
		return elems;

First, I have shortened "YAHOO.util.Dom" to Dom and this function required my Array.js to convert DOM node collections into arrays. The parameters for getElemetns are four optional values: an array of tag name strings, an array or class name strings, an array of attribute objects {attributeName, attributeValue}, and the root node to search the DOM from. If the root node is not provided, then getElements will start searching from the document, but if an invalid root node is provided, then getElements will return an empty array. If tag names are provided, then getElements concatenates the results of each into an array (elems), but will otherwise default to wildcard (*), retrieving all sub-nodes.

When class names or attributes are provided, getElements will iterate on the elems array and create a new array nodes containing the elements that matched the class and attribute values. However, if neither is provided, we simply return the elems array. To determine if the classes and/or attributes are present on a node, we create functions that take a node as a parameter and return that node when the value matches. The class name function will test to see if the node contains any of the classes in the array. The attribute function first creates a map of values for each type of attribute that is provided, then iterates through them, only returning true when the node matches at least 1 attribute of each type.

Here is an example that starts searching for input and a tags, with either class button or link, and has the name submit:

Example 2: Using getElements

Dom.getElements([input, a], [button, link], [{attributeName: name, attributeValue: submit}], myRootNode);